/**
 * An iterator over a set of items stored in the datastore
 * that deletes until we're happy with respect to our quota.
 *
 * @param cls closure
 * @param key key for the content
 * @param size number of bytes in data
 * @param data content stored
 * @param type type of the content
 * @param priority priority of the content
 * @param anonymity anonymity-level for the content
 * @param expiration expiration time for the content
 * @param uid unique identifier for the datum;
 *        maybe 0 if no unique identifier is available
 *
 * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue
 *         (continue on call to "next", of course),
 *         GNUNET_NO to delete the item and continue (if supported)
 */
static int
quota_processor (void *cls, const struct GNUNET_HashCode * key, uint32_t size,
                 const void *data, enum GNUNET_BLOCK_Type type,
                 uint32_t priority, uint32_t anonymity,
                 struct GNUNET_TIME_Absolute expiration, uint64_t uid)
{
  unsigned long long *need = cls;

  if (NULL == key)
    return GNUNET_SYSERR;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Deleting %llu bytes of low-priority (%u) content `%s' of type %u at %s prior to expiration (still trying to free another %llu bytes)\n",
              (unsigned long long) (size + GNUNET_DATASTORE_ENTRY_OVERHEAD),
	      (unsigned int) priority,
              GNUNET_h2s (key), type,
	      GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration),
						      GNUNET_YES),
	      *need);
  if (size + GNUNET_DATASTORE_ENTRY_OVERHEAD > *need)
    *need = 0;
  else
    *need -= size + GNUNET_DATASTORE_ENTRY_OVERHEAD;
  if (priority > 0)
    min_expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
  else
    min_expiration = expiration;
  GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# bytes purged (low-priority)"),
                            size, GNUNET_YES);
  GNUNET_CONTAINER_bloomfilter_remove (filter, key);
  return GNUNET_NO;
}
示例#2
0
/**
 * Function called by plugins to notify the datacache
 * about content deletions.
 *
 * @param cls closure
 * @param key key of the content that was deleted
 * @param size number of bytes that were made available
 */
static void
env_delete_notify (void *cls, const GNUNET_HashCode * key, size_t size)
{
  struct GNUNET_DATACACHE_Handle *h = cls;

  LOG (GNUNET_ERROR_TYPE_DEBUG, "Content under key `%s' discarded\n",
       GNUNET_h2s (key));
  GNUNET_assert (h->utilization >= size);
  h->utilization -= size;
  GNUNET_CONTAINER_bloomfilter_remove (h->filter, key);
  GNUNET_STATISTICS_update (h->stats, gettext_noop ("# bytes stored"), -size,
                            GNUNET_NO);
}
/**
 * Iterate over the expired items stored in the datastore.
 * Delete all expired items; once we have processed all
 * expired items, re-schedule the "delete_expired" task.
 *
 * @param cls not used
 * @param key key for the content
 * @param size number of bytes in data
 * @param data content stored
 * @param type type of the content
 * @param priority priority of the content
 * @param anonymity anonymity-level for the content
 * @param expiration expiration time for the content
 * @param uid unique identifier for the datum;
 *        maybe 0 if no unique identifier is available
 *
 * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue
 *         (continue on call to "next", of course),
 *         GNUNET_NO to delete the item and continue (if supported)
 */
static int
expired_processor (void *cls, const struct GNUNET_HashCode * key, uint32_t size,
                   const void *data, enum GNUNET_BLOCK_Type type,
                   uint32_t priority, uint32_t anonymity,
                   struct GNUNET_TIME_Absolute expiration, uint64_t uid)
{
  struct GNUNET_TIME_Absolute now;

