示例#1
0
/********************************************************************
* FUNCTION rpc_err_clean_record
*
* Clean an rpc_err_rec_t struct
*
* INPUTS:
*   err == rpc_err_rec_t struct to clean
* RETURNS:
*   none
*********************************************************************/
void
    rpc_err_clean_record (rpc_err_rec_t  *err)
{
    rpc_err_info_t  *errinfo;

#ifdef DEBUG
    if (!err) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    err->error_res = NO_ERR;
    err->error_id = RPC_ERR_NONE;
    err->error_type = NCX_LAYER_NONE;
    err->error_severity = RPC_ERR_SEV_NONE;
    err->error_tag = NULL;
    err->error_app_tag = NULL;
    if (err->error_path) {
        m__free(err->error_path);
        err->error_path = NULL;
    }
    if (err->error_message) {
        m__free(err->error_message);
    }
    err->error_message_lang = NULL;

    while (!dlq_empty(&err->error_info)) {
        errinfo = (rpc_err_info_t *)dlq_deque(&err->error_info);
        rpc_err_free_info(errinfo);
    }

}  /* rpc_err_clean_record */
示例#2
0
文件: rpc.c 项目: 0xDEC0DE8/OpenYuma
/********************************************************************
* FUNCTION rpc_free_msg
*
* Free all the memory used by the specified rpc_msg_t
*
* INPUTS:
*   msg == rpc_msg_t to clean and delete
* RETURNS:
*   none
*********************************************************************/
void rpc_free_msg (rpc_msg_t *msg)
{
    if (!msg) {
        return;
    }

    xml_msg_clean_hdr(&msg->mhdr);

    //msg->rpc_in_attrs = NULL;
    //msg->rpc_method = NULL;
    //msg->rpc_agt_state = 0;

    /* clean input parameter set */
    if (msg->rpc_input) {
        val_free_value(msg->rpc_input);
    }
    //msg->rpc_user1 = NULL;
    //msg->rpc_user2 = NULL;

    //msg->rpc_filter.op_filtyp = OP_FILTER_NONE;
    //msg->rpc_filter.op_filter = NULL;
    //msg->rpc_datacb = NULL;

    /* clean data queue */
    while (!dlq_empty(&msg->rpc_dataQ)) {
        val_value_t *val = (val_value_t *)dlq_deque(&msg->rpc_dataQ);
        val_free_value(val);
    }

    m__free(msg);

} /* rpc_free_msg */
示例#3
0
/********************************************************************
* FUNCTION yangapi_clean_keyvalQ
*
* Free all the YANGAPI keyval
*
* INPUTS:
*   rcb == control block to use
* RETURNS:
*   none
*********************************************************************/
void
    yangapi_clean_keyvalQ (yangapi_cb_t *rcb)
{
    while (!dlq_empty(&rcb->keyvalQ)) {
        yangapi_keyval_t *kv = (yangapi_keyval_t *)
            dlq_deque(&rcb->keyvalQ);
        yangapi_free_keyval(kv);
    }
}  /* yangapi_clean_keyvalQ */
示例#4
0
/********************************************************************
* FUNCTION mgr_not_clean_msgQ
*
* Clean the msg Q of mgr_not_msg_t entries
*
* INPUTS:
*   msgQ == Q of entries to free; the Q itself is not freed
*
* RETURNS:
*   none
*********************************************************************/
void
    mgr_not_clean_msgQ (dlq_hdr_t *msgQ)
{
    mgr_not_msg_t *msg;

#ifdef DEBUG
    if (!msgQ) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    msg = (mgr_not_msg_t *)dlq_deque(msgQ);
    while (msg) {
        mgr_not_free_msg(msg);
        msg = (mgr_not_msg_t *)dlq_deque(msgQ);
    }

} /* mgr_not_clean_msgQ */
示例#5
0
/********************************************************************
* FUNCTION mgr_rpc_clean_requestQ
*
* Clean the request Q of mgr_rpc_req_t entries
*
* INPUTS:
*   reqQ == Q of entries to free; the Q itself is not freed
*
* RETURNS:
*   none
*********************************************************************/
void
    mgr_rpc_clean_requestQ (dlq_hdr_t *reqQ)
{
    mgr_rpc_req_t *req;

#ifdef DEBUG
    if (!reqQ) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    req = (mgr_rpc_req_t *)dlq_deque(reqQ);
    while (req) {
        mgr_rpc_free_request(req);
        req = (mgr_rpc_req_t *)dlq_deque(reqQ);
    }

} /* mgr_rpc_clean_requestQ */
示例#6
0
/********************************************************************
* FUNCTION agt_cfg_free_transaction
*
* Clean and free a agt_cfg_transaction_t struct
*
* INPUTS:
*    txcb == transaction struct to free
*********************************************************************/
void
    agt_cfg_free_transaction (agt_cfg_transaction_t *txcb)
{
    if (txcb == NULL) {
        return;
    }

    /* clear current config txid if any */
    if (txcb->txid) {
        cfg_template_t *cfg = cfg_get_config_id(txcb->cfg_id);
        if (cfg) {
            if (cfg->cur_txid == txcb->txid) {
                log_debug3("\nClearing current txid for %s config",
                           cfg->name);
                cfg->cur_txid = 0;
            }
        }
    }

    /* clean undo queue */
    while (!dlq_empty(&txcb->undoQ)) {
        agt_cfg_undo_rec_t *undorec = (agt_cfg_undo_rec_t *)
            dlq_deque(&txcb->undoQ);
        agt_cfg_free_undorec(undorec);
    }

    /* clean audit queue */
    while (!dlq_empty(&txcb->auditQ)) {
        agt_cfg_audit_rec_t *auditrec = (agt_cfg_audit_rec_t *)
            dlq_deque(&txcb->auditQ);
        agt_cfg_free_auditrec(auditrec);
    }

    /* clean dead node queue */
    while (!dlq_empty(&txcb->deadnodeQ)) {
        agt_cfg_nodeptr_t *nodeptr = (agt_cfg_nodeptr_t *)
            dlq_deque(&txcb->deadnodeQ);
        agt_cfg_free_nodeptr(nodeptr);
    }

    m__free(txcb);

}  /* agt_cfg_free_transaction */
示例#7
0
文件: grp.c 项目: 0xDEC0DE8/OpenYuma
/********************************************************************
 * Clean a queue of grp_template_t structs
 *
 * \param que Q of grp_template_t data structures to free
 *********************************************************************/
