X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcontainer_bloomfilter.c;h=84aab6b17865dd9484911136bec62ec725738c8a;hb=f491ac4fab469421986f77df0bbf79fefc417786;hp=7176bb1e3e96bb534bd3728dbe2506cd91dd137a;hpb=25e636d19d7220430cac2a4fbdda0cac09f0b15d;p=oweals%2Fgnunet.git diff --git a/src/util/container_bloomfilter.c b/src/util/container_bloomfilter.c index 7176bb1e3..84aab6b17 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 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 @@ -44,6 +44,12 @@ #include "gnunet_container_lib.h" #include "gnunet_disk_lib.h" +#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) + +#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) + +#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) + struct GNUNET_CONTAINER_BloomFilter { @@ -177,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; @@ -225,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; @@ -276,33 +282,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; } @@ -319,8 +325,9 @@ makeEmptyFile (const struct GNUNET_DISK_FileHandle *fh, size_t size) * @return GNUNET_YES to continue, GNUNET_NO to stop early */ typedef int (*BitIterator) (void *cls, - const struct GNUNET_CONTAINER_BloomFilter * bf, - unsigned int bit); + const struct GNUNET_CONTAINER_BloomFilter * bf, + unsigned int bit); + /** * Call an iterator for each bit that the bloomfilter @@ -348,10 +355,10 @@ iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, while (slot < (sizeof (GNUNET_HashCode) / sizeof (uint32_t))) { if (GNUNET_YES != - callback (arg, bf, - (((uint32_t *) & tmp[round & 1])[slot]) & - ((bf->bitArraySize * 8) - 1))) - return; + callback (arg, bf, + (((uint32_t *) & tmp[round & 1])[slot]) & + ((bf->bitArraySize * 8) - 1))) + return; slot++; bitCount--; if (bitCount == 0) @@ -367,6 +374,7 @@ iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, } } + /** * Callback: increment bit * @@ -385,6 +393,7 @@ incrementBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, return GNUNET_YES; } + /** * Callback: decrement bit * @@ -403,6 +412,7 @@ decrementBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, return GNUNET_YES; } + /** * Callback: test if all bits are set * @@ -443,9 +453,11 @@ 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; + int must_read; GNUNET_assert (NULL != filename); if ((k == 0) || (size == 0)) @@ -453,22 +465,76 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, if (size < BUFFSIZE) size = BUFFSIZE; ui = 1; - while (ui < size) + while ( (ui < size) && + (ui * 2 > ui) ) ui *= 2; size = ui; /* make sure it's a power of 2 */ 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_OPEN_CREATE, + GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); - if (NULL == bf->fh) + if (NULL != bf->fh) { - GNUNET_free (bf); - return NULL; + /* 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, just create */ + must_read = GNUNET_NO; + bf->fh = + GNUNET_DISK_file_open (filename, + GNUNET_DISK_OPEN_CREATE | + GNUNET_DISK_OPEN_READWRITE, + GNUNET_DISK_PERM_USER_READ | + GNUNET_DISK_PERM_USER_WRITE); + if (NULL == bf->fh) + { + GNUNET_free (bf); + return NULL; + } + 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; + } } bf->filename = GNUNET_strdup (filename); /* Alloc block */ @@ -485,18 +551,24 @@ GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, bf->addressesPerElement = k; memset (bf->bitArray, 0, bf->bitArraySize); + if (GNUNET_YES != must_read) + return bf; /* already done! */ /* Read from the file what bits we can */ rbuff = GNUNET_malloc (BUFFSIZE); pos = 0; - while (pos < size * 8) + while (pos < size * 8LL) { int res; res = GNUNET_DISK_file_read (bf->fh, rbuff, BUFFSIZE); if (res == -1) { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "read", - bf->filename); + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "read", bf->filename); + GNUNET_free (rbuff); + GNUNET_free (bf->filename); + GNUNET_DISK_file_close (bf->fh); + GNUNET_free (bf); + return NULL; } if (res == 0) break; /* is ok! we just did not use that many bits yet */ @@ -587,6 +659,7 @@ GNUNET_CONTAINER_bloomfilter_get_raw_data (const struct return GNUNET_OK; } + /** * Free the space associated with a filter * in memory, flush to drive if needed (do not @@ -606,6 +679,7 @@ GNUNET_CONTAINER_bloomfilter_free (struct GNUNET_CONTAINER_BloomFilter *bf) GNUNET_free (bf); } + /** * Reset a bloom filter to empty. Clears the file on disk. * @@ -619,7 +693,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); } @@ -643,6 +717,7 @@ GNUNET_CONTAINER_bloomfilter_test (const struct GNUNET_CONTAINER_BloomFilter return res; } + /** * Add an element to the filter * @@ -653,7 +728,6 @@ void GNUNET_CONTAINER_bloomfilter_add (struct GNUNET_CONTAINER_BloomFilter *bf, const GNUNET_HashCode * e) { - if (NULL == bf) return; iterateBits (bf, &incrementBitCallback, bf, e); @@ -776,7 +850,7 @@ GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf, 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); }