X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcontainer_bloomfilter.c;h=6e8fc78377f4db6ec600e423222752072bc60c3d;hb=8226d9807819dbbc4b05751f4cdd09603832367d;hp=8b76ef8dc03d74966e773ad9627f7e990f11fa11;hpb=0a217a8df1657b4334b55b0e4a6c7837a8dbcfd9;p=oweals%2Fgnunet.git diff --git a/src/util/container_bloomfilter.c b/src/util/container_bloomfilter.c index 8b76ef8dc..6e8fc7837 100644 --- a/src/util/container_bloomfilter.c +++ b/src/util/container_bloomfilter.c @@ -60,7 +60,7 @@ struct GNUNET_CONTAINER_BloomFilter /** * The bit counter file on disk */ - int fd; + struct GNUNET_DISK_FileHandle *fh; /** * How many bits we set for each stored element @@ -70,7 +70,7 @@ struct GNUNET_CONTAINER_BloomFilter /** * Size of bitArray in bytes */ - unsigned int bitArraySize; + size_t bitArraySize; }; @@ -85,7 +85,7 @@ struct GNUNET_CONTAINER_BloomFilter static void setBit (char *bitArray, unsigned int bitIdx) { - unsigned int arraySlot; + size_t arraySlot; unsigned int targetBit; arraySlot = bitIdx / 8; @@ -103,7 +103,7 @@ setBit (char *bitArray, unsigned int bitIdx) static void clearBit (char *bitArray, unsigned int bitIdx) { - unsigned int slot; + size_t slot; unsigned int targetBit; slot = bitIdx / 8; @@ -121,7 +121,7 @@ clearBit (char *bitArray, unsigned int bitIdx) static int testBit (char *bitArray, unsigned int bitIdx) { - unsigned int slot; + size_t slot; unsigned int targetBit; slot = bitIdx / 8; @@ -139,26 +139,28 @@ testBit (char *bitArray, unsigned int bitIdx) * * @param bitArray memory area to set the bit in * @param bitIdx which bit to test - * @param fd A file to keep the 4 bit address usage counters in + * @param fh A file to keep the 4 bit address usage counters in */ static void -incrementBit (char *bitArray, unsigned int bitIdx, int fd) +incrementBit (char *bitArray, unsigned int bitIdx, + const struct GNUNET_DISK_FileHandle *fh) { - unsigned int fileSlot; + off_t fileSlot; unsigned char value; unsigned int high; unsigned int low; unsigned int targetLoc; setBit (bitArray, bitIdx); - if (fd == -1) + if (GNUNET_DISK_handle_invalid (fh)) return; /* Update the counter file on disk */ fileSlot = bitIdx / 2; targetLoc = bitIdx % 2; - GNUNET_assert (fileSlot == (unsigned int) LSEEK (fd, fileSlot, SEEK_SET)); - if (1 != READ (fd, &value, 1)) + GNUNET_assert (fileSlot == + GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET)); + if (1 != GNUNET_DISK_file_read (fh, &value, 1)) value = 0; low = value & 0xF; high = (value & (~0xF)) >> 4; @@ -174,8 +176,10 @@ incrementBit (char *bitArray, unsigned int bitIdx, int fd) high++; } value = ((high << 4) | low); - GNUNET_assert (fileSlot == (unsigned int) LSEEK (fd, fileSlot, SEEK_SET)); - GNUNET_assert (1 == WRITE (fd, &value, 1)); + GNUNET_assert (fileSlot == GNUNET_DISK_file_seek (fh, + fileSlot, + GNUNET_DISK_SEEK_SET)); + GNUNET_assert (1 == GNUNET_DISK_file_write (fh, &value, 1)); } /** @@ -184,24 +188,25 @@ incrementBit (char *bitArray, unsigned int bitIdx, int fd) * * @param bitArray memory area to set the bit in * @param bitIdx which bit to test - * @param fd A file to keep the 4bit address usage counters in + * @param fh A file to keep the 4bit address usage counters in */ static void -decrementBit (char *bitArray, unsigned int bitIdx, int fd) +decrementBit (char *bitArray, unsigned int bitIdx, + const struct GNUNET_DISK_FileHandle *fh) { - unsigned int fileSlot; + off_t fileSlot; unsigned char value; unsigned int high; unsigned int low; unsigned int targetLoc; - if (fd == -1) + if (GNUNET_DISK_handle_invalid (fh)) return; /* cannot decrement! */ /* Each char slot in the counter file holds two 4 bit counters */ fileSlot = bitIdx / 2; targetLoc = bitIdx % 2; - LSEEK (fd, fileSlot, SEEK_SET); - if (1 != READ (fd, &value, 1)) + GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET); + if (1 != GNUNET_DISK_file_read (fh, &value, 1)) value = 0; low = value & 0xF; high = (value & 0xF0) >> 4; @@ -226,8 +231,8 @@ decrementBit (char *bitArray, unsigned int bitIdx, int fd) } } value = ((high << 4) | low); - LSEEK (fd, fileSlot, SEEK_SET); - GNUNET_assert (1 == WRITE (fd, &value, 1)); + GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET); + GNUNET_assert (1 == GNUNET_DISK_file_write (fh, &value, 1)); } #define BUFFSIZE 65536 @@ -235,54 +240,55 @@ decrementBit (char *bitArray, unsigned int bitIdx, int fd) /** * Creates a file filled with zeroes * - * @param fd the file handle + * @param fh the file handle * @param size the size of the file * @return GNUNET_OK if created ok, GNUNET_SYSERR otherwise */ static int -makeEmptyFile (int fd, unsigned int size) +makeEmptyFile (const struct GNUNET_DISK_FileHandle *fh, size_t size) { char *buffer; - unsigned int bytesleft = size; + size_t bytesleft = size; int res = 0; - if (fd == -1) + if (GNUNET_DISK_handle_invalid (fh)) return GNUNET_SYSERR; buffer = GNUNET_malloc (BUFFSIZE); memset (buffer, 0, BUFFSIZE); - LSEEK (fd, 0, SEEK_SET); + GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_SET); while (bytesleft > 0) { if (bytesleft > BUFFSIZE) { - res = WRITE (fd, buffer, BUFFSIZE); + res = GNUNET_DISK_file_write (fh, buffer, BUFFSIZE); bytesleft -= BUFFSIZE; } else { - res = WRITE (fd, buffer, bytesleft); + res = GNUNET_DISK_file_write (fh, buffer, bytesleft); bytesleft = 0; } - GNUNET_assert (res != -1); + GNUNET_assert (res != GNUNET_SYSERR); } GNUNET_free (buffer); return GNUNET_OK; } -/* ************** GNUNET_CONTAINER_BloomFilter GNUNET_CRYPTO_hash iterator ********* */ +/* ************** GNUNET_CONTAINER_BloomFilter iterator ********* */ /** * Iterator (callback) method to be called by the * bloomfilter iterator on each bit that is to be * set or tested for the key. * + * @param cls closure * @param bf the filter to manipulate * @param bit the current bit - * @param additional context specific argument */ -typedef void (*BitIterator) (struct GNUNET_CONTAINER_BloomFilter * bf, - unsigned int bit, void *arg); +typedef void (*BitIterator) (void *cls, + struct GNUNET_CONTAINER_BloomFilter * bf, + unsigned int bit); /** * Call an iterator for each bit that the bloomfilter @@ -307,11 +313,12 @@ iterateBits (struct GNUNET_CONTAINER_BloomFilter *bf, round = 0; while (bitCount > 0) { - while (slot < (sizeof (GNUNET_HashCode) / sizeof (unsigned int))) + while (slot < (sizeof (GNUNET_HashCode) / sizeof (uint32_t))) { - callback (bf, - (((unsigned int *) &tmp[round & 1])[slot]) & - ((bf->bitArraySize * 8) - 1), arg); + callback (arg, + bf, + (((uint32_t *) & tmp[round & 1])[slot]) & + ((bf->bitArraySize * 8) - 1)); slot++; bitCount--; if (bitCount == 0) @@ -330,41 +337,43 @@ iterateBits (struct GNUNET_CONTAINER_BloomFilter *bf, /** * Callback: increment bit * + * @param cls not used * @param bf the filter to manipulate * @param bit the bit to increment - * @param arg not used */ static void -incrementBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf, - unsigned int bit, void *arg) +incrementBitCallback (void *cls, + struct GNUNET_CONTAINER_BloomFilter *bf, + unsigned int bit) { - incrementBit (bf->bitArray, bit, bf->fd); + incrementBit (bf->bitArray, bit, bf->fh); } /** * Callback: decrement bit * + * @param cls not used * @param bf the filter to manipulate * @param bit the bit to decrement - * @param arg not used */ static void -decrementBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf, - unsigned int bit, void *arg) +decrementBitCallback (void *cls, + struct GNUNET_CONTAINER_BloomFilter *bf, + unsigned int bit) { - decrementBit (bf->bitArray, bit, bf->fd); + decrementBit (bf->bitArray, bit, bf->fh); } /** * Callback: test if all bits are set * + * @param cls pointer set to GNUNET_NO if bit is not set * @param bf the filter * @param bit the bit to test - * @param arg pointer set to GNUNET_NO if bit is not set */ static void -testBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit, - void *cls) +testBitCallback (void *cls, + struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit) { int *arg = cls; if (GNUNET_NO == testBit (bf->bitArray, bit)) @@ -384,14 +393,14 @@ testBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit, * @return the bloomfilter */ struct GNUNET_CONTAINER_BloomFilter * -GNUNET_CONTAINER_bloomfilter_load (const char *filename, unsigned int size, - unsigned int k) +GNUNET_CONTAINER_bloomfilter_load (const char *filename, + size_t size, unsigned int k) { struct GNUNET_CONTAINER_BloomFilter *bf; char *rbuff; - unsigned int pos; + off_t pos; int i; - unsigned int ui; + size_t ui; if ((k == 0) || (size == 0)) return NULL; @@ -406,14 +415,11 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, unsigned int size, /* Try to open a bloomfilter file */ if (filename != NULL) { -#ifndef _MSC_VER - bf->fd = GNUNET_DISK_file_open (filename, O_RDWR | O_CREAT, - S_IRUSR | S_IWUSR); -#else - bf->fd = GNUNET_DISK_file_open (filename, - O_WRONLY | O_CREAT, S_IREAD | S_IWRITE); -#endif - if (-1 == bf->fd) + bf->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE + | GNUNET_DISK_OPEN_CREATE, + GNUNET_DISK_PERM_USER_READ | + GNUNET_DISK_PERM_USER_WRITE); + if (NULL == bf->fh) { GNUNET_free (bf); return NULL; @@ -422,16 +428,24 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, unsigned int size, } else { - bf->fd = -1; bf->filename = NULL; + bf->fh = NULL; } /* Alloc block */ bf->bitArray = GNUNET_malloc_large (size); + if (bf->bitArray == NULL) + { + if (bf->fh != NULL) + GNUNET_DISK_file_close (bf->fh); + GNUNET_free_non_null (bf->filename); + GNUNET_free (bf); + return NULL; + } bf->bitArraySize = size; bf->addressesPerElement = k; memset (bf->bitArray, 0, bf->bitArraySize); - if (bf->fd != -1) + if (bf->filename != NULL) { /* Read from the file what bits we can */ rbuff = GNUNET_malloc (BUFFSIZE); @@ -440,7 +454,12 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, unsigned int size, { int res; - res = READ (bf->fd, rbuff, BUFFSIZE); + res = GNUNET_DISK_file_read (bf->fh, rbuff, BUFFSIZE); + if (res == -1) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "read", bf->filename); + } if (res == 0) break; /* is ok! we just did not use that many bits yet */ for (i = 0; i < res; i++) @@ -474,11 +493,11 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, unsigned int size, * @return the bloomfilter */ struct GNUNET_CONTAINER_BloomFilter * -GNUNET_CONTAINER_bloomfilter_init (const char *data, unsigned int size, - unsigned int k) +GNUNET_CONTAINER_bloomfilter_init (const char *data, + size_t size, unsigned int k) { struct GNUNET_CONTAINER_BloomFilter *bf; - unsigned int ui; + size_t ui; if ((k == 0) || (size == 0)) return NULL; @@ -491,9 +510,14 @@ GNUNET_CONTAINER_bloomfilter_init (const char *data, unsigned int size, return NULL; } bf = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_BloomFilter)); - bf->fd = -1; bf->filename = NULL; + bf->fh = NULL; bf->bitArray = GNUNET_malloc_large (size); + if (bf->bitArray == NULL) + { + GNUNET_free (bf); + return NULL; + } bf->bitArraySize = size; bf->addressesPerElement = k; if (data != NULL) @@ -508,13 +532,14 @@ GNUNET_CONTAINER_bloomfilter_init (const char *data, unsigned int size, * Copy the raw data of this bloomfilter into * the given data array. * + * @param bf bloomfilter to take the raw data from * @param data where to write the data * @param size the size of the given data array * @return GNUNET_SYSERR if the data array is not big enough */ int GNUNET_CONTAINER_bloomfilter_get_raw_data (struct GNUNET_CONTAINER_BloomFilter - *bf, char *data, unsigned int size) + *bf, char *data, size_t size) { if (NULL == bf) return GNUNET_SYSERR; @@ -537,8 +562,8 @@ GNUNET_CONTAINER_bloomfilter_free (struct GNUNET_CONTAINER_BloomFilter *bf) { if (NULL == bf) return; - if (bf->fd != -1) - GNUNET_DISK_file_close (bf->filename, bf->fd); + if (bf->fh != NULL) + GNUNET_DISK_file_close (bf->fh); GNUNET_free_non_null (bf->filename); GNUNET_free (bf->bitArray); GNUNET_free (bf); @@ -556,8 +581,8 @@ GNUNET_CONTAINER_bloomfilter_clear (struct GNUNET_CONTAINER_BloomFilter *bf) return; memset (bf->bitArray, 0, bf->bitArraySize); - if (bf->fd != -1) - makeEmptyFile (bf->fd, bf->bitArraySize * 4); + if (bf->filename != NULL) + makeEmptyFile (bf->fh, bf->bitArraySize * 4); } @@ -603,21 +628,31 @@ GNUNET_CONTAINER_bloomfilter_add (struct GNUNET_CONTAINER_BloomFilter *bf, * data of the given bloom filter. Assumes that * the size of the data array and the current filter * match. + * * @param bf the filter + * @param data the data to or-in + * @param size number of bytes in data */ int GNUNET_CONTAINER_bloomfilter_or (struct GNUNET_CONTAINER_BloomFilter *bf, - const char *data, unsigned int size) + const char *data, size_t size) { unsigned int i; + unsigned int n; + unsigned long long* fc; + const unsigned long long* dc; if (NULL == bf) return GNUNET_YES; if (bf->bitArraySize != size) return GNUNET_SYSERR; - /* FIXME: we could do this 4-8x faster by - going over int/long arrays */ - for (i = 0; i < size; i++) + fc = (unsigned long long*) bf->bitArray; + dc = (const unsigned long long*) data; + n = size / sizeof (unsigned long long); + + for (i = 0; i < n; i++) + fc[i] |= dc[i]; + for (i = n * sizeof(unsigned long long); i < size; i++) bf->bitArray[i] |= data[i]; return GNUNET_OK; } @@ -634,7 +669,7 @@ GNUNET_CONTAINER_bloomfilter_remove (struct GNUNET_CONTAINER_BloomFilter *bf, { if (NULL == bf) return; - if (bf->fd == -1) + if (bf->filename == NULL) return; iterateBits (bf, &decrementBitCallback, NULL, e); } @@ -646,15 +681,15 @@ GNUNET_CONTAINER_bloomfilter_remove (struct GNUNET_CONTAINER_BloomFilter *bf, * * @param bf the filter * @param iterator an iterator over all elements stored in the BF - * @param iterator_arg argument to the iterator function + * @param iterator_cls argument to the iterator function * @param size the new size for the filter * @param k the new number of GNUNET_CRYPTO_hash-function to apply per element */ void GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf, GNUNET_HashCodeIterator iterator, - void *iterator_arg, unsigned int size, - unsigned int k) + void *iterator_cls, + size_t size, unsigned int k) { GNUNET_HashCode hc; unsigned int i; @@ -668,9 +703,9 @@ 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->fd != -1) - makeEmptyFile (bf->fd, bf->bitArraySize * 4); - while (GNUNET_YES == iterator (&hc, iterator_arg)) + if (bf->filename != NULL) + makeEmptyFile (bf->fh, bf->bitArraySize * 4); + while (GNUNET_YES == iterator (iterator_cls, &hc)) GNUNET_CONTAINER_bloomfilter_add (bf, &hc); }