diff options
Diffstat (limited to 'src/commit/commit-algorithm.hpp')
-rw-r--r-- | src/commit/commit-algorithm.hpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/commit/commit-algorithm.hpp b/src/commit/commit-algorithm.hpp new file mode 100644 index 0000000..3bc89a7 --- /dev/null +++ b/src/commit/commit-algorithm.hpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2011 Vyatta, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _COMMIT_ALGORITHM_HPP_ +#define _COMMIT_ALGORITHM_HPP_ +#include <vector> +#include <string> +#include <queue> +#include <tr1/memory> + +#include <cnode/cnode-util.hpp> +#include <cstore/cpath.hpp> +#include <cstore/ctemplate.hpp> + +// forward decl +namespace cnode { +class CfgNode; +} +namespace cstore { +class Cstore; +} + +namespace commit { + +using namespace cnode; +using namespace cstore; + +enum CommitState { + COMMIT_STATE_UNCHANGED, + COMMIT_STATE_ADDED, + COMMIT_STATE_DELETED, + COMMIT_STATE_CHANGED +}; + +enum CommitTreeTraversalOrder { + PRE_ORDER, + POST_ORDER +}; + +class CommitData { +public: + CommitData(); + virtual ~CommitData() {} + + // setters + void setCommitState(CommitState s); + void setCommitPath(const Cpath& p, bool is_val, const std::string& val, + const std::string& name); + void setCommitMultiValues(const std::vector<std::string>& values, + const std::vector<CommitState>& states); + void setCommitValue(const std::string& val1, const std::string& val2, + bool def1, bool def2); + void setCommitChildDeleteFailed(); + void setCommitCreateFailed(); + void setCommitSubtreeChanged(); + + // getters + CommitState getCommitState() const; + Cpath getCommitPath() const; + size_t numCommitMultiValues() const; + std::string commitMultiValueAt(size_t idx) const; + CommitState commitMultiStateAt(size_t idx) const; + std::string commitValueBefore() const; + std::string commitValueAfter() const; + bool commitChildDeleteFailed() const; + bool commitCreateFailed() const; + bool commitSubtreeChanged() const; + + // for tmpl stuff + void setTmpl(std::tr1::shared_ptr<cstore::Ctemplate> def); + std::tr1::shared_ptr<cstore::Ctemplate> getTmpl() const; + const vtw_def *getDef() const; + unsigned int getPriority() const; + void setPriority(unsigned int p); + const vtw_node *getActions(vtw_act_type act, bool raw = false) const; + bool isBeginEndNode() const; + +private: + std::tr1::shared_ptr<cstore::Ctemplate> _def; + Cpath _commit_path; + CommitState _commit_state; + std::vector<std::string> _commit_values; + std::vector<CommitState> _commit_values_states; + std::pair<std::string, std::string> _commit_value; + std::pair<bool, bool> _commit_default; + bool _commit_create_failed; + bool _commit_child_delete_failed; + bool _commit_subtree_changed; +}; + +class PrioNode : public TreeNode<PrioNode> { +public: + PrioNode(CfgNode *n); + ~PrioNode() {} + + CfgNode *getCfgNode(); + unsigned int getPriority() const; + CommitState getCommitState() const; + Cpath getCommitPath() const; + bool parentCreateFailed() const; + bool succeeded() const; + bool hasSubtreeFailure() const; + bool hasSubtreeSuccess() const; + + void setCfgParent(CfgNode *p); + void setSucceeded(bool succeeded); + void setSubtreeFailure(); + void setSubtreeSuccess(); + +#if 0 + // XXX testing + void print(size_t lvl) { +#define INDENT for(size_t xyz = 0; xyz < lvl; xyz++) { printf(" "); }; + INDENT; + if (_node) { + printf("[%s]\n", _node->getCommitPath().to_string().c_str()); + } else { + printf("[---]\n"); + } + INDENT; printf("|cp[%s]\n", + (_cfg_parent + ? _cfg_parent->getCommitPath().to_string().c_str() + : NULL)); + if (_node) { + INDENT; printf("======\n"); + _node->rprint(lvl); + INDENT; printf("======\n"); + } +#undef INDENT + } + void rprint(size_t lvl) { + print(lvl); + for (size_t i = 0; i < numChildNodes(); i++) { + childAt(i)->rprint(lvl + 1); + } + } +#endif + +private: + CfgNode *_node; + CfgNode *_cfg_parent; + bool _succeeded; + bool _subtree_failure; + bool _subtree_success; +}; + +template<bool for_delete> struct PrioNodeCmp { + inline bool operator()(PrioNode *a, PrioNode *b) { + return _is_after(a, b, Int2Type<for_delete>()); + } + + /* note: if comparing "for delete", use "<". if not for delete, use ">". + * if two nodes have the same priority, the ordering between them + * is not defined, i.e., can be either. + */ + inline bool _is_after(PrioNode *a, PrioNode *b, Int2Type<false>) { + return (a->getPriority() > b->getPriority()); + } + inline bool _is_after(PrioNode *a, PrioNode *b, Int2Type<true>) { + return (a->getPriority() < b->getPriority()); + } +}; + +typedef std::priority_queue<PrioNode *, std::vector<PrioNode *>, + PrioNodeCmp<false> > PrioQueueT; +typedef std::priority_queue<PrioNode *, std::vector<PrioNode *>, + PrioNodeCmp<true> > DelPrioQueueT; + +typedef std::pair<CommitState, std::tr1::shared_ptr<Cpath> > + CommittedPathT; +typedef std::vector<CommittedPathT> CommittedPathListT; + +// exported functions +CfgNode *getCommitTree(CfgNode *cfg1, CfgNode *cfg2, const Cpath& cur_path); +bool isCommitPathEffective(Cstore& cs, const Cpath& pcomps, + std::tr1::shared_ptr<Ctemplate> def, + bool in_active, bool in_working); +bool doCommit(Cstore& cs, CfgNode& cfg1, CfgNode& cfg2); + +} // namespace commit + +#endif /* _COMMIT_ALGORITHM_HPP_ */ + |