CLI: Improved and renamed show statistics -> show memory command
Fixed shared yang-spec reference count
This commit is contained in:
parent
25e1bade8f
commit
8d05432e98
4 changed files with 178 additions and 59 deletions
|
|
@ -1816,7 +1816,20 @@ clixon_cli2cbuf(clixon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! CLI callback show statistics
|
/*! CLI callback show memory statistics (and numbers)
|
||||||
|
*
|
||||||
|
* mempry in KiB
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] cvv Vector of cli string and instantiated variables
|
||||||
|
* @param[in] argv Arguments given at the callback: [(cli|backend) [detail]]
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
* where level means:
|
||||||
|
* <null> : Show mounts and summary clispec
|
||||||
|
* cli : Show mounts and summary clispec
|
||||||
|
* cli detail : Show mounts and per parse-tree clispec
|
||||||
|
* backend : Show summary mem
|
||||||
|
* backend detail : Per-module
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_show_statistics(clixon_handle h,
|
cli_show_statistics(clixon_handle h,
|
||||||
|
|
@ -1827,42 +1840,141 @@ cli_show_statistics(clixon_handle h,
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
cxobj *xret = NULL;
|
cxobj *xret = NULL;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
cg_var *cv;
|
char *what = NULL;
|
||||||
int modules = 0;
|
int detail = 0;
|
||||||
pt_head *ph;
|
pt_head *ph;
|
||||||
parse_tree *pt;
|
parse_tree *pt;
|
||||||
uint64_t nr = 0;
|
uint64_t nr;
|
||||||
size_t sz = 0;
|
uint64_t tnr;
|
||||||
|
size_t sz;
|
||||||
|
size_t tsz;
|
||||||
|
yang_stmt *yspec;
|
||||||
|
yang_stmt *yspec1;
|
||||||
|
yang_stmt *yspec2;
|
||||||
|
yang_stmt *ymnt;
|
||||||
|
cvec *cvv1 = NULL;
|
||||||
|
cvec *cvv2;
|
||||||
|
cg_var *cv;
|
||||||
|
cg_var *cv2;
|
||||||
|
cg_var *cv3;
|
||||||
|
|
||||||
if (argv != NULL && cvec_len(argv) != 1){
|
if (argv != NULL && (cvec_len(argv) < 1 || cvec_len(argv) > 2)){
|
||||||
clixon_err(OE_PLUGIN, EINVAL, "Expected arguments: [modules]");
|
clixon_err(OE_PLUGIN, EINVAL, "Expected arguments: [(cli|backend) [detail]]");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
yspec = clicon_dbspec_yang(h);
|
||||||
if (argv){
|
if (argv){
|
||||||
cv = cvec_i(argv, 0);
|
cv = cvec_i(argv, 0);
|
||||||
modules = (strcmp(cv_string_get(cv), "modules") == 0);
|
what = cv_string_get(cv);
|
||||||
|
if (strcmp(what, "cli") != 0 && strcmp(what, "backend") != 0){
|
||||||
|
clixon_err(OE_PLUGIN, EINVAL, "Unexpected argument: %s, expected: cli|backend", what);
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (cvec_len(argv) > 1 &&
|
||||||
|
(cv = cvec_i(argv, 1)) != NULL){
|
||||||
|
if (strcmp(cv_string_get(cv), "detail") != 0){
|
||||||
|
clixon_err(OE_PLUGIN, EINVAL, "Unexpected argument: %s, expected: detail",
|
||||||
|
cv_string_get(cv));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
detail = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
what = "cli";
|
||||||
if ((cb = cbuf_new()) == NULL){
|
if ((cb = cbuf_new()) == NULL){
|
||||||
clixon_err(OE_PLUGIN, errno, "cbuf_new");
|
clixon_err(OE_PLUGIN, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (strcmp(what, "cli") == 0) {
|
||||||
/* CLI */
|
/* CLI */
|
||||||
cligen_output(stdout, "CLI:\n");
|
if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT"))
|
||||||
|
cligen_output(stdout, "%-25s %-8s %-10s %-8s %-8s\n", "YANG", "Nodes#", "Mem(KiB)", "Refs", "Pointer");
|
||||||
|
else
|
||||||
|
cligen_output(stdout, "%-25s %-8s %-10s\n", "YANG", "Nodes#", "Mem(KiB)");
|
||||||
|
nr = 0; sz = 0;
|
||||||
|
if (yang_stats(yspec, &nr, &sz) < 0)
|
||||||
|
goto done;
|
||||||
|
tnr = nr;
|
||||||
|
tsz = sz;
|
||||||
|
cligen_output(stdout, "%-25s %-8" PRIu64 " %-8zu\n", "Top-level", nr, sz/1024);
|
||||||
|
if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")) {
|
||||||
|
if (yang_mount_yspec2ymnt(yspec, &cvv1) < 0)
|
||||||
|
goto done;
|
||||||
|
cv = NULL;
|
||||||
|
while ((cv = cvec_each(cvv1, cv)) != NULL) {
|
||||||
|
ymnt = cv_void_get(cv);
|
||||||
|
if ((cvv2 = yang_cvec_get(ymnt)) != NULL){
|
||||||
|
cv2 = NULL;
|
||||||
|
while ((cv2 = cvec_each(cvv2, cv2)) != NULL) {
|
||||||
|
yspec1 = cv_void_get(cv2);
|
||||||
|
nr = 0; sz = 0;
|
||||||
|
if (yang_stats(yspec1, &nr, &sz) < 0)
|
||||||
|
goto done;
|
||||||
|
/* check if not duplicate */
|
||||||
|
cv3 = NULL;
|
||||||
|
while ((cv3 = cvec_each(cvv2, cv3)) != NULL) {
|
||||||
|
if (cv2 == cv3)
|
||||||
|
break;
|
||||||
|
yspec2 = cv_void_get(cv3);
|
||||||
|
if (yspec1 == yspec2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cv2 != cv3){
|
||||||
|
cligen_output(stdout, "%s \\\n", cv_name_get(cv2));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tnr += nr;
|
||||||
|
tsz += sz;
|
||||||
|
if (strlen(cv_name_get(cv2)) > 25){
|
||||||
|
cligen_output(stdout, "%s \\\n", cv_name_get(cv2));
|
||||||
|
cligen_output(stdout, "%-25s %-8" PRIu64 " %-10zu %-8d %-8p\n",
|
||||||
|
"",
|
||||||
|
nr, sz/1024,
|
||||||
|
yang_ref_get(yspec1), ymnt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cligen_output(stdout, "%-25s %-8" PRIu64 " %-10zu %-8d %-8p\n",
|
||||||
|
cv_name_get(cv2),
|
||||||
|
nr, sz/1024,
|
||||||
|
yang_ref_get(yspec1), ymnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cligen_output(stdout, "%-25s %-8" PRIu64 " %-8zu\n", "YANG Total", tnr, tsz/1024);
|
||||||
|
}
|
||||||
|
if (strcmp(what, "cli") == 0) {
|
||||||
|
cligen_output(stdout, "%-25s %-8s %-8s\n", "CLIspecs", "Nodes#", "Mem(KiB)");
|
||||||
|
tnr = 0;
|
||||||
|
tsz = 0;
|
||||||
ph = NULL;
|
ph = NULL;
|
||||||
while ((ph = cligen_ph_each(cli_cligen(h), ph)) != NULL) {
|
while ((ph = cligen_ph_each(cli_cligen(h), ph)) != NULL) {
|
||||||
if ((pt = cligen_ph_parsetree_get(ph)) == NULL)
|
if ((pt = cligen_ph_parsetree_get(ph)) == NULL)
|
||||||
continue;
|
continue;
|
||||||
nr = 0; sz = 0;
|
nr = 0; sz = 0;
|
||||||
pt_stats(pt, &nr, &sz);
|
pt_stats(pt, &nr, &sz);
|
||||||
cligen_output(stdout, "%s: nr=%" PRIu64 " size:%zu\n",
|
tnr += nr;
|
||||||
cligen_ph_name_get(ph), nr, sz);
|
tsz += sz;
|
||||||
|
if (detail){
|
||||||
|
if (strlen(cligen_ph_name_get(ph)) > 25){
|
||||||
|
cligen_output(stdout, "%s \\\n", cligen_ph_name_get(ph));
|
||||||
|
cligen_output(stdout, "%-25s %-8" PRIu64 " %-8zu\n", "", nr, sz/1024);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
cligen_output(stdout, "%-25s %-8" PRIu64 " %-8zu\n", cligen_ph_name_get(ph), nr, sz/1024);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cligen_output(stdout, "%-25s %-8" PRIu64 " %-8zu\n", "CLIspec Total", tnr, tsz/1024);
|
||||||
|
}
|
||||||
|
if (strcmp(what, "backend") == 0) {
|
||||||
/* Backend */
|
/* Backend */
|
||||||
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
cprintf(cb, ">");
|
cprintf(cb, ">");
|
||||||
cprintf(cb, "<stats xmlns=\"%s\">", CLIXON_LIB_NS);
|
cprintf(cb, "<stats xmlns=\"%s\">", CLIXON_LIB_NS);
|
||||||
if (modules)
|
if (detail)
|
||||||
cprintf(cb, "<modules>true</modules>");
|
cprintf(cb, "<modules>true</modules>");
|
||||||
cprintf(cb, "</stats>");
|
cprintf(cb, "</stats>");
|
||||||
cprintf(cb, "</rpc>");
|
cprintf(cb, "</rpc>");
|
||||||
|
|
@ -1872,12 +1984,14 @@ cli_show_statistics(clixon_handle h,
|
||||||
clixon_err_netconf(h, OE_NETCONF, 0, xerr, "Get configuration");
|
clixon_err_netconf(h, OE_NETCONF, 0, xerr, "Get configuration");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
fprintf(stdout, "Backend:\n");
|
cligen_output(stdout, "Backend (nr nodes, size of mem\n");
|
||||||
if (clixon_xml2file(stdout, xml_child_i(xret, 0), 0, 1, NULL, cligen_output, 0, 1) < 0)
|
if (clixon_xml2file(stdout, xml_child_i(xret, 0), 0, 1, NULL, cligen_output, 0, 1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
fprintf(stdout, "CLI:\n");
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cvv1)
|
||||||
|
cvec_free(cvv1);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (cb)
|
if (cb)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
See also the separate
|
See also the separate
|
||||||
[clixon-examples](https://github.com/clicon/clixon-examples) repo
|
[clixon-examples](https://github.com/clicon/clixon-examples) repo
|
||||||
|
|
||||||
The only Clixon example remaining is for internal testing:
|
The remaining Clixon example is for internal testing:
|
||||||
* [Main example](main/README.md)
|
* [Main example](main/README.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,9 +123,13 @@ show("Show a particular state of the system"){
|
||||||
yang("Show yang specs"), show_yang(); {
|
yang("Show yang specs"), show_yang(); {
|
||||||
clixon-example("Show clixon-example yang spec"), show_yang("clixon-example");
|
clixon-example("Show clixon-example yang spec"), show_yang("clixon-example");
|
||||||
}
|
}
|
||||||
statistics("Show statistics"), cli_show_statistics();{
|
memory("Show memory usage") {
|
||||||
brief, cli_show_statistics();
|
cli("Show CLI memory usage"), cli_show_statistics("cli");{
|
||||||
modules, cli_show_statistics("modules");
|
detail("Show detailed CLI memory usage"), cli_show_statistics("cli", "detail");
|
||||||
|
}
|
||||||
|
backend("Show backend memory usage"), cli_show_statistics("backend");{
|
||||||
|
detail("Show detailed backend memory usage"), cli_show_statistics("backend", "detail");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ yang_mount_set(yang_stmt *y,
|
||||||
#if 0 /* Problematic to free yang specs here, upper layers should handle it? */
|
#if 0 /* Problematic to free yang specs here, upper layers should handle it? */
|
||||||
ys_free(yspec0);
|
ys_free(yspec0);
|
||||||
#endif
|
#endif
|
||||||
|
yang_ref_dec(yspec0);
|
||||||
cv_void_set(cv, NULL);
|
cv_void_set(cv, NULL);
|
||||||
}
|
}
|
||||||
else if ((cv = yang_cvec_add(y, CGV_VOID, xpath)) == NULL)
|
else if ((cv = yang_cvec_add(y, CGV_VOID, xpath)) == NULL)
|
||||||
|
|
@ -275,6 +276,7 @@ yang_mount_set(yang_stmt *y,
|
||||||
/* tag yspec with key/xpath */
|
/* tag yspec with key/xpath */
|
||||||
yang_cv_set(yspec, cv2);
|
yang_cv_set(yspec, cv2);
|
||||||
cv_void_set(cv, yspec);
|
cv_void_set(cv, yspec);
|
||||||
|
yang_ref_inc(yspec); /* share */
|
||||||
yang_flag_set(y, YANG_FLAG_MOUNTPOINT); /* Cache value */
|
yang_flag_set(y, YANG_FLAG_MOUNTPOINT); /* Cache value */
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -424,15 +426,16 @@ int
|
||||||
yang_mount_freeall(yang_stmt *ymnt)
|
yang_mount_freeall(yang_stmt *ymnt)
|
||||||
{
|
{
|
||||||
cvec *cvv;
|
cvec *cvv;
|
||||||
cg_var *cv = NULL;
|
cg_var *cv;
|
||||||
yang_stmt *ys;
|
yang_stmt *ys;
|
||||||
|
|
||||||
cvv = yang_cvec_get(ymnt);
|
if ((cvv = yang_cvec_get(ymnt)) != NULL){
|
||||||
cv = NULL;
|
cv = NULL;
|
||||||
while ((cv = cvec_each(cvv, cv)) != NULL){
|
while ((cv = cvec_each(cvv, cv)) != NULL){
|
||||||
if ((ys = cv_void_get(cv)) != NULL)
|
if ((ys = cv_void_get(cv)) != NULL)
|
||||||
ys_free(ys);
|
ys_free(ys);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,14 +501,13 @@ yang_mount_xtop2xmnt(cxobj *xtop,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Find schema mounts - callback function for xml_apply
|
/*! Find schema mounts - callback function for yang_apply
|
||||||
*
|
*
|
||||||
* @param[in] y YANG node
|
* @param[in] yn yang node
|
||||||
* @param[in] arg cvec, if match add node
|
* @param[in] arg Argument
|
||||||
* @retval 2 Locally abort this subtree, continue with others
|
* @retval n OK, abort traversal and return to caller with "n"
|
||||||
* @retval 1 Abort, dont continue with others, return 1 to end user
|
* @retval 0 OK, continue with next
|
||||||
* @retval 0 OK, continue
|
* @retval -1 Error, abort
|
||||||
* @retval -1 Error, aborted at first error encounter, return -1 to end user
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
find_yang_schema_mounts(yang_stmt *y,
|
find_yang_schema_mounts(yang_stmt *y,
|
||||||
|
|
@ -516,7 +518,7 @@ find_yang_schema_mounts(yang_stmt *y,
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
|
|
||||||
if (yang_config(y) == 0)
|
if (yang_config(y) == 0)
|
||||||
return 2;
|
return 0;
|
||||||
if ((ret = yang_schema_mount_point(y)) < 0)
|
if ((ret = yang_schema_mount_point(y)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
|
|
@ -937,7 +939,6 @@ yang_schema_find_share(clixon_handle h,
|
||||||
if ((ret = yang_schema_cmp_kludge(h, xyanglib, xmodst)) < 0)
|
if ((ret = yang_schema_cmp_kludge(h, xyanglib, xmodst)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 1){ /* equal */
|
if (ret == 1){ /* equal */
|
||||||
yang_ref_inc(yspec1); /* share */
|
|
||||||
*yspecp = yspec1;
|
*yspecp = yspec1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue