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

swarmfile.c (4011B)


      1 #include <stddef.h>
      2 #include <string.h>
      3 
      4 #include "def.h"
      5 #include "endian.h"
      6 #include "swarmfile.h"
      7 
      8 static inline void filehash_callback(filehash_t *fctx, const unsigned char *hash, const unsigned char *data, const size_t data_length, const bmt_spansize_t span_size) {
      9 	if (fctx->callback != NULL) {
     10 		if (span_size < 0) {
     11 			(*fctx->callback)(hash, data, data_length + SWARM_DATA_LENGTH_TYPESIZE, fctx->callback_static);
     12 		} else {
     13 			unsigned char out_data[SWARM_BLOCK_SIZE + SWARM_DATA_LENGTH_TYPESIZE];
     14 			memcpy(out_data, &span_size, SWARM_DATA_LENGTH_TYPESIZE);
     15 			to_endian(CONVERT_LITTLEENDIAN, SWARM_DATA_LENGTH_TYPESIZE, (unsigned char*)out_data);
     16 			memcpy(out_data + SWARM_DATA_LENGTH_TYPESIZE, data, data_length);
     17 			(*fctx->callback)(hash, out_data, data_length + SWARM_DATA_LENGTH_TYPESIZE, fctx->callback_static);
     18 		}
     19 	}
     20 }
     21 
     22 
     23 void filehash_reset(filehash_t *fctx) {
     24 	int i;
     25 	for (i = 0; i < SWARM_LEVELS; i++) {
     26 		fctx->ptr[i] = fctx->buf;
     27 		fctx->writes[i] = 0;
     28 	}
     29 	fctx->length = 0;
     30 }
     31 
     32 
     33 static bmt_spansize_t filehash_finalize_level(filehash_t *fctx, int level) {
     34 	bmt_t *bctx;
     35 	int l;
     36 	int r;
     37 	int next_level;
     38 	int blocks;
     39 	int blocks_span_length;
     40 	int remainder;
     41 
     42 	bctx = &fctx->bmt_context;
     43 
     44 	next_level = level + 1;
     45 
     46 	if (fctx->ptr[level] == fctx->target) {
     47 		return fctx->length;
     48 	}
     49 
     50 	l = fctx->ptr[level] - fctx->ptr[next_level];
     51 	blocks = (l / SWARM_WORD_SIZE);
     52 
     53 	remainder = fctx->length % fctx->spans[level];
     54 
     55 	if (blocks == 1) {
     56 		fctx->ptr[next_level] = fctx->ptr[level];
     57 		return filehash_finalize_level(fctx, next_level);
     58 	} else {
     59 		blocks_span_length = (blocks - 1) * fctx->spans[level];
     60 		if (remainder > 0) {
     61 			blocks_span_length += remainder;
     62 		} else {
     63 			blocks_span_length += fctx->spans[level];
     64 		}
     65 		bmt_init(bctx, fctx->ptr[next_level], l, (bmt_spansize_t)(blocks_span_length));
     66 		r = bmt_sum(bctx);
     67 		if (r != 0) {
     68 			return -1;
     69 		}
     70 		filehash_callback(fctx, bctx->buf, fctx->ptr[next_level], l, (bmt_spansize_t)(blocks_span_length));
     71 		memcpy(fctx->ptr[next_level], bctx->buf, SWARM_WORD_SIZE);
     72 		fctx->ptr[next_level] += SWARM_WORD_SIZE;
     73 	}
     74 	return filehash_finalize_level(fctx, next_level);
     75 }
     76 
     77 
     78 bmt_spansize_t filehash_sum(filehash_t *fctx) {
     79 	return filehash_finalize_level(fctx, 0);
     80 }
     81 
     82 
     83 void filehash_init_callback(filehash_t *fctx, void (*callback)(const unsigned char*, const unsigned char*, const size_t, void*), void *callback_static) {
     84 	int i;
     85 	int l;
     86 
     87 	l = SWARM_BLOCK_SIZE;
     88 
     89 	for (i = 0; i < SWARM_LEVELS; i++) {
     90 		fctx->spans[i] = l;
     91 		l *= SWARM_BATCH_SIZE;
     92 	}
     93 	fctx->target = fctx->buf + SWARM_WORD_SIZE;
     94 	fctx->callback = callback;
     95 	fctx->callback_static = callback_static;
     96 
     97 	filehash_reset(fctx);	
     98 }
     99 
    100 void filehash_init(filehash_t *fctx) {
    101 	return filehash_init_callback(fctx, NULL, NULL);
    102 }
    103 
    104 
    105 static int filehash_write_hash(filehash_t *fctx, int level, const unsigned char *data) {
    106 	bmt_t *bctx;
    107 	int next_level;
    108 	int r;
    109 
    110 	fctx->writes[level] += 1;
    111 	memcpy(fctx->ptr[level], data, SWARM_WORD_SIZE);
    112 	if (fctx->writes[level] % SWARM_BATCH_SIZE == 0) {
    113 		bctx = &fctx->bmt_context;
    114 		next_level = level + 1;
    115 		bmt_init(bctx, fctx->ptr[next_level], SWARM_BLOCK_SIZE, (long long)fctx->spans[next_level]);
    116 		r = bmt_sum(bctx);
    117 		if (r != 0) {
    118 			return -1;
    119 		}
    120 		filehash_callback(fctx, bctx->buf, fctx->ptr[next_level], SWARM_BLOCK_SIZE, (bmt_spansize_t)fctx->spans[next_level]);
    121 		r = filehash_write_hash(fctx, level + 1, bctx->buf);
    122 		if (r != 0) {
    123 			return -1;
    124 		}
    125 		fctx->ptr[level] = fctx->ptr[next_level];
    126 	} else {
    127 		fctx->ptr[level] += SWARM_WORD_SIZE;
    128 	}
    129 	return 0;
    130 }
    131 
    132 int filehash_write(filehash_t *fctx, const unsigned char *data, const size_t data_length) {
    133 	bmt_t *bctx;
    134 	int r;
    135 
    136 	bctx = &fctx->bmt_context;
    137 
    138 	bmt_init(bctx, data, data_length, (long long)data_length);
    139 	r = bmt_sum(bctx);
    140 	if (r != 0) {
    141 		return -1;
    142 	}
    143 	filehash_callback(fctx, bctx->buf, data, data_length, (bmt_spansize_t)data_length);
    144 	r = filehash_write_hash(fctx, 0, bctx->buf);
    145 	if (r != 0) {
    146 		return -1;
    147 	}
    148 	fctx->length += data_length;
    149 
    150 	return data_length;
    151 }
    152 
    153