X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftdb%2Ftest%2Fexternal-transaction.c;h=1211da9e76d5c1d54702f3725fc34e30eb8d9658;hb=9d045ca09a0b052d968e11d98540f63a8a0aa412;hp=c03dbc49f6320afd386a5e9f89a2bad936034cf8;hpb=450a9a4c70af36f3be1eb572d513ffebf25c3797;p=ccan diff --git a/ccan/tdb/test/external-transaction.c b/ccan/tdb/test/external-transaction.c index c03dbc49..1211da9e 100644 --- a/ccan/tdb/test/external-transaction.c +++ b/ccan/tdb/test/external-transaction.c @@ -7,7 +7,9 @@ #include #include #include +#include #include +#include static volatile sig_atomic_t alarmed; static void do_alarm(int signum) @@ -15,15 +17,22 @@ static void do_alarm(int signum) alarmed++; } -static int do_transaction(const char *name) +static int do_operation(enum operation op, const char *name) { TDB_DATA k = { .dptr = (void *)"a", .dsize = 1 }; TDB_DATA d = { .dptr = (void *)"b", .dsize = 1 }; - struct tdb_context *tdb = tdb_open(name, 0, 0, O_RDWR, 0); + struct tdb_context *tdb; + tdb = tdb_open(name, 0, op == OPEN_WITH_CLEAR_IF_FIRST ? + TDB_CLEAR_IF_FIRST : TDB_DEFAULT, O_RDWR, 0); if (!tdb) return -1; + if (op == OPEN || op == OPEN_WITH_CLEAR_IF_FIRST) { + tdb_close(tdb); + return 0; + } + alarmed = 0; tdb_setalarm_sigptr(tdb, &alarmed); @@ -61,7 +70,7 @@ struct agent *prepare_external_agent(void) int pid; int command[2], response[2]; struct sigaction act = { .sa_handler = do_alarm }; - char name[PATH_MAX]; + char name[1+PATH_MAX]; if (pipe(command) != 0 || pipe(response) != 0) return NULL; @@ -85,7 +94,9 @@ struct agent *prepare_external_agent(void) sigaction(SIGALRM, &act, NULL); while (read(command[0], name, sizeof(name)) != 0) { - int result = do_transaction(name); + int result; + + result = do_operation(name[0], name+1); if (write(response[1], &result, sizeof(result)) != sizeof(result)) err(1, "Writing response"); @@ -93,13 +104,17 @@ struct agent *prepare_external_agent(void) exit(0); } -/* Ask the external agent to try to do a transaction. */ -bool external_agent_transaction(struct agent *agent, const char *tdbname) +/* Ask the external agent to try to do an operation. */ +bool external_agent_operation(struct agent *agent, + enum operation op, const char *tdbname) { int res; + char string[1 + strlen(tdbname) + 1]; - if (write(agent->cmdfd, tdbname, strlen(tdbname)+1) - != strlen(tdbname)+1) + string[0] = op; + strcpy(string+1, tdbname); + + if (write(agent->cmdfd, string, sizeof(string)) != sizeof(string)) err(1, "Writing to agent"); if (read(agent->responsefd, &res, sizeof(res)) != sizeof(res)) @@ -110,3 +125,41 @@ bool external_agent_transaction(struct agent *agent, const char *tdbname) return res; } + +void external_agent_operation_start(struct agent *agent, + enum operation op, const char *tdbname) +{ + char string[1 + strlen(tdbname) + 1]; + + string[0] = op; + strcpy(string+1, tdbname); + + if (write(agent->cmdfd, string, sizeof(string)) != sizeof(string)) + err(1, "Writing to agent"); +} + +bool external_agent_operation_check(struct agent *agent, bool block, int *res) +{ + int flags = fcntl(agent->responsefd, F_GETFL); + + if (block) + fcntl(agent->responsefd, F_SETFL, flags & ~O_NONBLOCK); + else + fcntl(agent->responsefd, F_SETFL, flags | O_NONBLOCK); + + switch (read(agent->responsefd, res, sizeof(*res))) { + case sizeof(*res): + break; + case 0: + errx(1, "Agent died?"); + default: + if (!block && (errno == EAGAIN || errno == EWOULDBLOCK)) + return false; + err(1, "%slocking reading from agent", block ? "B" : "Non-b"); + } + + if (*res > 1) + errx(1, "Agent returned %u\n", *res); + + return true; +}