1 #include "external-transaction.h"
11 #include <ccan/tdb/tdb.h>
12 #include <ccan/tap/tap.h>
15 static volatile sig_atomic_t alarmed;
16 static void do_alarm(int signum)
21 static int do_operation(enum operation op, const char *name)
23 TDB_DATA k = { .dptr = (void *)"a", .dsize = 1 };
24 TDB_DATA d = { .dptr = (void *)"b", .dsize = 1 };
25 struct tdb_context *tdb;
27 tdb = tdb_open(name, 0, op == OPEN_WITH_CLEAR_IF_FIRST ?
28 TDB_CLEAR_IF_FIRST : TDB_DEFAULT, O_RDWR, 0);
32 if (op == OPEN || op == OPEN_WITH_CLEAR_IF_FIRST) {
38 tdb_setalarm_sigptr(tdb, &alarmed);
41 if (tdb_transaction_start(tdb) != 0)
44 if (tdb_store(tdb, k, d, 0) != 0) {
45 tdb_transaction_cancel(tdb);
50 if (tdb_transaction_commit(tdb) == 0) {
65 int cmdfd, responsefd;
68 /* Do this before doing any tdb stuff. Return handle, or NULL. */
69 struct agent *prepare_external_agent(void)
72 int command[2], response[2];
73 struct sigaction act = { .sa_handler = do_alarm };
74 char name[1+PATH_MAX];
76 if (pipe(command) != 0 || pipe(response) != 0)
84 struct agent *agent = malloc(sizeof(*agent));
88 agent->cmdfd = command[1];
89 agent->responsefd = response[0];
95 sigaction(SIGALRM, &act, NULL);
97 while (read(command[0], name, sizeof(name)) != 0) {
100 result = do_operation(name[0], name+1);
101 if (write(response[1], &result, sizeof(result))
103 err(1, "Writing response");
108 /* Ask the external agent to try to do an operation. */
109 bool external_agent_operation(struct agent *agent,
110 enum operation op, const char *tdbname)
113 char string[1 + strlen(tdbname) + 1];
116 strcpy(string+1, tdbname);
118 if (write(agent->cmdfd, string, sizeof(string)) != sizeof(string))
119 err(1, "Writing to agent");
121 if (read(agent->responsefd, &res, sizeof(res)) != sizeof(res))
122 err(1, "Reading from agent");
125 errx(1, "Agent returned %u\n", res);
130 void external_agent_operation_start(struct agent *agent,
131 enum operation op, const char *tdbname)
133 char string[1 + strlen(tdbname) + 1];
136 strcpy(string+1, tdbname);
138 if (write(agent->cmdfd, string, sizeof(string)) != sizeof(string))
139 err(1, "Writing to agent");
142 bool external_agent_operation_check(struct agent *agent, bool block, int *res)
144 int flags = fcntl(agent->responsefd, F_GETFL);
147 fcntl(agent->responsefd, F_SETFL, flags & ~O_NONBLOCK);
149 fcntl(agent->responsefd, F_SETFL, flags | O_NONBLOCK);
151 switch (read(agent->responsefd, res, sizeof(*res))) {
155 errx(1, "Agent died?");
157 if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
159 err(1, "%slocking reading from agent", block ? "B" : "Non-b");
163 errx(1, "Agent returned %u\n", *res);