X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcontainer_bloomfilter.c;h=d6c2cb8b9cddf385d6485c0c67fdcabb7be1186b;hb=72c8645af31896829b674b575c5375706f362a30;hp=788f148fa26f23d9f132166d626bed6901334385;hpb=04ae9253f7dff8d442e36edec1465f54d3f436a5;p=oweals%2Fgnunet.git diff --git a/src/util/container_bloomfilter.c b/src/util/container_bloomfilter.c index 788f148fa..d6c2cb8b9 100644 --- a/src/util/container_bloomfilter.c +++ b/src/util/container_bloomfilter.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001, 2002, 2003, 2004, 2006, 2008 Christian Grothoff (and other contributing authors) + (C) 2001, 2002, 2003, 2004, 2006, 2008, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -183,7 +183,7 @@ static void incrementBit (char *bitArray, unsigned int bitIdx, const struct GNUNET_DISK_FileHandle *fh) { - off_t fileSlot; + OFF_T fileSlot; unsigned char value; unsigned int high; unsigned int low; @@ -231,7 +231,7 @@ static void decrementBit (char *bitArray, unsigned int bitIdx, const struct GNUNET_DISK_FileHandle *fh) { - off_t fileSlot; + OFF_T fileslot; unsigned char value; unsigned int high; unsigned int low; @@ -240,9 +240,13 @@ decrementBit (char *bitArray, unsigned int bitIdx, if (GNUNET_DISK_handle_invalid (fh)) return; /* cannot decrement! */ /* Each char slot in the counter file holds two 4 bit counters */ - fileSlot = bitIdx / 2; + fileslot = bitIdx / 2; targetLoc = bitIdx % 2; - GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET); + if (GNUNET_SYSERR == GNUNET_DISK_file_seek (fh, fileslot, GNUNET_DISK_SEEK_SET)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "seek"); + return; + } if (1 != GNUNET_DISK_file_read (fh, &value, 1)) value = 0; low = value & 0xF; @@ -268,7 +272,11 @@ decrementBit (char *bitArray, unsigned int bitIdx, } } value = ((high << 4) | low); - GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET); + if (GNUNET_SYSERR == GNUNET_DISK_file_seek (fh, fileslot, GNUNET_DISK_SEEK_SET)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "seek"); + return; + } GNUNET_assert (1 == GNUNET_DISK_file_write (fh, &value, 1)); } @@ -282,33 +290,33 @@ decrementBit (char *bitArray, unsigned int bitIdx, * @return GNUNET_OK if created ok, GNUNET_SYSERR otherwise */ static int -makeEmptyFile (const struct GNUNET_DISK_FileHandle *fh, size_t size) +make_empty_file (const struct GNUNET_DISK_FileHandle *fh, size_t size) { - char *buffer; + char buffer[BUFFSIZE]; size_t bytesleft = size; int res = 0; if (GNUNET_DISK_handle_invalid (fh)) return GNUNET_SYSERR; - buffer = GNUNET_malloc (BUFFSIZE); - memset (buffer, 0, BUFFSIZE); + memset (buffer, 0, sizeof (buffer)); GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_SET); - while (bytesleft > 0) { - if (bytesleft > BUFFSIZE) + if (bytesleft > sizeof (buffer)) { - res = GNUNET_DISK_file_write (fh, buffer, BUFFSIZE); - bytesleft -= BUFFSIZE; + res = GNUNET_DISK_file_write (fh, buffer, sizeof (buffer)); + if (res >= 0) + bytesleft -= res; } else { res = GNUNET_DISK_file_write (fh, buffer, bytesleft); - bytesleft = 0; + if (res >= 0) + bytesleft -= res; } - GNUNET_assert (res != GNUNET_SYSERR); + if (GNUNET_SYSERR == res) + return GNUNET_SYSERR; } - GNUNET_free (buffer); return GNUNET_OK; } @@ -340,9 +348,9 @@ typedef int (*BitIterator) (void *cls, */ static void iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, - BitIterator callback, void *arg, const GNUNET_HashCode * key) + BitIterator callback, void *arg, const struct GNUNET_HashCode *key) { - GNUNET_HashCode tmp[2]; + struct GNUNET_HashCode tmp[2]; int bitCount; unsigned int round; unsigned int slot = 0; @@ -350,14 +358,16 @@ iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, bitCount = bf->addressesPerElement; tmp[0] = *key; round = 0; + GNUNET_assert (bf->bitArraySize > 0); + GNUNET_assert (bf->bitArraySize * 8LL > bf->bitArraySize); while (bitCount > 0) { - while (slot < (sizeof (GNUNET_HashCode) / sizeof (uint32_t))) + while (slot < (sizeof (struct GNUNET_HashCode) / sizeof (uint32_t))) { if (GNUNET_YES != callback (arg, bf, - (((uint32_t *) & tmp[round & 1])[slot]) & - ((bf->bitArraySize * 8) - 1))) + ntohl ((((uint32_t *) & tmp[round & 1])[slot])) % + ((bf->bitArraySize * 8LL)))) return; slot++; bitCount--; @@ -366,7 +376,7 @@ iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, } if (bitCount > 0) { - GNUNET_CRYPTO_hash (&tmp[round & 1], sizeof (GNUNET_HashCode), + GNUNET_CRYPTO_hash (&tmp[round & 1], sizeof (struct GNUNET_HashCode), &tmp[(round + 1) & 1]); round++; slot = 0; @@ -442,7 +452,8 @@ testBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, * * @param filename the name of the file (or the prefix) * @param size the size of the bloom-filter (number of - * bytes of storage space to use) + * bytes of storage space to use); will be rounded up + * to next power of 2 * @param k the number of GNUNET_CRYPTO_hash-functions to apply per * element (number of bits set per element in the set) * @return the bloomfilter @@ -453,10 +464,10 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, { struct GNUNET_CONTAINER_BloomFilter *bf; char *rbuff; - off_t pos; + OFF_T pos; int i; size_t ui; - off_t fsize; + OFF_T fsize; int must_read; GNUNET_assert (NULL != filename); @@ -472,14 +483,49 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, bf = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_BloomFilter)); /* Try to open a bloomfilter file */ - bf->fh = + if (GNUNET_YES == GNUNET_DISK_file_test (filename)) + bf->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); - if (NULL == bf->fh) + if (NULL != bf->fh) + { + /* file existed, try to read it! */ + must_read = GNUNET_YES; + if (GNUNET_OK != + GNUNET_DISK_file_handle_size (bf->fh, &fsize)) + { + GNUNET_DISK_file_close (bf->fh); + GNUNET_free (bf); + return NULL; + } + if (fsize == 0) + { + /* found existing empty file, just overwrite */ + if (GNUNET_OK != make_empty_file (bf->fh, size * 4LL)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "write"); + GNUNET_DISK_file_close (bf->fh); + GNUNET_free (bf); + return NULL; + } + } + else if (fsize != size * 4LL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Size of file on disk is incorrect for this Bloom filter (want %llu, have %llu)\n"), + (unsigned long long) (size * 4LL), + (unsigned long long) fsize); + GNUNET_DISK_file_close (bf->fh); + GNUNET_free (bf); + return NULL; + } + } + else { - /* file did not exist, don't read */ + /* file did not exist, don't read, just create */ must_read = GNUNET_NO; bf->fh = GNUNET_DISK_file_open (filename, @@ -492,22 +538,10 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, GNUNET_free (bf); return NULL; } - } - else - { - /* file existed, try to read it! */ - must_read = GNUNET_YES; - if (GNUNET_OK != - GNUNET_DISK_file_handle_size (bf->fh, &fsize)) - { - GNUNET_DISK_file_close (bf->fh); - GNUNET_free (bf); - return NULL; - } - if (fsize != size * 8LL) + if (GNUNET_OK != make_empty_file (bf->fh, size * 4LL)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Size of file on disk is incorrect for this Bloom filter\n")); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "write"); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; @@ -526,10 +560,8 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, } bf->bitArraySize = size; bf->addressesPerElement = k; - memset (bf->bitArray, 0, bf->bitArraySize); - - if (GNUNET_YES != must_read) - return bf; /* already done! */ + if (GNUNET_YES != must_read) + return bf; /* already done! */ /* Read from the file what bits we can */ rbuff = GNUNET_malloc (BUFFSIZE); pos = 0; @@ -583,33 +615,22 @@ GNUNET_CONTAINER_bloomfilter_init (const char *data, size_t size, unsigned int k) { struct GNUNET_CONTAINER_BloomFilter *bf; - size_t ui; - if ((k == 0) || (size == 0)) - return NULL; - ui = 1; - while (ui < size) - ui *= 2; - if (size != ui) - { - GNUNET_break (0); + if ((0 == k) || (0 == size)) return NULL; - } bf = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_BloomFilter)); bf->filename = NULL; bf->fh = NULL; bf->bitArray = GNUNET_malloc_large (size); - if (bf->bitArray == NULL) + if (NULL == bf->bitArray) { GNUNET_free (bf); return NULL; } bf->bitArraySize = size; bf->addressesPerElement = k; - if (data != NULL) + if (NULL != data) memcpy (bf->bitArray, data, size); - else - memset (bf->bitArray, 0, bf->bitArraySize); return bf; } @@ -670,7 +691,7 @@ GNUNET_CONTAINER_bloomfilter_clear (struct GNUNET_CONTAINER_BloomFilter *bf) memset (bf->bitArray, 0, bf->bitArraySize); if (bf->filename != NULL) - makeEmptyFile (bf->fh, bf->bitArraySize * 4); + make_empty_file (bf->fh, bf->bitArraySize * 4LL); } @@ -683,7 +704,7 @@ GNUNET_CONTAINER_bloomfilter_clear (struct GNUNET_CONTAINER_BloomFilter *bf) */ int GNUNET_CONTAINER_bloomfilter_test (const struct GNUNET_CONTAINER_BloomFilter - *bf, const GNUNET_HashCode * e) + *bf, const struct GNUNET_HashCode * e) { int res; @@ -703,7 +724,7 @@ GNUNET_CONTAINER_bloomfilter_test (const struct GNUNET_CONTAINER_BloomFilter */ void GNUNET_CONTAINER_bloomfilter_add (struct GNUNET_CONTAINER_BloomFilter *bf, - const GNUNET_HashCode * e) + const struct GNUNET_HashCode * e) { if (NULL == bf) return; @@ -788,7 +809,7 @@ GNUNET_CONTAINER_bloomfilter_or2 (struct GNUNET_CONTAINER_BloomFilter *bf, */ void GNUNET_CONTAINER_bloomfilter_remove (struct GNUNET_CONTAINER_BloomFilter *bf, - const GNUNET_HashCode * e) + const struct GNUNET_HashCode * e) { if (NULL == bf) return; @@ -814,7 +835,7 @@ GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf, void *iterator_cls, size_t size, unsigned int k) { - GNUNET_HashCode hc; + struct GNUNET_HashCode hc; unsigned int i; GNUNET_free (bf->bitArray); @@ -825,9 +846,8 @@ GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf, bf->bitArraySize = size; bf->bitArray = GNUNET_malloc (size); - memset (bf->bitArray, 0, bf->bitArraySize); if (bf->filename != NULL) - makeEmptyFile (bf->fh, bf->bitArraySize * 4); + make_empty_file (bf->fh, bf->bitArraySize * 4LL); while (GNUNET_YES == iterator (iterator_cls, &hc)) GNUNET_CONTAINER_bloomfilter_add (bf, &hc); }