Skip to content

Commit

Permalink
feat: Added process hooks for 'dehash' operations
Browse files Browse the repository at this point in the history
  • Loading branch information
mpolitzer committed Feb 21, 2024
1 parent 0694e93 commit 37718fd
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 10 deletions.
7 changes: 7 additions & 0 deletions sys-utils/libcmt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ $(ioctl_OBJDIR)io_echo: src/tests/io_echo.c $(ioctl_LIB)
$(ioctl_OBJDIR)rollup_echo: src/tests/rollup_echo.c $(ioctl_LIB)
$(TARGET_CC) $(TARGET_CFLAGS) -o $@ $^

$(ioctl_OBJDIR)dehash: src/tests/dehash.c $(ioctl_LIB)
$(TARGET_CC) $(TARGET_CFLAGS) -o $@ $^

ioctl.build: $(ioctl_LIB) $(ioctl_OBJDIR)io_echo $(ioctl_OBJDIR)rollup_echo
ioctl.install: $(ioctl_LIB)
mkdir -p $(TARGET_DESTDIR)$(TARGET_PREFIX)/lib
Expand All @@ -78,6 +81,7 @@ mock_SRC := \
src/merkle.c \
src/merkle-table.c \
src/rollup.c \
src/mock/hook.c \
src/mock/io.c

mock_OBJDIR := build/mock/
Expand All @@ -97,6 +101,9 @@ $(mock_OBJDIR)io_echo: src/tests/io_echo.c $(mock_LIB)
$(mock_OBJDIR)rollup_echo: src/tests/rollup_echo.c $(mock_LIB)
$(CC) $(CFLAGS) -o $@ $^

$(mock_OBJDIR)dehash: src/tests/dehash.c $(mock_LIB)
$(CC) $(CFLAGS) -o $@ $^

mock.build: $(mock_LIB) $(mock_OBJDIR)io_echo $(mock_OBJDIR)rollup_echo

mock.install: $(mock_LIB)
Expand Down
8 changes: 8 additions & 0 deletions sys-utils/libcmt/hook.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env lua

local line = io.read('*a')
io.stderr:write(string.format("%8s:%d req %s\n",
debug.getinfo(1).source,
debug.getinfo(1).currentline,
'>|' .. line .. '|<'))
io.write('that is all she wrote')
3 changes: 3 additions & 0 deletions sys-utils/libcmt/include/libcmt/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ typedef struct {
int output_seq;
int report_seq;
int exception_seq;

int hooks_num;
void *hooks;
} cmt_io_driver_mock_t;

/** Implementation specific cmio state. */
Expand Down
176 changes: 176 additions & 0 deletions sys-utils/libcmt/src/mock/hook.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>

#include "libcmt/io.h"

typedef struct {
char *exe;
uint16_t key;
} hook_entry_t;

static void *array_push(void **data, size_t m, size_t *n, size_t *max) {
if ((*n == *max) || (*data == NULL)) {
*max = *data == NULL ? 32 : *max * 2;
*data = realloc(*data, *max * m);
if (*data == NULL) {
perror("Failed to resize array with:");
exit(1);
}
}
return &((uint8_t *) *data)[(*n)++ * m];
}

static int __hook_entry_cmp(const hook_entry_t *a, const hook_entry_t *b) {
return (int) a->key - (int) b->key;
}
static int hook_entry_cmp(const void *a, const void *b) {
return __hook_entry_cmp(a, b);
}

static int write_whole_buffer(int wr, uint32_t n, cmt_buf_t *tx) {
ssize_t offset = 0;
ssize_t left = n;

while (left) {
ssize_t ret = write(wr, tx->begin + offset, left);
if (ret >= 0) {
offset += ret;
left -= ret;
} else
switch (errno) {
case EINTR:
case EAGAIN:
continue;
default:
return -errno;
}
}
return 0;
}