  if (key == NULL)
  {
    expired_kill_task =
        GNUNET_SCHEDULER_add_delayed_with_priority (MAX_EXPIRE_DELAY,
						    GNUNET_SCHEDULER_PRIORITY_IDLE,
						    &delete_expired, NULL);
    return GNUNET_SYSERR;
  }
  now = GNUNET_TIME_absolute_get ();
  if (expiration.abs_value_us > now.abs_value_us)
  {
    /* finished processing */
    expired_kill_task =
        GNUNET_SCHEDULER_add_delayed_with_priority (MAX_EXPIRE_DELAY,
						    GNUNET_SCHEDULER_PRIORITY_IDLE,
						    &delete_expired, NULL);
    return GNUNET_SYSERR;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Deleting content `%s' of type %u that expired %s ago\n",
              GNUNET_h2s (key), type,
	      GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (expiration,
											   now),
						      GNUNET_YES));
  min_expiration = now;
  GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes expired"), size,
                            GNUNET_YES);
  GNUNET_CONTAINER_bloomfilter_remove (filter, key);
  expired_kill_task =
      GNUNET_SCHEDULER_add_delayed_with_priority (MIN_EXPIRE_DELAY,
						  GNUNET_SCHEDULER_PRIORITY_IDLE,
						  &delete_expired, NULL);
  return GNUNET_NO;
}
int
main (int argc, char *argv[])
{
  struct GNUNET_CONTAINER_BloomFilter *bf;
  struct GNUNET_CONTAINER_BloomFilter *bfi;
  GNUNET_HashCode tmp;
  int i;
  int ok1;
  int ok2;
  int falseok;
  char buf[SIZE];
  struct stat sbuf;

  GNUNET_log_setup ("test-container-bloomfilter", "WARNING", NULL);
  GNUNET_CRYPTO_seed_weak_random (1);
  if (0 == STAT (TESTFILE, &sbuf))
    if (0 != UNLINK (TESTFILE))
      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink", TESTFILE);
  bf = GNUNET_CONTAINER_bloomfilter_load (TESTFILE, SIZE, K);

  for (i = 0; i < 200; i++)
  {
    nextHC (&tmp);
    GNUNET_CONTAINER_bloomfilter_add (bf, &tmp);
  }
  GNUNET_CRYPTO_seed_weak_random (1);
  ok1 = 0;
  for (i = 0; i < 200; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      ok1++;
  }
  if (ok1 != 200)
  {
    printf ("Got %d elements out of" "200 expected after insertion.\n", ok1);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    return -1;
  }
  if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_get_raw_data (bf, buf, SIZE))
  {
    GNUNET_CONTAINER_bloomfilter_free (bf);
    return -1;
  }

  GNUNET_CONTAINER_bloomfilter_free (bf);

  bf = GNUNET_CONTAINER_bloomfilter_load (TESTFILE, SIZE, K);
  GNUNET_assert (bf != NULL);
  bfi = GNUNET_CONTAINER_bloomfilter_init (buf, SIZE, K);
  GNUNET_assert (bfi != NULL);

  GNUNET_CRYPTO_seed_weak_random (1);
  ok1 = 0;
  ok2 = 0;
  for (i = 0; i < 200; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      ok1++;
    if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES)
      ok2++;
  }
  if (ok1 != 200)
  {
    printf ("Got %d elements out of 200 " "expected after reloading.\n", ok1);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  if (ok2 != 200)
  {
    printf ("Got %d elements out of 200 " "expected after initialization.\n",
            ok2);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  GNUNET_CRYPTO_seed_weak_random (1);
  for (i = 0; i < 100; i++)
  {
    nextHC (&tmp);
    GNUNET_CONTAINER_bloomfilter_remove (bf, &tmp);
    GNUNET_CONTAINER_bloomfilter_remove (bfi, &tmp);
  }

  GNUNET_CRYPTO_seed_weak_random (1);

  ok1 = 0;
  ok2 = 0;
  for (i = 0; i < 200; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      ok1++;
    if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES)
      ok2++;
  }

  if (ok1 != 100)
  {
    printf ("Expected 100 elements in loaded filter"
            " after adding 200 and deleting 100, got %d\n", ok1);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }
  if (ok2 != 200)
  {
    printf ("Expected 200 elements in initialized filter"
            " after adding 200 and deleting 100 "
            "(which should do nothing for a filter not backed by a file), got %d\n",
            ok2);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  GNUNET_CRYPTO_seed_weak_random (3);

  GNUNET_CONTAINER_bloomfilter_clear (bf);
  falseok = 0;
  for (i = 0; i < 1000; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      falseok++;
  }
  if (falseok > 0)
  {
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_or (bf, buf, SIZE))
  {
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }

  GNUNET_CRYPTO_seed_weak_random (2);
  i = 20;
  GNUNET_CONTAINER_bloomfilter_resize (bfi, &add_iterator, &i, SIZE * 2, K);

  GNUNET_CRYPTO_seed_weak_random (2);
  i = 20;
  GNUNET_CONTAINER_bloomfilter_resize (bf, &add_iterator, &i, SIZE * 2, K);
  GNUNET_CRYPTO_seed_weak_random (2);

  ok1 = 0;
  ok2 = 0;
  for (i = 0; i < 20; i++)
  {
    nextHC (&tmp);
    if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES)
      ok1++;
    if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES)
      ok2++;
  }

  if (ok1 != 20)
  {
    printf ("Expected 20 elements in resized file-backed filter"
            " after adding 20, got %d\n", ok1);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }
  if (ok2 != 20)
  {
    printf ("Expected 20 elements in resized filter"
            " after adding 20, got %d\n", ok2);
    GNUNET_CONTAINER_bloomfilter_free (bf);
    GNUNET_CONTAINER_bloomfilter_free (bfi);
    return -1;
  }


  GNUNET_CONTAINER_bloomfilter_free (bf);
  GNUNET_CONTAINER_bloomfilter_free (bfi);

  GNUNET_break (0 == UNLINK (TESTFILE));
  return 0;
}