static CfgNode * _get_commit_other_node(CfgNode *cfg1, CfgNode *cfg2, const Cpath& cur_path) { string name, value; bool not_tag_node, is_value, is_leaf_typeless; vector<CfgNode *> rcnodes1, rcnodes2; cnode::cmp_non_leaf_nodes(cfg1, cfg2, rcnodes1, rcnodes2, not_tag_node, is_value, is_leaf_typeless, name, value); if (!cfg1) { return _create_commit_cfg_node(*cfg2, cur_path, COMMIT_STATE_ADDED); } else if (!cfg2) { return _create_commit_cfg_node(*cfg1, cur_path, COMMIT_STATE_DELETED); } CfgNode *cn = _create_commit_cfg_node(*cfg1, cur_path, COMMIT_STATE_UNCHANGED); for (size_t i = 0; i < rcnodes1.size(); i++) { CfgNode *cnode = getCommitTree(rcnodes1[i], rcnodes2[i], cn->getCommitPath()); if (cnode) { cn->addChildNode(cnode); } } if (cn->numChildNodes() < 1) { delete cn; return NULL; } return cn; }
static void _set_node_commit_path(CfgNode& node, const Cpath &p, bool recursive) { node.setCommitPath(p, node.isValue(), node.getValue(), node.getName()); if (recursive) { for (size_t i = 0; i < node.numChildNodes(); i++) { _set_node_commit_path(*(node.childAt(i)), node.getCommitPath(), recursive); } } }
/* execute the specified type of actions on the specified "multi" node (i.e., * multi-value leaf node) during commit. act is one of "delete_act", * "update_act", and "syntax_act", representing the different processing * passes. * * see comment for _exec_node_actions() above about clist. */ static bool _exec_multi_node_actions(Cstore& cs, const CfgNode& node, vtw_act_type act, CommittedPathListT *clist = NULL) { if (!node.isMulti()) { // fail if this is called with a non-multi node OUTPUT_USER("_exec_multi_node_actions() called with non-multi[%s]\n", node.getCommitPath().to_string().c_str()); return false; } const vtw_def *def = node.getDef(); Cpath pcomps(node.getCommitPath()); if (clist) { CommitState s = node.getCommitState(); if (s == COMMIT_STATE_ADDED || s == COMMIT_STATE_DELETED) { /* for multi-value leaf node, add the node itself to the * "committed list" if it is added/deleted. */ tr1::shared_ptr<Cpath> ppdisp(new Cpath(pcomps)); clist->push_back(CommittedPathT(s, ppdisp)); } } for (size_t i = 0; i < _get_num_commit_multi_values(node); i++) { CommitState s = _get_commit_multi_state_at(node, i); if (s == COMMIT_STATE_UNCHANGED) { // nop for unchanged value continue; } string v = _get_commit_multi_value_at(node, i); auto_ptr<char> at_str(strdup(v.c_str())); tr1::shared_ptr<Cpath> pdisp(new Cpath(pcomps)); pdisp->push(v); if (clist) { // add the value to the committed list clist->push_back(CommittedPathT(s, pdisp)); continue; } if (act == syntax_act) { // syntax pass if (s != COMMIT_STATE_ADDED) { continue; } if (!_exec_tmpl_actions(cs, s, at_str.get(), pcomps, *(pdisp.get()), node, syntax_act, def)) { return false; } } else { //// delete or update pass // begin if (!_exec_tmpl_actions(cs, s, at_str.get(), pcomps, *(pdisp.get()), node, begin_act, def)) { return false; } /* note that for CHANGED value we need to do BOTH a delete AND a * create. this is the fix for bug 5460. more information in later * comment about bug 5460. */ if (act == delete_act) { // delete pass if (s == COMMIT_STATE_DELETED || s == COMMIT_STATE_CHANGED) { if (!_exec_tmpl_actions(cs, s, at_str.get(), pcomps, *(pdisp.get()), node, delete_act, def)) { return false; } } } else { // update pass if (s == COMMIT_STATE_ADDED || s == COMMIT_STATE_CHANGED) { if (!_exec_tmpl_actions(cs, s, at_str.get(), pcomps, *(pdisp.get()), node, create_act, def)) { return false; } } } // end if (!_exec_tmpl_actions(cs, s, at_str.get(), pcomps, *(pdisp.get()), node, end_act, def)) { return false; } } } return true; }
/* execute the specified type of actions on the specified node. * * note that if the "committed list" clist is specified, no action will be * performed except adding the node to the committed list (if needed). */ static bool _exec_node_actions(Cstore& cs, CfgNode& node, vtw_act_type act, CommittedPathListT *clist = NULL) { if (node.isMulti()) { // fail if this is called with a multi node OUTPUT_USER("_exec_node_actions() called with multi[%s]\n", node.getCommitPath().to_string().c_str()); return false; } CommitState s = node.getCommitState(); if (s == COMMIT_STATE_DELETED && node.commitChildDeleteFailed()) { return false; } bool nop = false; if (!node.getActions(act)) { // no actions => success nop = true; } auto_ptr<char> at_str; Cpath pcomps(node.getCommitPath()); tr1::shared_ptr<Cpath> pdisp(new Cpath(pcomps)); bool add_parent_to_committed = false; if (node.isLeaf()) { // single-value node if (s == COMMIT_STATE_CHANGED) { if (node.commitValueBefore() == node.commitValueAfter()) { // value didn't change (only "default" status), so nop nop = true; } at_str.reset(strdup(node.commitValueAfter().c_str())); } else { if (s == COMMIT_STATE_ADDED || s == COMMIT_STATE_DELETED) { // add parent to "committed list" if it's added/deleted add_parent_to_committed = true; } at_str.reset(strdup(node.getValue().c_str())); } pdisp->push(at_str.get()); } else if (node.isValue()) { // tag value at_str.reset(strdup(node.getValue().c_str())); pcomps.pop(); // paths need to be at the "node" level } else { // typeless node at_str.reset(strdup(node.getName().c_str())); } if (clist) { /* note that even though every "tag value" will be added to the * "committed list" here, simply adding the corresponding "tag node" * here does not work. * * basically there are three scenarios for a tag node: * (1) in both active and working * i.e., tag node itself is unchanged => doesn't need to be added * to committed list since "committed query" will check for this * condition first. * (2) only in working * i.e., all tag values are being added so tag node itself is also * being added. in this case, tag node must be considered * "committed" after the first tag value has been processed * successfully. * (3) only in active * i.e., all tag values are being deleted so is tag node itself. * in this case, tag node must be considered "committed" only * after all tag values have been processed successfully. * * cases (2) and (3) cannot be handled here since they depend on the * processing order and outcome of siblings of tag values. therefore, * tag node will never be added to the committed list, and the * "committed query" function will need to handle tag nodes as special * case. */ if (add_parent_to_committed) { tr1::shared_ptr<Cpath> ppdisp(new Cpath(pcomps)); clist->push_back(CommittedPathT(s, ppdisp)); } clist->push_back(CommittedPathT(s, pdisp)); return true; } if (nop) { // nothing to do return true; } if (!_exec_tmpl_actions(cs, s, at_str.get(), pcomps, *(pdisp.get()), node, act, node.getDef())) { if (act == create_act) { _set_node_commit_create_failed(node); } return false; } return true; }