[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r36284 - gnunet/src/set
From: |
gnunet |
Subject: |
[GNUnet-SVN] r36284 - gnunet/src/set |
Date: |
Sun, 30 Aug 2015 22:54:44 +0200 |
Author: dold
Date: 2015-08-30 22:54:44 +0200 (Sun, 30 Aug 2015)
New Revision: 36284
Added:
gnunet/src/set/test_set_union_copy.c
Modified:
gnunet/src/set/Makefile.am
gnunet/src/set/gnunet-service-set.c
gnunet/src/set/gnunet-service-set.h
gnunet/src/set/gnunet-service-set_union.c
gnunet/src/set/set_api.c
gnunet/src/set/test_set.conf
Log:
add test case for 'GNUNET_SET_copy_lazy', fix bugs
Modified: gnunet/src/set/Makefile.am
===================================================================
--- gnunet/src/set/Makefile.am 2015-08-30 12:55:04 UTC (rev 36283)
+++ gnunet/src/set/Makefile.am 2015-08-30 20:54:44 UTC (rev 36284)
@@ -67,7 +67,8 @@
check_PROGRAMS = \
test_set_api \
test_set_union_result_full \
- test_set_intersection_result_full
+ test_set_intersection_result_full \
+ test_set_union_copy
endif
if ENABLE_TEST_RUN
@@ -96,5 +97,12 @@
$(top_builddir)/src/testing/libgnunettesting.la \
libgnunetset.la
+test_set_union_copy_SOURCES = \
+ test_set_union_copy.c
+test_set_union_copy_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/testing/libgnunettesting.la \
+ libgnunetset.la
+
EXTRA_DIST = \
test_set.conf
Modified: gnunet/src/set/gnunet-service-set.c
===================================================================
--- gnunet/src/set/gnunet-service-set.c 2015-08-30 12:55:04 UTC (rev 36283)
+++ gnunet/src/set/gnunet-service-set.c 2015-08-30 20:54:44 UTC (rev 36284)
@@ -510,8 +510,24 @@
}
{
struct SetContent *content;
+ struct PendingMutation *pm;
+ struct PendingMutation *pm_current;
content = set->content;
+
+ // discard any pending mutations that reference this set
+ pm = content->pending_mutations_head;
+ while (NULL != pm)
+ {
+ pm_current = pm;
+ pm = pm->next;
+ if (pm_current-> set == set)
+ GNUNET_CONTAINER_DLL_remove (content->pending_mutations_head,
+ content->pending_mutations_tail,
+ pm_current);
+
+ }
+
set->content = NULL;
GNUNET_assert (0 != content->refcount);
content->refcount -= 1;
@@ -531,7 +547,21 @@
sets_tail,
set);
- // FIXME: remove from lazy copy requests
+ // remove set from pending copy requests
+ {
+ struct LazyCopyRequest *lcr;
+ lcr = lazy_copy_head;
+ while (NULL != lcr)
+ {
+ struct LazyCopyRequest *lcr_current;
+ lcr_current = lcr;
+ lcr = lcr->next;
+ if (lcr_current->source_set == set)
+ GNUNET_CONTAINER_DLL_remove (lazy_copy_head,
+ lazy_copy_tail,
+ lcr_current);
+ }
+ }
GNUNET_free (set);
}
@@ -750,6 +780,140 @@
}
+static void
+execute_add (struct Set *set,
+ const struct GNUNET_MessageHeader *m)
+{
+ const struct GNUNET_SET_ElementMessage *msg;
+ struct GNUNET_SET_Element el;
+ struct ElementEntry *ee;
+ struct GNUNET_HashCode hash;
+
+ GNUNET_assert (GNUNET_MESSAGE_TYPE_SET_ADD == ntohs (m->type));
+
+ msg = (const struct GNUNET_SET_ElementMessage *) m;
+ el.size = ntohs (m->size) - sizeof *msg;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client inserts element of size %u\n",
+ el.size);
+ el.data = &msg[1];
+ GNUNET_CRYPTO_hash (el.data,
+ el.size,
+ &hash);
+
+ ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
+ &hash);
+
+ if (NULL == ee)
+ {
+ ee = GNUNET_malloc (el.size + sizeof *ee);
+ ee->element.size = el.size;
+ memcpy (&ee[1],
+ el.data,
+ el.size);
+ ee->element.data = &ee[1];
+ ee->remote = GNUNET_NO;
+ ee->mutations = NULL;
+ ee->mutations_size = 0;
+ ee->element_hash = hash;
+ } else if (GNUNET_YES == _GSS_is_element_of_set (ee, set)) {
+ /* same element inserted twice */
+ GNUNET_break (0);
+ return;
+ }
+
+ if (0 != set->current_generation)
+ {
+ struct MutationEvent mut = {
+ .generation = set->current_generation,
+ .added = GNUNET_YES
+ };
+ GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
+ ee->mutations_size += 1;
+ }
+
+ GNUNET_break (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_put (set->content->elements,
+ &ee->element_hash,
+ ee,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ set->vt->add (set->state, ee);
+}
+
+
+static void
+execute_remove (struct Set *set,
+ const struct GNUNET_MessageHeader *m)
+{
+ const struct GNUNET_SET_ElementMessage *msg;
+ struct GNUNET_SET_Element el;
+ struct ElementEntry *ee;
+ struct GNUNET_HashCode hash;
+
+ GNUNET_assert (GNUNET_MESSAGE_TYPE_SET_REMOVE == ntohs (m->type));
+
+ msg = (const struct GNUNET_SET_ElementMessage *) m;
+ el.size = ntohs (m->size) - sizeof *msg;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client removes element of size %u\n",
+ el.size);
+ el.data = &msg[1];
+ GNUNET_CRYPTO_hash (el.data,
+ el.size,
+ &hash);
+ ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
+ &hash);
+ if (NULL == ee)
+ {
+ /* Client tried to remove non-existing element */
+ GNUNET_break (0);
+ return;
+ }
+ if (GNUNET_NO == _GSS_is_element_of_set (ee, set))
+ {
+ /* Client tried to remove element twice */
+ GNUNET_break (0);
+ return;
+ }
+ else if (0 == set->current_generation)
+ {
+ // If current_generation is 0, then there are no running set operations
+ // or lazy copies, thus we can safely remove the element.
+ (void) GNUNET_CONTAINER_multihashmap_remove_all (set->content->elements,
&hash);
+ }
+ else
+ {
+ struct MutationEvent mut = {
+ .generation = set->current_generation,
+ .added = GNUNET_NO
+ };
+ GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
+ ee->mutations_size += 1;
+ }
+ set->vt->remove (set->state, ee);
+}
+
+
+
+static void
+execute_mutation (struct Set *set,
+ const struct GNUNET_MessageHeader *m)
+{
+ switch (ntohs (m->type))
+ {
+ case GNUNET_MESSAGE_TYPE_SET_ADD:
+ execute_add (set, m);
+ break;
+ case GNUNET_MESSAGE_TYPE_SET_REMOVE:
+ execute_remove (set, m);
+ break;
+ default:
+ GNUNET_break (0);
+ }
+}
+
+
+
/**
* Send the next element of a set to the set's client. The next element is
given by
* the set's current hashmap iterator. The set's iterator will be set to NULL
if there
@@ -777,14 +941,43 @@
(const void **) &ee);
if (GNUNET_NO == ret)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Iteration on %p done.\n",
+ (void *) set);
ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_DONE);
GNUNET_CONTAINER_multihashmap_iterator_destroy (set->iter);
set->iter = NULL;
set->iteration_id++;
+
+ GNUNET_assert (set->content->iterator_count > 0);
+ set->content->iterator_count -= 1;
+
+ if (0 == set->content->iterator_count)
+ {
+ while (NULL != set->content->pending_mutations_head)
+ {
+ struct PendingMutation *pm;
+
+ pm = set->content->pending_mutations_head;
+ GNUNET_CONTAINER_DLL_remove (set->content->pending_mutations_head,
+ set->content->pending_mutations_tail,
+ pm);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Executing pending mutation on %p.\n",
+ (void *) pm->set);
+ execute_mutation (pm->set, pm->mutation_message);
+ GNUNET_free (pm->mutation_message);
+ GNUNET_free (pm);
+ }
+ }
+
}
else
{
GNUNET_assert (NULL != ee);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending iteration element on %p.\n",
+ (void *) set);
ev = GNUNET_MQ_msg_extra (msg,
ee->element.size,
GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT);
@@ -831,10 +1024,12 @@
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Iterating set with %u elements\n",
+ "Iterating set %p with %u elements\n",
+ (void *) set,
GNUNET_CONTAINER_multihashmap_size (set->content->elements));
GNUNET_SERVER_receive_done (client,
GNUNET_OK);
+ set->content->iterator_count += 1;
set->iter = GNUNET_CONTAINER_multihashmap_iterator_create
(set->content->elements);
send_client_element (set);
}
@@ -992,8 +1187,9 @@
}
+
/**
- * Called when a client wants to add an element to a set it inhabits.
+ * Called when a client wants to add or remove an element to a set it inhabits.
*
* @param cls unused
* @param client client that sent the message
@@ -1000,15 +1196,11 @@
* @param m message sent by the client
*/
static void
-handle_client_add (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *m)
+handle_client_mutation (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *m)
{
struct Set *set;
- const struct GNUNET_SET_ElementMessage *msg;
- struct GNUNET_SET_Element el;
- struct ElementEntry *ee;
- struct GNUNET_HashCode hash;
set = set_get (client);
if (NULL == set)
@@ -1018,130 +1210,30 @@
GNUNET_SERVER_client_disconnect (client);
return;
}
+
GNUNET_SERVER_receive_done (client,
GNUNET_OK);
- msg = (const struct GNUNET_SET_ElementMessage *) m;
- el.size = ntohs (m->size) - sizeof *msg;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Client inserts element of size %u\n",
- el.size);
- el.data = &msg[1];
- GNUNET_CRYPTO_hash (el.data,
- el.size,
- &hash);
- ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
- &hash);
-
- if (NULL == ee)
+ if (0 != set->content->iterator_count)
{
- ee = GNUNET_malloc (el.size + sizeof *ee);
- ee->element.size = el.size;
- memcpy (&ee[1],
- el.data,
- el.size);
- ee->element.data = &ee[1];
- ee->remote = GNUNET_NO;
- ee->mutations = NULL;
- ee->mutations_size = 0;
- ee->element_hash = hash;
- } else if (GNUNET_YES == _GSS_is_element_of_set (ee, set)) {
- /* same element inserted twice */
- GNUNET_break (0);
- return;
- }
+ struct PendingMutation *pm;
- if (0 != set->current_generation)
- {
- struct MutationEvent mut = {
- .generation = set->current_generation,
- .added = GNUNET_YES
- };
- GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
- ee->mutations_size += 1;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Scheduling mutation on set\n");
- GNUNET_break (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_put (set->content->elements,
- &ee->element_hash,
- ee,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- set->vt->add (set->state, ee);
-}
-
-
-/**
- * Called when a client wants to remove an element from a set it
- * inhabits.
- *
- * @param cls unused
- * @param client client that sent the message
- * @param m message sent by the client
- */
-static void
-handle_client_remove (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *m)
-{
- struct Set *set;
- const struct GNUNET_SET_ElementMessage *msg;
- struct GNUNET_SET_Element el;
- struct ElementEntry *ee;
- struct GNUNET_HashCode hash;
-
- set = set_get (client);
- if (NULL == set)
- {
- /* client without a set requested an operation */
- GNUNET_break (0);
- GNUNET_SERVER_client_disconnect (client);
+ pm = GNUNET_new (struct PendingMutation);
+ pm->mutation_message = GNUNET_copy_message (m);
+ pm->set = set;
+ GNUNET_CONTAINER_DLL_insert (set->content->pending_mutations_head,
+ set->content->pending_mutations_tail,
+ pm);
return;
}
- GNUNET_SERVER_receive_done (client,
- GNUNET_OK);
- msg = (const struct GNUNET_SET_ElementMessage *) m;
- el.size = ntohs (m->size) - sizeof *msg;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Client removes element of size %u\n",
- el.size);
- el.data = &msg[1];
- GNUNET_CRYPTO_hash (el.data,
- el.size,
- &hash);
- ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
- &hash);
- if (NULL == ee)
- {
- /* Client tried to remove non-existing element */
- GNUNET_break (0);
- return;
- }
- if (GNUNET_NO == _GSS_is_element_of_set (ee, set))
- {
- /* Client tried to remove element twice */
- GNUNET_break (0);
- return;
- }
- else if (0 == set->current_generation)
- {
- // If current_generation is 0, then there are no running set operations
- // or lazy copies, thus we can safely remove the element.
- (void) GNUNET_CONTAINER_multihashmap_remove_all (set->content->elements,
&hash);
- }
- else
- {
- struct MutationEvent mut = {
- .generation = set->current_generation,
- .added = GNUNET_NO
- };
- GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
- ee->mutations_size += 1;
- }
- set->vt->remove (set->state, ee);
+
+ execute_mutation (set, m);
}
-
/**
* Advance the current generation of a set,
* adding exclusion ranges if necessary.
@@ -1302,6 +1394,8 @@
{
struct Set *set;
struct LazyCopyRequest *cr;
+ struct GNUNET_MQ_Envelope *ev;
+ struct GNUNET_SET_CopyLazyResponseMessage *resp_msg;
set = set_get (client);
if (NULL == set)
@@ -1321,8 +1415,19 @@
GNUNET_CONTAINER_DLL_insert (lazy_copy_head,
lazy_copy_tail,
cr);
+
+
+ ev = GNUNET_MQ_msg (resp_msg,
+ GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_RESPONSE);
+ resp_msg->cookie = cr->cookie;
+ GNUNET_MQ_send (set->client_mq, ev);
+
+
GNUNET_SERVER_receive_done (client,
GNUNET_OK);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client requested lazy copy\n");
}
@@ -1396,11 +1501,12 @@
GNUNET_break (0);
GNUNET_free (set);
GNUNET_free (cr);
+ GNUNET_SERVER_client_disconnect (client);
return;
}
set->operation = cr->source_set->operation;
- set->state = set->vt->copy_state (set);
+ set->state = set->vt->copy_state (cr->source_set);
set->content = cr->source_set->content;
set->content->refcount += 1;
set->client = client;
@@ -1413,6 +1519,9 @@
GNUNET_SERVER_receive_done (client,
GNUNET_OK);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client connected to lazy set\n");
}
@@ -1787,7 +1896,7 @@
{ &handle_client_iter_ack, NULL,
GNUNET_MESSAGE_TYPE_SET_ITER_ACK,
sizeof (struct GNUNET_SET_IterAckMessage) },
- { &handle_client_add, NULL,
+ { &handle_client_mutation, NULL,
GNUNET_MESSAGE_TYPE_SET_ADD,
0},
{ &handle_client_create_set, NULL,
@@ -1805,7 +1914,7 @@
{ &handle_client_reject, NULL,
GNUNET_MESSAGE_TYPE_SET_REJECT,
sizeof (struct GNUNET_SET_RejectMessage)},
- { &handle_client_remove, NULL,
+ { &handle_client_mutation, NULL,
GNUNET_MESSAGE_TYPE_SET_REMOVE,
0},
{ &handle_client_cancel, NULL,
Modified: gnunet/src/set/gnunet-service-set.h
===================================================================
--- gnunet/src/set/gnunet-service-set.h 2015-08-30 12:55:04 UTC (rev 36283)
+++ gnunet/src/set/gnunet-service-set.h 2015-08-30 20:54:44 UTC (rev 36284)
@@ -437,6 +437,25 @@
struct GNUNET_CONTAINER_MultiHashMap *elements;
unsigned int latest_generation;
+
+ /**
+ * Mutations requested by the client that we're
+ * unable to execute right now because we're iterating
+ * over the underlying hash map of elements.
+ */
+ struct PendingMutation *pending_mutations_head;
+
+ /**
+ * Mutations requested by the client that we're
+ * unable to execute right now because we're iterating
+ * over the underlying hash map of elements.
+ */
+ struct PendingMutation *pending_mutations_tail;
+
+ /**
+ * Number of concurrently active iterators.
+ */
+ int iterator_count;
};
@@ -454,6 +473,22 @@
};
+struct PendingMutation
+{
+ struct PendingMutation *prev;
+ struct PendingMutation *next;
+
+ struct Set *set;
+
+ /**
+ * Message that describes the desired mutation.
+ * May only be a GNUNET_MESSAGE_TYPE_SET_ADD or
+ * GNUNET_MESSAGE_TYPE_SET_REMOVE.
+ */
+ struct GNUNET_MessageHeader *mutation_message;
+};
+
+
/**
* A set that supports a specific operation with other peers.
*/
@@ -540,7 +575,6 @@
* and thus reference counted.
*/
struct SetContent *content;
-
};
Modified: gnunet/src/set/gnunet-service-set_union.c
===================================================================
--- gnunet/src/set/gnunet-service-set_union.c 2015-08-30 12:55:04 UTC (rev
36283)
+++ gnunet/src/set/gnunet-service-set_union.c 2015-08-30 20:54:44 UTC (rev
36284)
@@ -1452,7 +1452,18 @@
finish_and_destroy (op);
}
+static struct SetState *
+union_copy_state (struct Set *set)
+{
+ struct SetState *new_state;
+ new_state = GNUNET_new (struct SetState);
+ GNUNET_assert ( (NULL != set->state) && (NULL != set->state->se) );
+ new_state->se = strata_estimator_dup (set->state->se);
+
+ return new_state;
+}
+
/**
* Get the table with implementing functions for
* set union.
@@ -1472,6 +1483,7 @@
.accept = &union_accept,
.peer_disconnect = &union_peer_disconnect,
.cancel = &union_op_cancel,
+ .copy_state = &union_copy_state,
};
return &union_vt;
Modified: gnunet/src/set/set_api.c
===================================================================
--- gnunet/src/set/set_api.c 2015-08-30 12:55:04 UTC (rev 36283)
+++ gnunet/src/set/set_api.c 2015-08-30 20:54:44 UTC (rev 36284)
@@ -272,6 +272,9 @@
GNUNET_break (0);
return;
}
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Handling response to lazy copy\n");
GNUNET_CONTAINER_DLL_remove (set->copy_req_head,
set->copy_req_tail,
@@ -555,9 +558,6 @@
struct GNUNET_SET_CreateMessage *create_msg;
struct GNUNET_SET_CopyLazyConnectMessage *copy_msg;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Creating new set (operation %u)\n",
- op);
set = GNUNET_new (struct GNUNET_SET_Handle);
set->client = GNUNET_CLIENT_connect ("set", cfg);
set->cfg = cfg;
@@ -574,6 +574,9 @@
if (NULL == cookie)
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating new set (operation %u)\n",
+ op);
mqm = GNUNET_MQ_msg (create_msg,
GNUNET_MESSAGE_TYPE_SET_CREATE);
create_msg->operation = htonl (op);
@@ -580,6 +583,9 @@
}
else
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating new set (lazy copy)\n",
+ op);
mqm = GNUNET_MQ_msg (copy_msg,
GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_CONNECT);
copy_msg->cookie = *cookie;
Modified: gnunet/src/set/test_set.conf
===================================================================
--- gnunet/src/set/test_set.conf 2015-08-30 12:55:04 UTC (rev 36283)
+++ gnunet/src/set/test_set.conf 2015-08-30 20:54:44 UTC (rev 36284)
@@ -1,4 +1,3 @@
-# @INLINE@ test_set_defaults.conf
[PATHS]
GNUNET_TEST_HOME = /tmp/test-gnunet-set/
@@ -8,11 +7,52 @@
#PREFIX = valgrind
#PREFIX = valgrind -v --leak-check=full
#PREFIX = gdbserver :1234
-#OPTIONS = -L INFO
+OPTIONS = -L INFO
[transport]
+PLUGINS = unix
OPTIONS = -LERROR
-[testbed]
-OVERLAY_TOPOLOGY = CLIQUE
+[nat]
+RETURN_LOCAL_ADDRESSES = YES
+DISABLEV6 = YES
+USE_LOCALADDR = YES
+[peerinfo]
+NO_IO = YES
+
+[nse]
+WORKBITS = 0
+
+[hostlist]
+FORCESTART = NO
+AUTOSTART = NO
+
+[fs]
+FORCESTART = NO
+AUTOSTART = NO
+
+[vpn]
+FORCESTART = NO
+AUTOSTART = NO
+
+[revocation]
+FORCESTART = NO
+AUTOSTART = NO
+
+[gns]
+FORCESTART = NO
+AUTOSTART = NO
+
+[namestore]
+FORCESTART = NO
+AUTOSTART = NO
+
+[namecache]
+FORCESTART = NO
+AUTOSTART = NO
+
+[topology]
+FORCESTART = NO
+AUTOSTART = NO
+
Added: gnunet/src/set/test_set_union_copy.c
===================================================================
--- gnunet/src/set/test_set_union_copy.c (rev 0)
+++ gnunet/src/set/test_set_union_copy.c 2015-08-30 20:54:44 UTC (rev
36284)
@@ -0,0 +1,225 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2015 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
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file set/test_set_union_copy.c
+ * @brief testcase for lazy copying of union sets
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_common.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_set_service.h"
+
+
+/**
+ * Value to return from #main().
+ */
+static int ret;
+
+static struct GNUNET_PeerIdentity local_id;
+
+static struct GNUNET_SET_Handle *set1;
+
+static struct GNUNET_SET_Handle *set2;
+
+static const struct GNUNET_CONFIGURATION_Handle *config;
+
+
+static void
+add_element_str (struct GNUNET_SET_Handle *set, char *str)
+{
+ struct GNUNET_SET_Element element;
+
+ element.element_type = 0;
+ element.data = str;
+ element.size = strlen (str);
+
+ GNUNET_SET_add_element (set, &element, NULL, NULL);
+}
+
+
+static void
+remove_element_str (struct GNUNET_SET_Handle *set, char *str)
+{
+ struct GNUNET_SET_Element element;
+
+ element.element_type = 0;
+ element.data = str;
+ element.size = strlen (str);
+
+ GNUNET_SET_remove_element (set, &element, NULL, NULL);
+}
+
+
+/**
+ * Signature of the main function of a task.
+ *
+ * @param cls closure
+ * @param tc context information (why was this task triggered now)
+ */
+static void
+timeout_fail (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+ GNUNET_SCHEDULER_shutdown ();
+ ret = 1;
+}
+
+typedef void (*Continuation) (void *cls);
+
+
+struct CountIterClosure
+{
+ unsigned int expected_count;
+ unsigned int ongoing_count;
+ Continuation cont;
+ void *cont_cls;
+ char *what;
+};
+
+
+static int
+check_count_iter (void *cls,
+ const struct GNUNET_SET_Element *element)
+{
+ struct CountIterClosure *ci_cls = cls;
+
+ if (NULL == element)
+ {
+ if (ci_cls->expected_count != ci_cls->ongoing_count)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected count (what: %s) to be %u, but it's actually %u\n",
+ ci_cls->what,
+ ci_cls->expected_count, ci_cls->ongoing_count);
+ ret = 1;
+ return GNUNET_NO;
+ }
+ ci_cls->cont (ci_cls->cont_cls);
+ return GNUNET_NO;
+ }
+
+ ci_cls->ongoing_count += 1;
+ return GNUNET_YES;
+}
+
+
+
+void
+check_count (struct GNUNET_SET_Handle *set,
+ char *what,
+ unsigned int expected_count,
+ Continuation cont,
+ void *cont_cls)
+{
+ struct CountIterClosure *ci_cls = GNUNET_new (struct CountIterClosure);
+
+ ci_cls->expected_count = expected_count;
+ ci_cls->ongoing_count = 0;
+ ci_cls->cont = cont;
+ ci_cls->cont_cls = cont_cls;
+ ci_cls->what = what;
+
+ GNUNET_assert (GNUNET_YES == GNUNET_SET_iterate (set, check_count_iter,
ci_cls));
+}
+
+
+void test_done (void *cls)
+{
+ if (NULL != set1)
+ GNUNET_SET_destroy (set1);
+ if (NULL != set2)
+ GNUNET_SET_destroy (set2);
+
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+void check_new_set_count (void *cls)
+{
+ check_count (set2, "new set", 2, &test_done, NULL);
+}
+
+
+void copy_done (void *cls, struct GNUNET_SET_Handle *new_set)
+{
+ printf ("copy done\n");
+ set2 = new_set;
+ remove_element_str (set2, "spam");
+ // Check that set1 didn't change.
+ check_count (set1, "old set", 3, &check_new_set_count, NULL);
+}
+
+
+void test_copy (void *cls)
+{
+ printf ("about to copy\n");
+ GNUNET_SET_copy_lazy (set1, copy_done, NULL);
+}
+
+
+
+/**
+ * Signature of the 'main' function for a (single-peer) testcase that
+ * is run using 'GNUNET_TESTING_peer_run'.
+ *
+ * @param cls closure
+ * @param cfg configuration of the peer that was started
+ * @param peer identity of the peer that was created
+ */
+static void
+run (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_TESTING_Peer *peer)
+{
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 5),
+ &timeout_fail,
+ NULL);
+
+ config = cfg;
+ GNUNET_TESTING_peer_get_identity (peer,
+ &local_id);
+
+ set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
+ add_element_str (set1, "foo");
+ add_element_str (set1, "bar");
+ remove_element_str (set1, "foo");
+ add_element_str (set1, "spam");
+ add_element_str (set1, "eggs");
+
+ check_count (set1, "initial test", 3, &test_copy, NULL);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ if (0 != GNUNET_TESTING_peer_run ("test_set_api",
+ "test_set.conf",
+ &run, NULL))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failed to start testing peer\n");
+ return 1;
+ }
+ return ret;
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r36284 - gnunet/src/set,
gnunet <=