Hi, 

I wanted to know the size of the augeas tree to calculate the memory
impact of adding indexes to tree nodes, and no function was existing for
this. aug_get is returning the size of the node set match by PATH, but
this is not the size of the tree i.e. it's not recursive. 

I would propose the attached patch to add this capability to the API. I
find that it could be useful also for sanity check in other
applications, like in a GUI, when a duplicated model must stay in sync
with the augeas tree. 

Cheer, 

Francis
>From 95cebcc676cab3a4896a16bb0899124aea3986ca Mon Sep 17 00:00:00 2001
From: Francis Giraldeau <[email protected]>
Date: Fri, 15 Oct 2010 23:44:23 -0400
Subject: [PATCH] Add function to get a subtree size

The new function aug_size returns the number of nodes in the subtree selected by PATH. It counts the number of nodes by traversing recursively the subtree.

  * Add the aug_size API function
  * Add the "size" command to augtool
  * Add unittest for aug_size
---
 src/augeas.c           |   35 +++++++++++++++++++++++++++++++++++
 src/augeas.h           |   10 ++++++++++
 src/augeas_sym.version |    5 +++++
 src/augtool.c          |   24 ++++++++++++++++++++++++
 tests/test-api.c       |   12 ++++++++++++
 5 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 25ca016..7d51720 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -173,6 +173,14 @@ void tree_store_value(struct tree *tree, char **value) {
     tree_mark_dirty(tree);
 }
 
+int tree_size(struct tree *tree) {
+    int size = 1;
+    list_for_each(c, tree->children) {
+        size += tree_size(c);
+    }
+    return size;
+}
+
 int tree_set_value(struct tree *tree, const char *value) {
     char *v = NULL;
 
@@ -1350,6 +1358,33 @@ int aug_print(const struct augeas *aug, FILE *out, const char *pathin) {
     return -1;
 }
 
+int aug_size(const struct augeas *aug, const char *path) {
+    struct pathx *p;
+    struct tree *root;
+    int r = 0;
+
+    api_entry(aug);
+
+    if (path == NULL || strlen(path) == 0) {
+        path = "/*";
+    }
+
+    p = pathx_aug_parse(aug, aug->origin, path, true);
+    ERR_BAIL(aug);
+    pathx_find_one(p, &root);
+
+    if (root != NULL)
+        r = tree_size(root);
+
+    free_pathx(p);
+
+    api_exit(aug);
+    return r;
+ error:
+    api_exit(aug);
+    return -1;
+}
+
 void aug_close(struct augeas *aug) {
     if (aug == NULL)
         return;
diff --git a/src/augeas.h b/src/augeas.h
index b4848cb..2da2cee 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -276,6 +276,16 @@ int aug_load(augeas *aug);
  */
 int aug_print(const augeas *aug, FILE *out, const char *path);
 
+/* Function: aug_size
+ *
+ * Get the number of nodes in an augeas tree.
+ *
+ * Returns:
+ * number of nodes of the tree under PATH on success, or a negative value
+ * on failure
+ */
+int aug_size(const augeas *aug, const char *path);
+
 /* Function: aug_close
  *
  * Close this Augeas instance and free any storage associated with
diff --git a/src/augeas_sym.version b/src/augeas_sym.version
index 542f5fa..64e9d1e 100644
--- a/src/augeas_sym.version
+++ b/src/augeas_sym.version
@@ -34,3 +34,8 @@ AUGEAS_0.11.0 {
     global:
       aug_setm;
 } AUGEAS_0.10.0;
+
+AUGEAS_0.12.0 {
+    global:
+        aug_size;
+} AUGEAS_0.11.0;
\ No newline at end of file
diff --git a/src/augtool.c b/src/augtool.c
index 6c8416a..3c88d01 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -770,6 +770,29 @@ static const struct command_def cmd_print_def = {
     .help = "Print entries in the tree.  If PATH is given, printing starts there,\n otherwise the whole tree is printed"
 };
 
+static void cmd_size(struct command *cmd) {
+    const char *path = arg_value(cmd, "path");
+    int size;
+
+    size = aug_size(aug, path);
+    err_check(cmd);
+    printf("tree size: %d\n", size);
+}
+
+static const struct command_opt_def cmd_size_opts[] = {
+    { .type = CMD_PATH, .name = "path", .optional = true,
+      .help = "get the number of nodes of this subtree" },
+    CMD_OPT_DEF_LAST
+};
+
+static const struct command_def cmd_size_def = {
+    .name = "size",
+    .opts = cmd_size_opts,
+    .handler = cmd_size,
+    .synopsis = "size of this subtree",
+    .help = "Print the size of this tree.  If PATH is given, returns the size of the subtree there,\n otherwise, returns the size of the whole tree"
+};
+
 static void cmd_save(struct command *cmd) {
     int r;
     r = aug_save(aug);
@@ -928,6 +951,7 @@ static const struct command_def const *commands[] = {
     &cmd_match_def,
     &cmd_mv_def,
     &cmd_print_def,
+    &cmd_size_def,
     &cmd_rm_def,
     &cmd_save_def,
     &cmd_set_def,
diff --git a/tests/test-api.c b/tests/test-api.c
index 322f4a9..e853553 100644
--- a/tests/test-api.c
+++ b/tests/test-api.c
@@ -222,6 +222,17 @@ static void testDefNodeCreateMeta(CuTest *tc) {
     aug_close(aug);
 }
 
+static void testTreeSize(CuTest *tc) {
+    int size;
+    struct augeas *aug;
+
+    aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
+    CuAssertPtrNotNull(tc, aug);
+
+    size = aug_size(aug, "/augeas/version");
+    CuAssertIntEquals(tc, 8, size);
+}
+
 int main(void) {
     char *output = NULL;
     CuSuite* suite = CuSuiteNew();
@@ -232,6 +243,7 @@ int main(void) {
     SUITE_ADD_TEST(suite, testDefVarMeta);
     SUITE_ADD_TEST(suite, testDefNodeExistingMeta);
     SUITE_ADD_TEST(suite, testDefNodeCreateMeta);
+    SUITE_ADD_TEST(suite, testTreeSize);
 
     abs_top_srcdir = getenv("abs_top_srcdir");
     if (abs_top_srcdir == NULL)
-- 
1.7.1

_______________________________________________
augeas-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/augeas-devel

Reply via email to