commit e48de796ff6ede0b2cfd7751fb69d22dea226f54
parent 846373e74b7ebda76074eaf6c037f2fb479fa1b9
Author: nolash <dev@holbrook.no>
Date: Tue, 14 Sep 2021 22:12:45 +0200
Apply output callback
Diffstat:
4 files changed, 163 insertions(+), 10 deletions(-)
diff --git a/src/swarmfile.c b/src/swarmfile.c
@@ -3,6 +3,13 @@
#include "swarmfile.h"
+static inline void filehash_callback(filehash_t *fctx, const char *hash, const char *data, const size_t data_length) {
+ if (fctx->callback != NULL) {
+ (*fctx->callback)(hash, data, data_length);
+ }
+}
+
+
void filehash_reset(filehash_t *fctx) {
int i;
for (i = 0; i < SWARM_LEVELS; i++) {
@@ -12,6 +19,7 @@ void filehash_reset(filehash_t *fctx) {
fctx->length = 0;
}
+
static bmt_spansize_t filehash_finalize_level(filehash_t *fctx, int level) {
bmt_t *bctx;
int l;
@@ -49,6 +57,7 @@ static bmt_spansize_t filehash_finalize_level(filehash_t *fctx, int level) {
if (r != 0) {
return -1;
}
+ filehash_callback(fctx, bctx->buf, fctx->ptr[next_level], l);
memcpy(fctx->ptr[next_level], bctx->buf, _SWARM_WORD_SIZE);
fctx->ptr[next_level] += _SWARM_WORD_SIZE;
}
@@ -61,7 +70,7 @@ bmt_spansize_t filehash_sum(filehash_t *fctx) {
}
-void filehash_init(filehash_t *fctx) {
+void filehash_init_callback(filehash_t *fctx, void *callback) {
int i;
int l;
@@ -72,10 +81,16 @@ void filehash_init(filehash_t *fctx) {
l *= _SWARM_BATCH_SIZE;
}
fctx->target = fctx->buf + _SWARM_WORD_SIZE;
+ fctx->callback = callback;
filehash_reset(fctx);
}
+void filehash_init(filehash_t *fctx) {
+ return filehash_init_callback(fctx, NULL);
+}
+
+
static int filehash_write_hash(filehash_t *fctx, int level, const char *data) {
bmt_t *bctx;
int next_level;
@@ -91,6 +106,7 @@ static int filehash_write_hash(filehash_t *fctx, int level, const char *data) {
if (r != 0) {
return -1;
}
+ filehash_callback(fctx, bctx->buf, fctx->ptr[next_level], SWARM_BLOCK_SIZE);
r = filehash_write_hash(fctx, level + 1, bctx->buf);
if (r != 0) {
return -1;
@@ -113,6 +129,7 @@ int filehash_write(filehash_t *fctx, const char *data, const size_t data_length)
if (r != 0) {
return -1;
}
+ filehash_callback(fctx, bctx->buf, data, data_length);
r = filehash_write_hash(fctx, 0, bctx->buf);
if (r != 0) {
return -1;
diff --git a/src/swarmfile.h b/src/swarmfile.h
@@ -13,11 +13,13 @@ typedef struct filehash {
long long writes[SWARM_LEVELS];
long long spans[SWARM_LEVELS];
long long length;
+ void (*callback)(const char*, const char*, const size_t);
bmt_t bmt_context;
} filehash_t;
void filehash_reset(filehash_t *filehash_context);
void filehash_init(filehash_t *filehash_context);
+void filehash_init_callback(filehash_t *filehash_context, void *callback);
int filehash_write(filehash_t *filehash_context, const char *data, const size_t data_length);
bmt_spansize_t filehash_sum(filehash_t *filehash_content);
diff --git a/test/check_file.c b/test/check_file.c
@@ -1,12 +1,39 @@
#include <check.h>
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "hex.h"
#include "swarmfile.h"
#include "common.h"
+
+int file_callback_serial = 0;
+int file_callback_dir_fd = -1;
+
+void file_callback(const char *hash, const char *data, const size_t data_length) {
+ int fd;
+ char filename[32];
+
+ sprintf(filename, "d%d", file_callback_serial);
+ fd = openat(file_callback_dir_fd, filename, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC | O_SYNC);
+ ck_assert_int_ge(fd, 2);
+ write(fd, data, data_length);
+ close(fd);
+
+ sprintf(filename, "h%d", file_callback_serial);
+ fd = openat(file_callback_dir_fd, filename, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC | O_SYNC);
+ ck_assert_int_ge(fd, 2);
+ write(fd, hash, _SWARM_WORD_SIZE);
+ close(fd);
+
+ file_callback_serial++;
+}
+
+
START_TEST(check_file_init) {
ck_assert_int_eq(_SWARM_BATCH_SIZE, 128);
@@ -64,6 +91,104 @@ START_TEST(check_file_write_batch) {
}
END_TEST
+START_TEST(check_file_callback_data) {
+ filehash_t fh;
+ int r;
+
+ const char *data = "foo";
+ char cbdir_template[] = "swarmfile_test_callback_data_XXXXXX";
+ char *cbdir;
+
+ cbdir = mkdtemp(cbdir_template);
+ ck_assert_ptr_nonnull(cbdir);
+
+ file_callback_serial = 0;
+ file_callback_dir_fd = open(cbdir, O_DIRECTORY | O_SYNC);
+
+ filehash_init_callback(&fh, file_callback);
+
+ r = filehash_write(&fh, data, strlen(data));
+ ck_assert_int_eq(r, 3);
+ ck_assert_int_eq(fh.writes[0], 1);
+ ck_assert_int_eq(fh.length, 3);
+ close(file_callback_dir_fd);
+
+}
+END_TEST
+
+START_TEST(check_file_callback_intermediate) {
+ filehash_t fh;
+ int i;
+ int r;
+ struct block_generator bg;
+
+ char buf[SWARM_BLOCK_SIZE * (_SWARM_BATCH_SIZE + 1)];
+ char cbdir_template[] = "swarmfile_test_callback_intermediate_XXXXXX";
+ char *cbdir;
+ char cbfilename[1024];
+ int cbfd;
+ char cbbuf[SWARM_BLOCK_SIZE];
+
+ file_callback_serial = 0;
+ cbdir = mkdtemp(cbdir_template);
+ ck_assert_ptr_nonnull(cbdir);
+
+ file_callback_dir_fd = open(cbdir, O_DIRECTORY | O_SYNC);
+
+ filehash_init_callback(&fh, file_callback);
+
+ bg.v = 0;
+ bg.m = 255;
+
+ r = block_generate(&bg, buf, SWARM_BLOCK_SIZE * (_SWARM_BATCH_SIZE + 1));
+ ck_assert_int_eq(r, SWARM_BLOCK_SIZE * (_SWARM_BATCH_SIZE + 1));
+ for (i = 0; i < _SWARM_BATCH_SIZE + 1; i++) {
+ r = filehash_write(&fh, buf + i * SWARM_BLOCK_SIZE, SWARM_BLOCK_SIZE);
+ ck_assert_int_eq(r, SWARM_BLOCK_SIZE);
+
+ if (i > 127) {
+ continue;
+ }
+
+ sprintf(cbfilename, "%s/d%d", cbdir, i);
+ cbfd = open(cbfilename, O_RDONLY);
+ ck_assert_int_gt(cbfd, 2);
+
+ r = read(cbfd, cbbuf, SWARM_BLOCK_SIZE);
+ ck_assert_int_eq(r, SWARM_BLOCK_SIZE);
+ ck_assert_mem_eq(cbbuf, buf + i * SWARM_BLOCK_SIZE, SWARM_BLOCK_SIZE);
+ close(cbfd);
+ }
+
+ sprintf(cbfilename, "%s/h128", cbdir);
+ //cbfd = openat(file_callback_dir_fd, cbfilename, O_RDONLY);
+ cbfd = open(cbfilename, O_RDONLY);
+ ck_assert_int_gt(cbfd, 2);
+
+ r = read(cbfd, cbbuf, _SWARM_WORD_SIZE);
+ ck_assert_int_eq(r, _SWARM_WORD_SIZE);
+ ck_assert_mem_eq(cbbuf, fh.buf, _SWARM_WORD_SIZE);
+ close(cbfd);
+
+ r = filehash_sum(&fh);
+ ck_assert_int_eq(r, SWARM_BLOCK_SIZE * (_SWARM_BATCH_SIZE + 1));
+ sprintf(cbfilename, "%s/h130", cbdir);
+ cbfd = open(cbfilename, O_RDONLY);
+ ck_assert_int_gt(cbfd, 2);
+
+ r = read(cbfd, cbbuf, _SWARM_WORD_SIZE);
+ ck_assert_mem_eq(cbbuf, fh.buf, _SWARM_WORD_SIZE);
+
+ r = hex2bin("b8e1804e37a064d28d161ab5f256cc482b1423d5cd0a6b30fde7b0f51ece9199", cbbuf + _SWARM_WORD_SIZE);
+ ck_assert_int_eq(r, _SWARM_WORD_SIZE);
+ ck_assert_mem_eq(cbbuf, cbbuf + _SWARM_WORD_SIZE, _SWARM_WORD_SIZE);
+ close(cbfd);
+
+ close(file_callback_dir_fd);
+ file_callback_dir_fd = -1;
+}
+END_TEST
+
START_TEST(check_file_vectors) {
filehash_t fh;
int r;
@@ -146,17 +271,28 @@ START_TEST(check_file_vectors) {
}
END_TEST
+
+
+
Suite * common_suite(void) {
Suite *s;
- TCase *tc;
+ TCase *tch;
+ TCase *tcc;
+ TCase *tcv;
s = suite_create("file");
- tc = tcase_create("core");
- tcase_add_test(tc, check_file_init);
- tcase_add_test(tc, check_file_single_write);
- tcase_add_test(tc, check_file_write_batch);
- tcase_add_test(tc, check_file_vectors);
- suite_add_tcase(s, tc);
+ tch = tcase_create("hasher");
+ tcc = tcase_create("callback");
+ tcv = tcase_create("vectors");
+ tcase_add_test(tch, check_file_init);
+ tcase_add_test(tch, check_file_single_write);
+ tcase_add_test(tch, check_file_write_batch);
+ suite_add_tcase(s, tch);
+ tcase_add_test(tcc, check_file_callback_data);
+ tcase_add_test(tcc, check_file_callback_intermediate);
+ suite_add_tcase(s, tcc);
+ tcase_add_test(tcv, check_file_vectors);
+ suite_add_tcase(s, tcv);
return s;
}
diff --git a/test/common.c b/test/common.c
@@ -13,5 +13,3 @@ int block_generate(struct block_generator *bg, char *buf, size_t l) {
return i;
}
-
-