1 #include "external-transaction.h"
11 #include <ccan/tdb/tdb.h>
12 #include <ccan/tap/tap.h>
14 static volatile sig_atomic_t alarmed;
15 static void do_alarm(int signum)
20 static int do_operation(enum operation op, const char *name)
22 TDB_DATA k = { .dptr = (void *)"a", .dsize = 1 };
23 TDB_DATA d = { .dptr = (void *)"b", .dsize = 1 };
24 struct tdb_context *tdb;
26 tdb = tdb_open(name, 0, op == OPEN_WITH_CLEAR_IF_FIRST ?
27 TDB_CLEAR_IF_FIRST : TDB_DEFAULT, O_RDWR, 0);
31 if (op == OPEN || op == OPEN_WITH_CLEAR_IF_FIRST) {
37 tdb_setalarm_sigptr(tdb, &alarmed);
40 if (tdb_transaction_start(tdb) != 0)
43 if (tdb_store(tdb, k, d, 0) != 0) {
44 tdb_transaction_cancel(tdb);
49 if (tdb_transaction_commit(tdb) == 0) {
64 int cmdfd, responsefd;
67 /* Do this before doing any tdb stuff. Return handle, or NULL. */
68 struct agent *prepare_external_agent(void)
71 int command[2], response[2];
72 struct sigaction act = { .sa_handler = do_alarm };
73 char name[1+PATH_MAX];
75 if (pipe(command) != 0 || pipe(response) != 0)
83 struct agent *agent = malloc(sizeof(*agent));
87 agent->cmdfd = command[1];
88 agent->responsefd = response[0];
94 sigaction(SIGALRM, &act, NULL);
96 while (read(command[0], name, sizeof(name)) != 0) {
99 result = do_operation(name[0], name+1);
100 if (write(response[1], &result, sizeof(result))
102 err(1, "Writing response");
107 /* Ask the external agent to try to do an operation. */
108 bool external_agent_operation(struct agent *agent,
109 enum operation op, const char *tdbname)
112 char string[1 + strlen(tdbname) + 1];
115 strcpy(string+1, tdbname);
117 if (write(agent->cmdfd, string, sizeof(string)) != sizeof(string))
118 err(1, "Writing to agent");
120 if (read(agent->responsefd, &res, sizeof(res)) != sizeof(res))
121 err(1, "Reading from agent");
124 errx(1, "Agent returned %u\n", res);
129 void external_agent_operation_start(struct agent *agent,
130 enum operation op, const char *tdbname)
132 char string[1 + strlen(tdbname) + 1];
135 strcpy(string+1, tdbname);
137 if (write(agent->cmdfd, string, sizeof(string)) != sizeof(string))
138 err(1, "Writing to agent");
141 bool external_agent_operation_check(struct agent *agent, bool block, int *res)
143 int flags = fcntl(agent->responsefd, F_GETFL);
146 fcntl(agent->responsefd, F_SETFL, flags & ~O_NONBLOCK);
148 fcntl(agent->responsefd, F_SETFL, flags | O_NONBLOCK);
150 switch (read(agent->responsefd, res, sizeof(*res))) {
154 errx(1, "Agent died?");
156 if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
158 err(1, "%slocking reading from agent", block ? "B" : "Non-b");
162 errx(1, "Agent returned %u\n", *res);