void grp_clean_groupingQ (dlq_hdr_t *que)
{
    if (!que) {
        return;
    }

    while (!dlq_empty(que)) {
        grp_template_t *grp = (grp_template_t *)dlq_deque(que);
        grp_free_template(grp);
    }
}  /* grp_clean_groupingQ */
/********************************************************************
 * FUNCTION free_aliases
 * 
 * Free all the command aliases
 *
 *********************************************************************/
void
    free_aliases (void)
{
    dlq_hdr_t   *aliasQ = get_aliasQ();
    alias_cb_t  *alias;

    while (!dlq_empty(aliasQ)) {
        alias = (alias_cb_t *)dlq_deque(aliasQ);
        free_alias(alias);
    }

}  /* free_aliases */
/********************************************************************
 * FUNCTION yangcli_notif_cleanup
 * 
 * Cleanup this module
 *
 *********************************************************************/
void
    yangcli_notif_cleanup (void)
{
    if (yangcli_notif_init_done) {
        while (!dlq_empty(&event_cbQ)) {
            event_cb_t *cb = dlq_deque(&event_cbQ);
            free_event_cb(cb);
        }
        yangcli_notif_init_done = FALSE;
    }

}  /* yangcli_notif_cleanup */
void agt_not_queue_notification_cb_cleanup( void )
{
    if ( initialised )
    {
        agt_cb_queue_notification_set_t* cbSet;

        while ( !dlq_empty( &callbackQ ) )
        {
            cbSet = ( agt_cb_queue_notification_set_t* )dlq_deque( &callbackQ );
            free_callback_set( cbSet );
        }
        initialised = false;
    }
} /* agt_not_queue_notification_callbacks_cleanup */
示例#11
0
void agt_commit_complete_cleanup( void )
{
    if ( initialised )
    {
        agt_cb_commit_complete_set_t* cbSet;

        while ( !dlq_empty( &callbackQ ) )
        {
            cbSet = ( agt_cb_commit_complete_set_t* )dlq_deque( &callbackQ );
            free_callback_set( cbSet );
        }
        initialised = false;
    }
} /* agt_commit_complete_cleanup */
示例#12
0
文件: agt.c 项目: 0xDEC0DE8/OpenYuma
/********************************************************************
* FUNCTION clean_server_profile
* 
* Clean the server profile variables
*
* OUTPUTS:
*  *agt_profile is filled in with params of defaults
*
*********************************************************************/
static void
    clean_server_profile (void)
{
    ncx_clean_save_deviationsQ(&agt_profile.agt_savedevQ);

    while (!dlq_empty(&agt_profile.agt_commit_testQ)) {
        agt_cfg_commit_test_t *commit_test = (agt_cfg_commit_test_t *)
            dlq_deque(&agt_profile.agt_commit_testQ);
        agt_cfg_free_commit_test(commit_test);
    }

    if (agt_profile.agt_startup_txid_file) {
        m__free(agt_profile.agt_startup_txid_file);
        agt_profile.agt_startup_txid_file = NULL;
    }

} /* clean_server_profile */
示例#13
0
/********************************************************************
* FUNCTION ncx_feature_cleanup
* 
* Cleanup the ncx_feature module
*
* INPUTS:
*    none
* RETURNS:
*    none
*********************************************************************/
void
    ncx_feature_cleanup (void)
{
    feature_entry_t  *feature_entry;

    if (!feature_init_done) {
        return;
    }

    while (!dlq_empty(&feature_entryQ)) {
        feature_entry = (feature_entry_t *)dlq_deque(&feature_entryQ);
        free_feature_entry(feature_entry);
    }

    feature_init_done = FALSE;

}  /* ncx_feature_cleanup */
示例#14
0
/********************************************************************
* FUNCTION rpc_err_clean_errQ
*
* Clean all the entries from a Q of rpc_err_rec_t
*
* INPUTS:
*   errQ == Q of rpc_err_rec_t to clean
* RETURNS:
*   none
*********************************************************************/
void 
    rpc_err_clean_errQ (dlq_hdr_t *errQ)
{
    rpc_err_rec_t *err;

#ifdef DEBUG
    if (!errQ) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    /* clean error queue */
    while (!dlq_empty(errQ)) {
        err = (rpc_err_rec_t *)dlq_deque(errQ);
        rpc_err_free_record(err);
    }

} /* rpc_err_clean_errQ */
示例#15
0
/********************************************************************
* FUNCTION ncx_clean_iffeatureQ
* 
* Clean a Q of malloced ncx_iffeature_t struct
*
* INPUTS:
*    iffeatureQ == address of Q to clean
*
*********************************************************************/
void 
    ncx_clean_iffeatureQ (dlq_hdr_t *iffeatureQ)
{

    ncx_iffeature_t  *iff;

#ifdef DEBUG
    if (!iffeatureQ) {
        SET_ERROR(ERR_INTERNAL_PTR);
        return;
    }
#endif

    while (!dlq_empty(iffeatureQ)) {
        iff = (ncx_iffeature_t *)dlq_deque(iffeatureQ);
        ncx_free_iffeature(iff);
    }
    
} /* ncx_clean_iffeatureQ */
示例#16
0
/********************************************************************
* FUNCTION xml_msg_clean_hdr
*
* Clean all the memory used by the specified xml_msg_hdr_t
* but do not free the struct itself
*
* Do NOT reuse this header without calling xml_msg_init_hdr first!!!
* xml_msg_t headers were originally meant to be used
* only in other messages, but <hello> messages use the hdr
* without a wrapper message
*
* INPUTS:
*   msg == xml_msg_hdr_t to clean
* RETURNS:
*   none
*********************************************************************/
void
xml_msg_clean_hdr (xml_msg_hdr_t *msg)
{
    if (!msg) {
        return;
    }

    /* clean prefix queue */
    while (!dlq_empty(&msg->prefixQ)) {
        xmlns_pmap_t *pmap = (xmlns_pmap_t *)dlq_deque(&msg->prefixQ);
        xmlns_free_pmap(pmap);
    }

    /* clean error queue */
    rpc_err_clean_errQ(&msg->errQ);

    // this step not needed; not sure why it was added!
    msg->withdef = NCX_DEF_WITHDEF;

} /* xml_msg_clean_hdr */
示例#17
0
/********************************************************************
* FUNCTION yangapi_free_rcb
*
* Free a YANGAPI control block
*
* INPUTS:
*   rcb == Yuma REST-API control block to free
* RETURNS:
*   none
*********************************************************************/
void
    yangapi_free_rcb (yangapi_cb_t *rcb)
{

    if (rcb == NULL) {
        return;
    }

    while (!dlq_empty(&rcb->paramQ)) {
        yangapi_param_t *param = (yangapi_param_t *)dlq_deque(&rcb->paramQ);
        if (param) {
            yangapi_free_param(param);
        }
    }

    yangapi_clean_keyvalQ(rcb);

    m__free(rcb->accept);
    m__free(rcb->request_method);
    m__free(rcb->request_uri);

    xpath_free_pcb(rcb->request_xpath);
    xpath_free_result(rcb->request_xpath_result);

    xpath_free_pcb(rcb->query_select_xpath);
    xpath_free_result(rcb->query_select_xpath_result);

    xpath_free_pcb(rcb->query_test_xpath);
    xpath_free_result(rcb->query_test_xpath_result);

    m__free(rcb->content_type);
    m__free(rcb->content_length);
    m__free(rcb->if_modified_since);
    m__free(rcb->if_unmodified_since);
    m__free(rcb->if_match);
    m__free(rcb->if_none_match);

    m__free(rcb);

}  /* yangapi_free_rcb */
示例#18
0
/********************************************************************
* FUNCTION clean_undorec
*
* Clean all the memory used by the specified agt_cfg_undo_rec_t
* but do not free the struct itself
*
*  !!! The caller must free internal pointers that were malloced
*  !!! instead of copied.  This function does not check them!!!
*  
* INPUTS:
*   undo == agt_cfg_undo_rec_t to clean
*   reuse == TRUE if possible reuse
*            FALSE if this node is being freed right now
*
* RETURNS:
*   none
*********************************************************************/
static void 
    clean_undorec (agt_cfg_undo_rec_t *undo,
                   boolean reuse)
{
    if (undo->free_curnode && undo->curnode) {
        val_free_value(undo->curnode);
    }

    if (undo->curnode_clone) {
        val_free_value(undo->curnode_clone);
    }

    if (undo->newnode_marker) {
        val_free_value(undo->newnode_marker);
    }

    if (undo->curnode_marker) {
        val_free_value(undo->curnode_marker);
    }

    /* really expecting the extra_deleteQ to be empty at this point */
    while (!dlq_empty(&undo->extra_deleteQ)) {
        agt_cfg_nodeptr_t *nodeptr = (agt_cfg_nodeptr_t *)
            dlq_deque(&undo->extra_deleteQ);
        if (nodeptr && nodeptr->node) {
            val_remove_child(nodeptr->node);
            val_free_value(nodeptr->node);
        } else {
            SET_ERROR(ERR_INTERNAL_VAL);
        }
        agt_cfg_free_nodeptr(nodeptr);
    }

    if (reuse) {
        agt_cfg_init_undorec(undo);
    }

} /* clean_undorec */
示例#19
0
/********************************************************************
 * FUNCTION exit_config_mode
 * 
 * Exit the configuration mode
 *
 * INPUTS:
 *    session_cb == session control block to use
 *
 *********************************************************************/
