Hi,
Try something like this:
$ diff -u . ~/tailf/confd-6.3.1/examples.confd/intro/6-c_config/
diff -u ./Makefile /Users/tailf/confd-6.3.1/examples.confd/intro/6-c_config/Makefile
--- ./Makefile 2016-11-23 10:43:27.000000000 +0100
+++ /Users/tailf/confd-6.3.1/examples.confd/intro/6-c_config/Makefile 2017-03-19 14:55:05.000000000 +0100
@@ -44,16 +44,21 @@
SRC = hosts.c dlist.c
OBJS = $(SRC:.c=.o)
-all: hst.fxs hst.h hosts $(CDB_DIR) ssh-keydir
+SRC2 = vp1.c
+OBJS2 = $(SRC2:.c=.o)
+
+all: hst.fxs hst.h hosts vp1 $(CDB_DIR) ssh-keydir
@echo "Build complete"
hosts: $(OBJS)
$(CC) -o $@ $(OBJS) $(LIBS)
+vp1: $(OBJS2)
+ $(CC) -o $@ $(OBJS2) $(LIBS)
######################################################################
clean: iclean
- -rm -rf hst.h hosts RUNNING.ckp 2> /dev/null || true
+ -rm -rf hst.h hosts vp1 RUNNING.ckp 2> /dev/null || true
start: stop
$(CONFD) -c confd.conf $(CONFD_FLAGS)
@@ -61,7 +66,8 @@
### * In another terminal window, run queries
### (try 'make query' for an example)
### * In this window, the HOSTS confd daemon now starts:
- ./hosts $(START_FLAGS)
+ ./hosts $(START_FLAGS) -q &
+ ./vp1
######################################################################
stop:
diff -u ./hst.yang /Users/tailf/confd-6.3.1/examples.confd/intro/6-c_config/hst.yang
--- ./hst.yang 2016-11-23 10:43:27.000000000 +0100
+++ /Users/tailf/confd-6.3.1/examples.confd/intro/6-c_config/hst.yang 2017-03-19 14:42:26.000000000 +0100
@@ -16,6 +16,9 @@
list host {
key name;
max-elements 64;
+ tailf:validate vp1 {
+ tailf:dependency '.';
+ }
leaf name {
type string;
}
Only in /Users/tailf/confd-6.3.1/examples.confd/intro/6-c_config/: vp1.c
$ cat /Users//tailf/confd-6.3.1/examples.confd/intro/6-c_config/vp1.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/poll.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include "confd_lib.h"
#include "confd_dp.h"
#include "confd_maapi.h"
/* include generated ns file */
#include "hst.h"
int debuglevel = CONFD_TRACE;
static int ctlsock;
static int workersock;
static int maapi_socket;
static struct confd_daemon_ctx *dctx;
struct confd_trans_validate_cbs vcb;
struct confd_valpoint_cb valp1;
static void OK(int rval)
{
if (rval != CONFD_OK) {
fprintf(stderr, "vp1.c: error not CONFD_OK: %d : %s \n",
confd_errno, confd_lasterr());
abort();
}
}
static int init_validation(struct confd_trans_ctx *tctx)
{
OK(maapi_attach(maapi_socket, hst__ns, tctx));
confd_trans_set_fd(tctx, workersock);
return CONFD_OK;
}
static int stop_validation(struct confd_trans_ctx *tctx)
{
OK(maapi_detach(maapi_socket, tctx));
return CONFD_OK;
}
enum maapi_iter_ret iter(confd_hkeypath_t *kp,
enum maapi_iter_op op,
confd_value_t *oldv,
confd_value_t *newv,
void *state)
{
char buf[BUFSIZ];
char *opstr = "";
if (op == MOP_CREATED)
opstr = "create";
else if (op == MOP_DELETED)
opstr = "delete";
else if (op == MOP_MODIFIED)
opstr = "modif";
else if (op == MOP_VALUE_SET)
opstr = "set ";
confd_pp_kpath(buf, BUFSIZ, kp);
fprintf(stderr, "Op= %s Path= %s\n", opstr, buf);
return ITER_RECURSE;
}
static int traverse_list(struct confd_trans_ctx *tctx,
confd_hkeypath_t *keypath,
confd_value_t *newval)
{
char buf[BUFSIZ];
confd_pp_kpath(buf, BUFSIZ, keypath);
fprintf(stderr, "traverse_list path %s\n", buf);
maapi_diff_iterate(maapi_socket, tctx->thandle, iter, 0, NULL);
return CONFD_OK;
}
static int maapi_sock(int *maapi_sock)
{
struct sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(4565);
if ((*maapi_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
confd_fatal("Failed to open socket\n");
if (maapi_connect(*maapi_sock, (struct sockaddr*)&addr,
sizeof (struct sockaddr_in)) < 0)
confd_fatal("Failed to confd_connect() to confd \n");
return CONFD_OK;
}
int main(int argc, char **argv)
{
int c;
struct sockaddr_in addr;
while ((c = getopt(argc, argv, "tdps")) != -1) {
switch(c) {
case 't':
debuglevel = CONFD_TRACE;
break;
case 'd':
debuglevel = CONFD_DEBUG;
break;
case 'p':
debuglevel = CONFD_PROTO_TRACE;
break;
case 's':
debuglevel = CONFD_SILENT;
break;
}
}
confd_init("MYNAME", stderr, debuglevel);
if ((dctx = confd_init_daemon("mydaemon")) == NULL)
confd_fatal("Failed to initialize confd\n");
if ((ctlsock = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
confd_fatal("Failed to open ctlsocket\n");
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(CONFD_PORT);
OK(confd_load_schemas((struct sockaddr*)&addr,sizeof (struct sockaddr_in)));
/* Create the first control socket, all requests to */
/* create new transactions arrive here */
if (confd_connect(dctx, ctlsock, CONTROL_SOCKET,
(struct sockaddr*)&addr,
sizeof (struct sockaddr_in)) < 0) {
confd_fatal("Failed to confd_connect() to confd \n");
}
/* Also establish a workersocket, this is the most simple */
/* case where we have just one ctlsock and one workersock */
if ((workersock = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
confd_fatal("Failed to open workersocket\n");
if (confd_connect(dctx, workersock, WORKER_SOCKET,(struct sockaddr*)&addr,
sizeof (struct sockaddr_in)) < 0)
confd_fatal("Failed to confd_connect() to confd \n");
vcb.init = init_validation;
vcb.stop = stop_validation;
confd_register_trans_validate_cb(dctx, &vcb);
valp1.validate = traverse_list;
strcpy(valp1.valpoint, "vp1");
OK(confd_register_valpoint_cb(dctx, &valp1));
OK(confd_register_done(dctx));
OK(maapi_sock(&maapi_socket));
while (1) {
struct pollfd set[2];
int ret;
set[0].fd = ctlsock;
set[0].events = POLLIN;
set[0].revents = 0;
set[1].fd = workersock;
set[1].events = POLLIN;
set[1].revents = 0;
if (poll(&set[0], 2, -1) < 0) {
perror("Poll failed:");
continue;
}
if (set[0].revents & POLLIN) {
if ((ret = confd_fd_ready(dctx, ctlsock)) == CONFD_EOF) {
confd_fatal("Control socket closed\n");
} else if (ret == CONFD_ERR && confd_errno != CONFD_ERR_EXTERNAL) {
confd_fatal("Error on control socket request: %s (%d): %s\n",
confd_strerror(confd_errno), confd_errno, confd_lasterr());
}
}
if (set[1].revents & POLLIN) {
if ((ret = confd_fd_ready(dctx, workersock)) == CONFD_EOF) {
confd_fatal("Worker socket closed\n");
} else if (ret == CONFD_ERR && confd_errno != CONFD_ERR_EXTERNAL) {
confd_fatal("Error on worker socket request: %s (%d): %s\n",
confd_strerror(confd_errno), confd_errno, confd_lasterr());
}
}
}
}