static int read_whole_buffer(int rd, uint32_t *n, cmt_buf_t *rx) {
ssize_t offset = 0;
ssize_t max = cmt_buf_length(rx);

while (max) {
ssize_t ret = read(rd, rx->begin + offset, max);
if (ret == 0)
break;
if (ret > 0) {
offset += ret;
max -= ret;
} else
switch (errno) {
case EINTR:
case EAGAIN:
continue;
default:
return -errno;
}
}
*n = offset;
return 0;
}

static int parent(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr, pid_t child, int pipes[2][2]) {
int rc;
int rd = pipes[1][0];
if (close(pipes[1][1]) < 0)
perror("Failed to close pipes[1][1]: ");

int wr = pipes[0][1];
if (close(pipes[0][0]) < 0)
perror("Failed to close pipes[0][0]: ");

if ((rc = write_whole_buffer(wr, rr->data, me->tx)))
fprintf(stderr, "Failed to write whole buffer: %s\n", strerror(-rc));
if (close(wr) < 0)
perror("Failed to close wr: ");

if ((rc = read_whole_buffer(rd, &rr->data, me->rx)))
fprintf(stderr, "Failed to write whole buffer: %s\n", strerror(-rc));
if (close(rd) < 0)
perror("Failed to close rd: ");

if ((rc = waitpid(child, NULL, 0)) < 0)
return -errno;
return 0;
}

static int child(int pipes[2][2], uint16_t key, char *exe) {
int rd = pipes[0][0];
if (dup2(rd, STDIN_FILENO) < 0)
perror("dup2 failed: ");
if (close(pipes[0][1]) < 0)
perror("Failed close(pipes[0][1]): ");

int wr = pipes[1][1];
if (dup2(wr, STDOUT_FILENO) < 0)
perror("dup2 failed: ");
if (close(pipes[1][0]) < 0)
perror("Failed close(pipes[1][0]): ");

char skey[16];
snprintf(skey, sizeof skey, "%hu", key);
char *const argv[] = {exe, skey, NULL};
char *const envp[] = {NULL};
if (execve(argv[0], argv, envp) < 0)
perror("Failed: ");
return -errno;
}

int cmt_io_driver_mock_hook_load(cmt_io_driver_mock_t *me, char *env) {
cmt_buf_t x;
cmt_buf_t xs;
hook_entry_t *hooks = NULL;
size_t n = 0, max = 0;

if (!env)
goto end;
size_t envlen = strlen(env);

cmt_buf_init(&xs, envlen, env);
while (cmt_buf_split_by_comma(&x, &xs)) {
uint16_t key = 0;
char exe[128] = "";

if (sscanf((char *) x.begin, "%hu:%127[^,]", &key, exe) != 2) {
fprintf(stderr, "Failed to parse: `%.*s', skipped.\n", (int) cmt_buf_length(&x), x.begin);
continue;
}
fprintf(stderr, "Adding hook: [%d] = \"%s\"\n", key, exe);
hook_entry_t *hook = array_push((void **) &hooks, sizeof hooks[0], &n, &max);
hook->key = key;
hook->exe = strdup(exe);
}
qsort(hooks, n, sizeof hooks[0], hook_entry_cmp);
end:
fprintf(stderr, "Added %lu hook%s\n", n, n > 1 ? "s" : "");
me->hooks = hooks;
me->hooks_num = n;
return 0;
}

int cmt_io_driver_mock_hook_dispatch(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr) {
hook_entry_t key[1] = {{NULL, rr->reason}};
hook_entry_t *hook = bsearch(key, me->hooks, me->hooks_num, sizeof key, hook_entry_cmp);
if (!hook)
return -ENOKEY;

int pipes[2][2];
if (pipe(pipes[0]) < 0)
perror("Failed to create pipes[0]");
if (pipe(pipes[1]) < 0)
perror("Failed to create pipes[1]");

pid_t pid = fork();
return pid ? parent(me, rr, pid, pipes) : child(pipes, hook->key, hook->exe);
}
20 changes: 10 additions & 10 deletions sys-utils/libcmt/src/mock/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

