]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb/test/external-transaction.c
tdb: rewrite external agent for testing.
[ccan] / ccan / tdb / test / external-transaction.c
diff --git a/ccan/tdb/test/external-transaction.c b/ccan/tdb/test/external-transaction.c
deleted file mode 100644 (file)
index 23d8471..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-#include "external-transaction.h"
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <err.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <string.h>
-#include <errno.h>
-#include <ccan/tdb/tdb.h>
-#include <ccan/tdb/tdb_private.h>
-#include <ccan/tap/tap.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-static struct tdb_context *tdb;
-
-static volatile sig_atomic_t alarmed;
-static void do_alarm(int signum)
-{
-       alarmed++;
-}
-
-static void taplog(struct tdb_context *tdb,
-                  enum tdb_debug_level level,
-                  const char *fmt, ...)
-{
-       va_list ap;
-       char line[200];
-
-       va_start(ap, fmt);
-       vsprintf(line, fmt, ap);
-       va_end(ap);
-
-       diag("external: %s", line);
-}
-
-static int do_operation(enum operation op, const char *name)
-{
-       struct tdb_logging_context logctx = { taplog, NULL };
-
-       TDB_DATA k = { .dptr = (void *)"a", .dsize = 1 };
-       TDB_DATA d = { .dptr = (void *)"b", .dsize = 1 };
-
-       if (op <= KEEP_OPENED) {
-               tdb = tdb_open_ex(name, 0, op == OPEN_WITH_CLEAR_IF_FIRST ?
-                                 TDB_CLEAR_IF_FIRST : TDB_DEFAULT, O_RDWR, 0,
-                                 &logctx, NULL);
-               if (!tdb)
-                       return -1;
-       }
-
-       if (op == KEEP_OPENED) {
-               return 0;
-       } else if (op == OPEN || op == OPEN_WITH_CLEAR_IF_FIRST || op == CLOSE) {
-               tdb_close(tdb);
-               tdb = NULL;
-               return 1;
-       } else if (op == STORE_KEEP_OPENED) {
-               if (tdb_store(tdb, k, d, 0) != 0)
-                       return -2;
-               return 1;
-       } else if (op == FETCH_KEEP_OPENED) {
-               TDB_DATA ret;
-               ret = tdb_fetch(tdb, k);
-               if (ret.dptr == NULL) {
-                       if (tdb_error(tdb) == TDB_ERR_NOEXIST)
-                               return 1;
-                       return -3;
-               }
-               if (ret.dsize != 1 || *(char *)ret.dptr != 'b')
-                       return -4;
-               free(ret.dptr);
-               return 1;
-       } else if (op == CHECK_KEEP_OPENED) {
-               return tdb_check(tdb, NULL, 0) == 0;
-       } else if (op == NEEDS_RECOVERY_KEEP_OPENED) {
-               return tdb_needs_recovery(tdb);
-       }
-
-       alarmed = 0;
-       tdb_setalarm_sigptr(tdb, &alarmed);
-
-       alarm(1);
-       if (tdb_transaction_start(tdb) != 0)
-               goto maybe_alarmed;
-
-       alarm(0);
-       if (tdb_store(tdb, k, d, 0) != 0) {
-               tdb_transaction_cancel(tdb);
-               tdb_close(tdb);
-               tdb = NULL;
-               return -2;
-       }
-
-       if (tdb_transaction_commit(tdb) == 0) {
-               tdb_delete(tdb, k);
-               if (op != TRANSACTION_KEEP_OPENED) {
-                       tdb_close(tdb);
-                       tdb = NULL;
-               }
-               return 1;
-       }
-
-       tdb_delete(tdb, k);
-maybe_alarmed:
-       if (op != TRANSACTION_KEEP_OPENED) {
-               tdb_close(tdb);
-               tdb = NULL;
-       }
-       if (alarmed)
-               return 0;
-       return -3;
-}
-
-struct agent {
-       int cmdfd, responsefd;
-};
-
-/* Do this before doing any tdb stuff.  Return handle, or NULL. */
-struct agent *prepare_external_agent(void)
-{
-       int pid, ret;
-       int command[2], response[2];
-       struct sigaction act = { .sa_handler = do_alarm };
-       char name[1+PATH_MAX];
-
-       if (pipe(command) != 0 || pipe(response) != 0)
-               return NULL;
-
-       pid = fork();
-       if (pid < 0)
-               return NULL;
-
-       if (pid != 0) {
-               struct agent *agent = malloc(sizeof(*agent));
-
-               close(command[0]);
-               close(response[1]);
-               agent->cmdfd = command[1];
-               agent->responsefd = response[0];
-               return agent;
-       }
-
-       close(command[1]);
-       close(response[0]);
-       sigaction(SIGALRM, &act, NULL);
-
-       while ((ret = read(command[0], name, sizeof(name))) > 0) {
-               int result;
-
-               result = do_operation(name[0], name+1);
-               if (write(response[1], &result, sizeof(result))
-                   != sizeof(result))
-                       err(1, "Writing response");
-       }
-       diag("external: read %i: %s", ret, strerror(errno));
-       exit(0);
-}
-
-/* Ask the external agent to try to do an operation. */
-int external_agent_operation(struct agent *agent,
-                             enum operation op, const char *tdbname)
-{
-       int res;
-       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");
-
-       if (read(agent->responsefd, &res, sizeof(res)) != sizeof(res))
-               err(1, "Reading from agent");
-
-       if (res > 1)
-               errx(1, "Agent returned %u\n", res);
-
-       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;
-}