libswarm-ng

C implementation of BMT hasher, Swarmhash and Single Owner Chunk for swarm
git clone git://git.defalsify.org/libswarm-ng.git
Log | Files | Refs | Submodules | README

commit e48de796ff6ede0b2cfd7751fb69d22dea226f54
parent 846373e74b7ebda76074eaf6c037f2fb479fa1b9
Author: nolash <dev@holbrook.no>
Date:   Tue, 14 Sep 2021 22:12:45 +0200

Apply output callback

Diffstat:
Msrc/swarmfile.c | 19++++++++++++++++++-
Msrc/swarmfile.h | 2++
Mtest/check_file.c | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mtest/common.c | 2--
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; } - -