#include "libcmt/io.h"

int cmt_io_driver_mock_hook_load(cmt_io_driver_mock_t *me, char *env);
int cmt_io_driver_mock_hook_dispatch(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr);

static int read_whole_file(const char *name, size_t max, void *data, size_t *length);
static int write_whole_file(const char *name, size_t length, const void *data);

Expand All @@ -32,6 +35,8 @@ int cmt_io_init(cmt_io_driver_t *_me) {
else
cmt_buf_init(&me->inputs_left, 0, "");

cmt_io_driver_mock_hook_load(me, getenv("CMT_HOOKS"));

// in case the user writes something before loading any input
strcpy(me->input_filename, "none");
strcpy(me->input_fileext, ".bin");
Expand All @@ -51,6 +56,7 @@ void cmt_io_fini(cmt_io_driver_t *_me) {

free(me->tx->begin);
free(me->rx->begin);
free(me->hooks);
}

cmt_buf_t cmt_io_get_tx(cmt_io_driver_t *me) {
Expand Down Expand Up @@ -99,10 +105,6 @@ static int load_next_input(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr) {
static int store_output(cmt_io_driver_mock_t *me, const char *filepath, struct cmt_io_yield *rr) {
if (rr->data > cmt_buf_length(me->tx))
return -ENOBUFS;

//char filepath[128 + 1 + 8 + 16];
//snprintf(filepath, sizeof filepath, "%s.%s%d%s", me->input_filename, ns, *seq, me->input_fileext);

int rc = write_whole_file(filepath, rr->data, me->tx->begin);
if (rc) {
fprintf(stderr, "failed to store \"%s\". %s\n", filepath, strerror(-rc));
Expand All @@ -111,8 +113,6 @@ static int store_output(cmt_io_driver_mock_t *me, const char *filepath, struct c
if (getenv("CMT_DEBUG")) {
fprintf(stderr, "wrote filename: \"%s\" (%u)\n", filepath, rr->data);
}

//seq[0] += 1;
return 0;
}

Expand All @@ -139,10 +139,10 @@ static int mock_rx_accepted(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr) {
}
if (me->input_seq++) { // skip the first
char filepath[128 + 32 + 8 + 16];
snprintf(filepath, sizeof filepath,
"%s.outputs_root_hash%s", me->input_filename, me->input_fileext);
snprintf(filepath, sizeof filepath, "%s.outputs_root_hash%s", me->input_filename, me->input_fileext);
int rc = store_output(me, filepath, rr);
if (rc) return rc;
if (rc)
return rc;
}
if (load_next_input(me, rr))
return -ENODATA;
Expand Down Expand Up @@ -215,7 +215,7 @@ int cmt_io_yield(cmt_io_driver_t *_me, struct cmt_io_yield *rr) {
case CMT_IO_REASON_TX_EXCEPTION:
return mock_tx_exception(me, rr);
default:
return -EINVAL;
return cmt_io_driver_mock_hook_dispatch(me, rr);
}
return 0;
}
Expand Down
26 changes: 26 additions & 0 deletions sys-utils/libcmt/src/tests/dehash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include<stdio.h>
#include<string.h>
#include "libcmt/rollup.h"

int main()
{
cmt_rollup_t rollup;
if (cmt_rollup_init(&rollup))
return -1;

cmt_buf_t tx[1] = {cmt_io_get_tx(rollup.io)};
cmt_buf_t rx[1] = {cmt_io_get_rx(rollup.io)};

int m = snprintf((char *)tx->begin, cmt_buf_length(tx), "request");
struct cmt_io_yield req[1] = {{
.dev = CMT_IO_DEV,
.cmd = CMT_IO_CMD_MANUAL,
.reason = 10,
.data = m,
}};
int rc = cmt_io_yield(rollup.io, req);
printf("%d:%s \"%.*s\"\n", rc, strerror(rc), req->data, (char *)rx->begin);

return 0;
}

0 comments on commit 37718fd

Please sign in to comment.