summaryrefslogtreecommitdiff
path: root/src/cstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/cstore')
-rw-r--r--src/cstore/cstore-c.cpp13
-rw-r--r--src/cstore/cstore-c.h3
-rw-r--r--src/cstore/cstore.cpp60
-rw-r--r--src/cstore/cstore.hpp5
-rw-r--r--src/cstore/unionfs/cstore-unionfs.cpp28
-rw-r--r--src/cstore/unionfs/cstore-unionfs.hpp1
6 files changed, 105 insertions, 5 deletions
diff --git a/src/cstore/cstore-c.cpp b/src/cstore/cstore-c.cpp
index fd818a5..c835efe 100644
--- a/src/cstore/cstore-c.cpp
+++ b/src/cstore/cstore-c.cpp
@@ -143,6 +143,19 @@ cstore_cfg_path_get_effective_value(void *handle, const char *path_comps[],
return NULL;
}
+int
+cstore_unmark_cfg_path_changed(void *handle, const char *path_comps[],
+ int num_comps)
+{
+ if (handle) {
+ vector<string> vs;
+ _get_str_vec(vs, path_comps, num_comps);
+ Cstore *cs = (Cstore *) handle;
+ return (cs->unmarkCfgPathChanged(vs) ? 1 : 0);
+ }
+ return 0;
+}
+
char **
cstore_path_string_to_path_comps(const char *path_str, int *num_comps)
{
diff --git a/src/cstore/cstore-c.h b/src/cstore/cstore-c.h
index a2ad844..4f33672 100644
--- a/src/cstore/cstore-c.h
+++ b/src/cstore/cstore-c.h
@@ -38,6 +38,9 @@ char *cstore_cfg_path_get_effective_value(void *handle,
const char *path_comps[],
int num_comps);
+int cstore_unmark_cfg_path_changed(void *handle, const char *path_comps[],
+ int num_comps);
+
/* the following are internal APIs for the library. they can only be used
* during cstore operations since they operate on "current" paths constructed
* by the operations.
diff --git a/src/cstore/cstore.cpp b/src/cstore/cstore.cpp
index 3cd0649..f146cb0 100644
--- a/src/cstore/cstore.cpp
+++ b/src/cstore/cstore.cpp
@@ -1096,10 +1096,19 @@ void
Cstore::cfgPathGetDeletedValues(const vector<string>& path_comps,
vector<string>& dvals)
{
+ cfgPathGetDeletedValuesDA(path_comps, dvals, false);
+}
+
+// same as above but DA
+void
+Cstore::cfgPathGetDeletedValuesDA(const vector<string>& path_comps,
+ vector<string>& dvals,
+ bool include_deactivated)
+{
vector<string> ovals;
vector<string> nvals;
- if (!cfgPathGetValues(path_comps, ovals, true)
- || !cfgPathGetValues(path_comps, nvals, false)) {
+ if (!cfgPathGetValuesDA(path_comps, ovals, true, include_deactivated)
+ || !cfgPathGetValuesDA(path_comps, nvals, false, include_deactivated)) {
return;
}
map<string, bool> dmap;
@@ -1189,16 +1198,24 @@ Cstore::cfgPathGetChildNodesStatusDA(const vector<string>& path_comps,
*
* for "added" state, can't use cfgPathAdded() since it's not DA.
*
+ * for "changed" state, can't use cfgPathChanged() since it's not DA.
+ *
* deleted ones already handled above.
*/
if (!cfg_path_exists(ppath, true, true)
&& cfg_path_exists(ppath, false, true)) {
cmap[work_nodes[i]] = C_NODE_STATUS_ADDED;
- } else if (cfgPathChanged(ppath)) {
- cmap[work_nodes[i]] = C_NODE_STATUS_CHANGED;
} else {
- cmap[work_nodes[i]] = C_NODE_STATUS_STATIC;
+ SAVE_PATHS;
+ append_cfg_path(ppath);
+ if (marked_changed()) {
+ cmap[work_nodes[i]] = C_NODE_STATUS_CHANGED;
+ } else {
+ cmap[work_nodes[i]] = C_NODE_STATUS_STATIC;
+ }
+ RESTORE_PATHS;
}
+
ppath.pop_back();
}
}
@@ -1746,6 +1763,23 @@ Cstore::unmarkCfgPathDeactivated(const vector<string>& path_comps)
* note: if a node is changed, all of its ancestors are also considered
* changed.
* return true if successful. otherwise return false.
+ *
+ * the original backend implementation only uses the "changed" marker at
+ * "root" to indicate whether the whole config has changed. for the rest
+ * of the config hierarchy, the original implementation treated all nodes
+ * that are present in the unionfs "changes only" directory as "changed".
+ *
+ * this worked until the introduction of "deactivate". since deactivated
+ * nodes are also present in the "changes only" directory, the backend
+ * treat them as "changed". on the other hand, deleted nodes don't appear
+ * in "changes only", so they are _not_ treated as "changed". this creates
+ * problems in various parts of the backend.
+ *
+ * the new CLI backend/library marks all changed nodes explicitly, and the
+ * "changed" status depends on such markers. note that the actual marking
+ * is done by the low-level implementation, so it does not have to be done
+ * as a "file marker" as long as the low-level implementation can correctly
+ * answer the "changed" query for a given path.
*/
bool
Cstore::markCfgPathChanged(const vector<string>& path_comps)
@@ -1774,6 +1808,22 @@ Cstore::markCfgPathChanged(const vector<string>& path_comps)
return true;
}
+/* unmark "changed" status of specified path in working config.
+ * this is used, e.g., at the end of "commit" to reset a subtree.
+ * note: unmarking a node means all of its descendants are also unmarked,
+ * i.e., they become "unchanged".
+ * return true if successful. otherwise return false.
+ */
+bool
+Cstore::unmarkCfgPathChanged(const vector<string>& path_comps)
+{
+ SAVE_PATHS;
+ append_cfg_path(path_comps);
+ bool ret = unmark_changed_with_descendants();
+ RESTORE_PATHS;
+ return ret;
+}
+
////// protected functions
void
diff --git a/src/cstore/cstore.hpp b/src/cstore/cstore.hpp
index 492462e..4b07fab 100644
--- a/src/cstore/cstore.hpp
+++ b/src/cstore/cstore.hpp
@@ -144,6 +144,7 @@ public:
virtual bool inSession() = 0;
// common
bool markCfgPathChanged(const vector<string>& path_comps);
+ bool unmarkCfgPathChanged(const vector<string>& path_comps);
// XXX load
//bool unmarkCfgPathDeactivatedDescendants(const vector<string>& path_comps);
@@ -240,6 +241,9 @@ public:
void cfgPathGetDeletedChildNodesDA(const vector<string>& path_comps,
vector<string>& cnodes,
bool include_deactivated = true);
+ void cfgPathGetDeletedValuesDA(const vector<string>& path_comps,
+ vector<string>& dvals,
+ bool include_deactivated = true);
void cfgPathGetChildNodesStatusDA(const vector<string>& path_comps,
map<string, string>& cmap);
@@ -303,6 +307,7 @@ private:
virtual bool mark_deactivated() = 0;
virtual bool unmark_deactivated() = 0;
virtual bool unmark_deactivated_descendants() = 0;
+ virtual bool unmark_changed_with_descendants() = 0;
virtual bool mark_changed() = 0;
virtual bool remove_comment() = 0;
virtual bool set_comment(const string& comment) = 0;
diff --git a/src/cstore/unionfs/cstore-unionfs.cpp b/src/cstore/unionfs/cstore-unionfs.cpp
index 860d553..7f14483 100644
--- a/src/cstore/unionfs/cstore-unionfs.cpp
+++ b/src/cstore/unionfs/cstore-unionfs.cpp
@@ -749,6 +749,34 @@ UnionfsCstore::unmark_deactivated_descendants()
return ret;
}
+/* remove all "changed" markers under the current work path. this is used,
+ * e.g., at the end of "commit" to reset a subtree.
+ */
+bool
+UnionfsCstore::unmark_changed_with_descendants()
+{
+ try {
+ vector<b_fs::path> markers;
+ b_fs::recursive_directory_iterator di(get_work_path());
+ for (; di != b_fs::recursive_directory_iterator(); ++di) {
+ if (!b_fs_is_regular(di->path())
+ || di->path().filename() != C_MARKER_CHANGED) {
+ // not marker
+ continue;
+ }
+ markers.push_back(di->path());
+ }
+ for (size_t i = 0; i < markers.size(); i++) {
+ b_fs::remove(markers[i]);
+ }
+ } catch (...) {
+ output_internal("failed to unmark changed with descendants [%s]\n",
+ get_work_path().file_string().c_str());
+ return false;
+ }
+ return true;
+}
+
bool
UnionfsCstore::mark_changed()
{
diff --git a/src/cstore/unionfs/cstore-unionfs.hpp b/src/cstore/unionfs/cstore-unionfs.hpp
index 9e49064..bff4844 100644
--- a/src/cstore/unionfs/cstore-unionfs.hpp
+++ b/src/cstore/unionfs/cstore-unionfs.hpp
@@ -158,6 +158,7 @@ private:
bool mark_deactivated();
bool unmark_deactivated();
bool unmark_deactivated_descendants();
+ bool unmark_changed_with_descendants();
bool mark_changed();
bool remove_comment();
bool set_comment(const string& comment);