static void
    exit_config_mode (session_cb_t *session_cb)
{
    session_cb->config_mode = FALSE;
    session_cb->config_no_active = FALSE;
    session_cb->config_edit_dirty = FALSE;
    session_cb->alt_names = session_cb->config_alt_names;
    session_cb->match_names = session_cb->config_match_names;
    m__free(session_cb->config_path);
    session_cb->config_path = NULL;
    session_cb->config_curval = NULL;
    session_cb->config_curobj = NULL;
    session_cb->config_curkey = NULL;
    val_free_value(session_cb->config_etree);
    session_cb->config_etree = NULL;
    session_cb->config_ecurval = NULL;
    while (!dlq_empty(&session_cb->config_editQ)) {
        config_edit_t *edit = (config_edit_t *)
            dlq_deque(&session_cb->config_editQ);
        free_config_edit(edit);
    }

} /* exit_config_mode */
示例#20
0
/********************************************************************
 * FUNCTION process_apply
 * (config mode input received)
 *  Handle the apply command and check if there are edits
 *  to apply to the server.  If so apply the edits.
 *
 * INPUTS:
 *    server_cb == server control block to use
 *    session_cb == session control block to use
 *
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    process_apply (server_cb_t *server_cb,
                   session_cb_t *session_cb)
{
    if (dlq_empty(&session_cb->config_editQ)) {
        if (LOGDEBUG2) {
            log_debug2("\nSkipping apply, no edits");
        }
        session_cb->config_edit_dirty = FALSE;
        return NO_ERR;
    }

    /* make a dummy config root -- it will not be used; only the child
     * nodes added to this container will be added to the <config>
     * parameter in the <edit-config> operation
     */
    val_value_t *configval = xml_val_new_root(NCX_EL_CONFIG, xmlns_nc_id());
    if (configval == NULL) {
        log_error("\nError: malloc failed");
        return ERR_INTERNAL_MEM;
    }
 
    status_t res = NO_ERR;
    boolean anyedits = FALSE;
    uint32 editcnt = dlq_count(&session_cb->config_editQ);
    
    while (!dlq_empty(&session_cb->config_editQ)) {
        config_edit_t *edit = (config_edit_t *)
            dlq_deque(&session_cb->config_editQ);

        /* compare the edit to the shadow config to see if it
         * represents any change or not   */
        boolean ischange = check_edit(session_cb, edit);

        if (ischange) {
            /** TBD: add to tree and collapse all edits!!! */
            val_add_child(edit->edit_payload, configval);
            edit->edit_payload = NULL;
            anyedits = TRUE;
        } else if (LOGDEBUG3) {
            log_debug3("\nSkipping edit due to no change:\n");
            val_dump_value(edit->edit_payload, 0);
        }
        free_config_edit(edit);
    }

    if (!anyedits) {
        val_free_value(configval);
        return NO_ERR;
    }

    if (server_cb->program_mode == PROG_MODE_SERVER) {
        if (LOGDEBUG) {
            if (editcnt == 1) {
                log_debug("\nApplying 1 edit\n");
            } else {
                log_debug("\nApplying %u edits\n", editcnt);
            }
        }
    } else {
        if (LOGINFO) {
            const xmlChar *sesname = (session_cb->session_cfg)
                ? session_cb->session_cfg->name : NCX_EL_DEFAULT;

            if (editcnt == 1) {
                log_info("\nApplying 1 edit to session '%s'\n", sesname);
            } else {
                log_info("\nApplying %u edits to session '%s'\n", editcnt,
                         sesname);
            }
        }
    }

    session_cb->command_mode = CMD_MODE_CONF_APPLY;
    session_cb->config_edit_dirty = FALSE;

    res = send_edit_config_to_server(server_cb, session_cb, NULL,
                                     configval, TRUE, session_cb->timeout,
                                     OP_DEFOP_MERGE);
    /* configval consumed no matter what! */

    return res;

}  /* process_apply */
示例#21
0
/********************************************************************
* FUNCTION y_ietf_netconf_partial_lock_partial_lock_invoke
* 
* RPC invocation phase
* All constraints have passed at this point.
* Call device instrumentation code in this function.
* 
* INPUTS:
*     see agt/agt_rpc.h for details
* 
* RETURNS:
*     error status
********************************************************************/
static status_t
    y_ietf_netconf_partial_lock_partial_lock_invoke (
        ses_cb_t *scb,
        rpc_msg_t *msg,
        xml_node_t *methnode)
{
    plock_cb_t *plcb;
    val_value_t *testval, *newval;
    xpath_result_t *result;
    xpath_resnode_t *resnode, *clearnode;
    xmlChar *pathbuff;
    cfg_template_t *running;
    status_t res;
    ncx_num_t num;

    res = NO_ERR;

    plcb = (plock_cb_t *)msg->rpc_user1;
    result = plock_get_final_result(plcb);
    running = cfg_get_config_id(NCX_CFGID_RUNNING);

    /* try to lock all the target nodes */
    for (resnode = xpath_get_first_resnode(result);
         resnode != NULL && res == NO_ERR;
         resnode = xpath_get_next_resnode(resnode)) {

        testval = xpath_get_resnode_valptr(resnode);

        res = val_set_partial_lock(testval, plcb);
        if (res != NO_ERR) {
            agt_record_error(scb,
                             &msg->mhdr,
                             NCX_LAYER_OPERATION,
                             res,
                             methnode,
                             NCX_NT_NONE,
                             NULL,
                             NCX_NT_VAL,
                             testval);
        }
    }

    /* unlock any nodes already attempted if any fail */
    if (res != NO_ERR) {
        for (clearnode = xpath_get_first_resnode(result);
             clearnode != NULL;
             clearnode = xpath_get_next_resnode(clearnode)) {

            testval = xpath_get_resnode_valptr(clearnode);

            val_clear_partial_lock(testval, plcb);
            if (clearnode == resnode) {
                return res;
            }
        }
        return res;
    }

    /* add this partial lock to the running config */
    res = cfg_add_partial_lock(running, plcb);
    if (res != NO_ERR) {
        /* should not happen since config lock state could
         * not have changed since validate callback
         */
        agt_record_error(scb,
                         &msg->mhdr,
                         NCX_LAYER_OPERATION,
                         res,
                         methnode,
                         NCX_NT_NONE,
                         NULL,
                         NCX_NT_NONE,
                         NULL);
        for (clearnode = xpath_get_first_resnode(result);
             clearnode != NULL;
             clearnode = xpath_get_next_resnode(clearnode)) {

            testval = xpath_get_resnode_valptr(clearnode);
            val_clear_partial_lock(testval, plcb);
        }
        plock_cb_free(plcb);
        return res;
    }

    /* setup return data only if lock successful
     * cache the reply instead of stream the reply
     * in case there is any error; if so; the partial
     * lock will be backed out and the dataQ cleaned
     * for an error exit; add lock-id leaf first 
     */
    msg->rpc_data_type = RPC_DATA_YANG;
    
    ncx_init_num(&num);
    num.u = plock_get_id(plcb);
    newval = xml_val_new_number
        (y_ietf_netconf_partial_lock_N_lock_id,
         val_get_nsid(msg->rpc_input),
         &num,
         NCX_BT_UINT32);
    ncx_clean_num(NCX_BT_UINT32, &num);

    if (newval == NULL) {
        res = ERR_INTERNAL_MEM;
        agt_record_error(scb, 
                         &msg->mhdr, 
                         NCX_LAYER_OPERATION, 
                         res,
                         methnode, 
                         NCX_NT_NONE, 
                         NULL, 
                         NCX_NT_NONE, 
                         NULL);
    } else {
        dlq_enque(newval, &msg->rpc_dataQ);
    }

    /* add lock-node leaf-list instance for each resnode */
    for (resnode = xpath_get_first_resnode(result);
         resnode != NULL && res == NO_ERR;
         resnode = xpath_get_next_resnode(resnode)) {

        /* Q&D method: generate the i-i string as a plain
         * string and add any needed prefixes to the global
         * prefix map for the reply message (in mhdr)
         */
        pathbuff = NULL;
        testval = xpath_get_resnode_valptr(resnode);
        res = val_gen_instance_id(&msg->mhdr, 
                                  testval,
                                  NCX_IFMT_XPATH1, 
                                  &pathbuff);
        if (res == NO_ERR) {
            /* make leaf; pass off pathbuff malloced memory */
            newval = xml_val_new_string
                (y_ietf_netconf_partial_lock_N_locked_node,
                 val_get_nsid(msg->rpc_input),
                 pathbuff);
            if (newval == NULL) {
                res = ERR_INTERNAL_MEM;
                m__free(pathbuff);
                pathbuff = NULL;
            }
        }

        if (res == NO_ERR) {
            dlq_enque(newval, &msg->rpc_dataQ);
        } else {
            agt_record_error(scb, 
                             &msg->mhdr, 
                             NCX_LAYER_OPERATION, 
                             res,
                             methnode, 
                             NCX_NT_NONE, 
                             NULL, 
                             NCX_NT_NONE, 
                             NULL);
        }
    }

    if (res != NO_ERR) {
        /* back out everything, except waste the lock ID */
        for (clearnode = xpath_get_first_resnode(result);
             clearnode != NULL;
             clearnode = xpath_get_next_resnode(clearnode)) {

            testval = xpath_get_resnode_valptr(clearnode);
            val_clear_partial_lock(testval, plcb);
        }
        cfg_delete_partial_lock(running, plock_get_id(plcb));

        /* clear any data already queued */
        while (!dlq_empty(&msg->rpc_dataQ)) {
            testval = (val_value_t *)
                dlq_deque(&msg->rpc_dataQ);
            val_free_value(testval);
        }
        msg->rpc_data_type = RPC_DATA_NONE;
    }

    return res;

} /* y_ietf_netconf_partial_lock_partial_lock_invoke */