Hi,
I do not believe there is any benefit in calling cdb_get_modifications_iter() from your iter() function on MOP_VALUE_SET.
Full main() and print_modifications() from a modified iter_c example for reference:
static void print_modifications(confd_tag_value_t *val, int nvals,
struct confd_cs_node *start_node,
int start_indent)
{
int i, indent = start_indent;
struct confd_cs_node root, *pnode = start_node, *node;
char tmpbuf[BUFSIZ];
char *tmp;
for (i=0; i<nvals; i++) {
if (indent == start_indent && start_node == NULL) {
node = confd_find_cs_root(CONFD_GET_TAG_NS(&val[i]));
root.children = node;
pnode = &root;
}
switch (CONFD_GET_TAG_VALUE(&val[i])->type) {
case C_XMLBEGIN:
tmp = "begin";
if (pnode != NULL)
pnode = confd_find_cs_node_child(pnode, val[i].tag);
break;
case C_XMLBEGINDEL:
tmp = "begin-deleted";
if (pnode != NULL)
pnode = confd_find_cs_node_child(pnode, val[i].tag);
break;
case C_XMLEND:
tmp = "end";
if (pnode != NULL)
pnode = pnode->parent;
indent -= 2;
break;
case C_XMLTAG:
tmp = "created";
break;
case C_NOEXISTS:
tmp = "deleted";
break;
default:
if (pnode == NULL ||
(node = confd_find_cs_node_child(pnode, val[i].tag)) == NULL ||
confd_val2str(node->info.type, CONFD_GET_TAG_VALUE(&val[i]),
tmpbuf, sizeof(tmpbuf)) == CONFD_ERR) {
confd_pp_value(tmpbuf, sizeof(tmpbuf),
CONFD_GET_TAG_VALUE(&val[i]));
if(node != NULL) {
char tmpbuf2[BUFSIZ];
confd_pp_value(tmpbuf2, BUFSIZ, node->info.defval);
printf("%*s%s default=%s", indent, "", "", tmpbuf2);
}
}
tmp = tmpbuf;
}
fprintf(stderr, "%*s%s %s\n", indent, "",
confd_hash2str(CONFD_GET_TAG_TAG(&val[i])), tmp);
switch (CONFD_GET_TAG_VALUE(&val[i])->type) {
case C_XMLBEGIN:
case C_XMLBEGINDEL:
indent += 2;
break;
default:
break;
}
}
}
static void free_tag_values(confd_tag_value_t *tv, int n)
{
int i;
for (i = 0; i < n; i++) {
confd_free_value(CONFD_GET_TAG_VALUE(&tv[i]));
}
}
static enum cdb_iter_ret do_iter(confd_hkeypath_t *kp,
enum cdb_iter_op op,
confd_value_t *oldv,
confd_value_t *newv,
void *state)
{
char tmppath[BUFSIZ];
char tmpbuf1[BUFSIZ], tmpbuf2[BUFSIZ];
char *opstr = "";
int cdbsock = *((int *)state);
confd_pp_kpath(tmppath, BUFSIZ, kp);
switch (op) {
case MOP_CREATED: opstr = "created"; break;
case MOP_DELETED: opstr = "deleted"; break;
case MOP_VALUE_SET: opstr = "set"; break;
case MOP_MODIFIED: opstr = "modified"; break;
default: opstr = "?";
}
tmpbuf1[0] = tmpbuf2[0] = 0;
if (oldv) confd_pp_value(tmpbuf1, BUFSIZ, oldv);
if (newv) confd_pp_value(tmpbuf2, BUFSIZ, newv);
fprintf(stderr, "%s %s", tmppath, opstr);
if (oldv || newv) {
fprintf(stderr, " (%s -> %s)", tmpbuf1, tmpbuf2);
}
fprintf(stderr, "\n");
if (kp->v[0][0].type != C_XMLTAG &&
(op == MOP_CREATED || op == MOP_MODIFIED)) {
int nvals;
confd_tag_value_t *val;
int rc;
/* a created or modified list entry */
rc = cdb_get_modifications_iter(cdbsock, CDB_GET_MODS_INCLUDE_LISTS,
&val, &nvals);
if (CONFD_OK != rc) {
fprintf(stderr, "cdb_get_modifications_iter:%s\n",
confd_strerror(confd_errno));
exit(confd_errno);
}
fprintf(stderr, " get_modifications_iter:\n");
print_modifications(val, nvals, confd_find_cs_node(kp, kp->len), 2);
free_tag_values(val, nvals);
free(val);
}
return ITER_RECURSE;
}
int main(int argc, char **argv)
{
struct sockaddr_in addr;
int c, status, subsock, sock;
int headpoint;
enum confd_debug_level dbgl = CONFD_TRACE;
char *confd_addr = "127.0.0.1";
int confd_port = CONFD_PORT;
while ((c = getopt(argc, argv, "dta:p:")) != EOF) {
switch (c) {
case 'd': dbgl = CONFD_DEBUG; break;
case 's': dbgl = CONFD_SILENT; break;
case 'a': confd_addr = optarg; break;
case 'p': confd_port = atoi(optarg); break;
}
}
addr.sin_addr.s_addr = inet_addr(confd_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(confd_port);
confd_init(argv[0], stderr, dbgl);
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
confd_fatal("%s: Failed to create socket", argv[0]);
if (confd_load_schemas((struct sockaddr*)&addr,
sizeof (struct sockaddr_in)) != CONFD_OK)
confd_fatal("%s: Failed to load schemas from confd\n", argv[0]);
if (cdb_connect(sock, CDB_DATA_SOCKET, (struct sockaddr *)&addr,
sizeof(struct sockaddr_in)) != CONFD_OK)
confd_fatal("%s: Failed to connect to ConfD", argv[0]);
if ((subsock = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
confd_fatal("Failed to open socket\n");
if (cdb_connect(subsock, CDB_SUBSCRIPTION_SOCKET, (struct sockaddr*)&addr,
sizeof (struct sockaddr_in)) < 0)
confd_fatal("Failed to cdb_connect() to confd \n");
/* setup subscription point */
if ((status = cdb_subscribe(subsock, 3, root__ns, &headpoint,
"/root/NodeB/RFHead"))
!= CONFD_OK) {
confd_fatal("Terminate: subscribe %d\n", status);
}
if (cdb_subscribe_done(subsock) != CONFD_OK)
confd_fatal("cdb_subscribe_done() failed");
while (1) {
int status;
struct pollfd set[1];
set[0].fd = subsock;
set[0].events = POLLIN;
set[0].revents = 0;
if (poll(&set[0], sizeof(set)/sizeof(*set), -1) < 0) {
if (errno != EINTR) {
perror("Poll failed:");
continue;
}
}
if (set[0].revents & POLLIN) {
int sub_points[1];
int reslen;
if ((status = cdb_read_subscription_socket(subsock,
&sub_points[0],
&reslen)) != CONFD_OK) {
confd_fatal("terminate sub_read: %d\n", status);
}
if (reslen > 0) {
fprintf(stderr, "*** Config updated \n");
cdb_diff_iterate(subsock, sub_points[0], do_iter,
ITER_WANT_PREV, (void*)&subsock);
}
if ((status = cdb_sync_subscription_socket(subsock,
CDB_DONE_PRIORITY))
!= CONFD_OK) {
confd_fatal("failed to sync subscription: %d\n", status);
}
}
}
}