aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2021-10-04 17:26:30 +0200
committerFlorian Dold <florian@dold.me>2021-10-04 17:26:30 +0200
commita4b3524111d176d7374db1340f0d996eecfadff1 (patch)
treed402af36a6a3b402baf4e9c49f35a593b9d057f3
parent0e60574acfb81d6bc279aac469e023e5c689a21d (diff)
downloadanastasis-a4b3524111d176d7374db1340f0d996eecfadff1.tar.gz
anastasis-a4b3524111d176d7374db1340f0d996eecfadff1.zip
allow external reducer binary to process actions
m---------contrib/gana0
-rw-r--r--src/reducer/anastasis_api_redux.c120
2 files changed, 120 insertions, 0 deletions
diff --git a/contrib/gana b/contrib/gana
Subproject 3b638032297cfed132912dfe82a1c47033eff03 Subproject 90aee6a0ba5c9e3e52074a2dabe1b3b9421ad16
diff --git a/src/reducer/anastasis_api_redux.c b/src/reducer/anastasis_api_redux.c
index 851be12..796e60d 100644
--- a/src/reducer/anastasis_api_redux.c
+++ b/src/reducer/anastasis_api_redux.c
@@ -1480,6 +1480,116 @@ typedef struct ANASTASIS_ReduxAction *
1480 ANASTASIS_ActionCallback cb, 1480 ANASTASIS_ActionCallback cb,
1481 void *cb_cls); 1481 void *cb_cls);
1482 1482
1483/**
1484 * Dummy cleanup function.
1485 */
1486static void
1487dummy_cleanup (void *cls)
1488{
1489 GNUNET_assert (0);
1490}
1491
1492
1493/**
1494 * Handle an action using an external reducer, i.e.
1495 * by shelling out to another process.
1496 */
1497static struct ANASTASIS_ReduxAction *
1498redux_action_external (const char *ext_reducer,
1499 const json_t *state,
1500 const char *action,
1501 const json_t *arguments,
1502 ANASTASIS_ActionCallback cb,
1503 void *cb_cls)
1504{
1505 struct ANASTASIS_ReduxAction *act = NULL;
1506 int pipefd_stdout[2];
1507 int pipefd_stdin[2];
1508 pid_t pid = 0;
1509 int status;
1510 FILE *reducer_stdout;
1511 FILE *reducer_stdin;
1512 json_t *next_state;
1513
1514 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1515 "Using external reducer '%s'\n",
1516 ext_reducer);
1517
1518 GNUNET_assert (0 == pipe (pipefd_stdout));
1519 GNUNET_assert (0 == pipe (pipefd_stdin));
1520 pid = fork ();
1521 if (pid == 0)
1522 {
1523 /* Child */
1524
1525 char *arg_str = json_dumps (arguments, JSON_COMPACT);
1526
1527 close (pipefd_stdout[0]);
1528 dup2 (pipefd_stdout[1], STDOUT_FILENO);
1529
1530 close (pipefd_stdin[1]);
1531 dup2 (pipefd_stdin[0], STDIN_FILENO);
1532
1533 /* Unset environment variable, otherwise anastasis-reducer
1534 would recursively shell out to itself. */
1535 unsetenv ("ANASTASIS_EXTERNAL_REDUCER");
1536
1537 execlp (ext_reducer,
1538 ext_reducer,
1539 "-a",
1540 arg_str,
1541 action,
1542 NULL);
1543 GNUNET_assert (0);
1544 }
1545
1546 /* Only parent reaches here */
1547
1548 close (pipefd_stdout[1]);
1549 close (pipefd_stdin[0]);
1550
1551 reducer_stdout = fdopen (pipefd_stdout[0],
1552 "r");
1553 reducer_stdin = fdopen (pipefd_stdin[1],
1554 "w");
1555
1556 GNUNET_assert (0 == json_dumpf (state,
1557 reducer_stdin,
1558 JSON_COMPACT));
1559
1560 GNUNET_assert (0 == fclose (reducer_stdin));
1561 reducer_stdin = NULL;
1562
1563 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1564 "Wrote old state to reducer stdin.\n");
1565
1566 next_state = json_loadf (reducer_stdout,
1567 0,
1568 NULL);
1569
1570 /* FIXME: report error instead! */
1571 GNUNET_assert (NULL != next_state);
1572
1573 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1574 "Waiting for external reducer to terminate.\n");
1575 GNUNET_assert (0 == fclose (reducer_stdout));
1576 reducer_stdout = NULL;
1577 waitpid (pid, &status, 0);
1578
1579 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1580 "External reducer finished with exit status '%d'\n",
1581 status);
1582
1583 act = GNUNET_new (struct ANASTASIS_ReduxAction);
1584 /* Callback is called immediately, cleanup must never be called */
1585 act->cleanup = &dummy_cleanup;
1586
1587 cb (cb_cls,
1588 TALER_EC_NONE,
1589 next_state);
1590 return act;
1591}
1592
1483 1593
1484struct ANASTASIS_ReduxAction * 1594struct ANASTASIS_ReduxAction *
1485ANASTASIS_redux_action (const json_t *state, 1595ANASTASIS_redux_action (const json_t *state,
@@ -1540,6 +1650,16 @@ ANASTASIS_redux_action (const json_t *state,
1540 const char *s = json_string_value (json_object_get (state, 1650 const char *s = json_string_value (json_object_get (state,
1541 "backup_state")); 1651 "backup_state"));
1542 enum ANASTASIS_GenericState gs; 1652 enum ANASTASIS_GenericState gs;
1653 const char *ext_reducer = getenv ("ANASTASIS_EXTERNAL_REDUCER");
1654
1655 /* If requested, handle action with external reducer, used for testing. */
1656 if (NULL != ext_reducer)
1657 return redux_action_external (ext_reducer,
1658 state,
1659 action,
1660 arguments,
1661 cb,
1662 cb_cls);
1543 1663
1544 if (NULL == s) 1664 if (NULL == s)
1545 { 1665 {