aboutsummaryrefslogtreecommitdiff
path: root/src/set
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2015-10-03 22:36:37 +0000
committerFlorian Dold <florian.dold@gmail.com>2015-10-03 22:36:37 +0000
commit8c85bda93a8ece52f02af7f20fb797ad6ac79337 (patch)
tree9170d89d46bae30e60a3f45e852e0469700a7eab /src/set
parent03b62462b4db11dbbb3e121cb6992c8d0fb9152a (diff)
- another fix to generation handling and lazy copying
Diffstat (limited to 'src/set')
-rw-r--r--src/set/gnunet-service-set.c54
-rw-r--r--src/set/gnunet-service-set.h8
-rw-r--r--src/set/test_set.conf2
-rw-r--r--src/set/test_set_union_copy.c17
4 files changed, 58 insertions, 23 deletions
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c
index 754bc96e0c..2f15785149 100644
--- a/src/set/gnunet-service-set.c
+++ b/src/set/gnunet-service-set.c
@@ -341,12 +341,7 @@ is_element_of_generation (struct ElementEntry *ee,
int is_present;
unsigned int i;
- /* If ee->mutations is NULL,
- the element was added in generation 0,
- and there are no removes, thus the element
- is part of any generation we query. */
- if (NULL == ee->mutations)
- return GNUNET_YES;
+ GNUNET_assert (NULL != ee->mutations);
if (GNUNET_YES == is_excluded_generation (query_generation, excluded, excluded_size))
{
@@ -389,7 +384,7 @@ is_element_of_generation (struct ElementEntry *ee,
is_present = mut->added;
}
- return GNUNET_YES;
+ return is_present;
}
@@ -404,6 +399,17 @@ _GSS_is_element_of_set (struct ElementEntry *ee,
}
+static int
+is_element_of_iteration (struct ElementEntry *ee,
+ struct Set *set)
+{
+ return is_element_of_generation (ee,
+ set->iter_generation,
+ set->excluded_generations,
+ set->excluded_generations_size);
+}
+
+
int
_GSS_is_element_of_operation (struct ElementEntry *ee,
struct Operation *op)
@@ -842,11 +848,9 @@ execute_add (struct Set *set,
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,
@@ -888,22 +892,14 @@ execute_remove (struct Set *set,
&hash);
if (NULL == ee)
{
- /* Client tried to remove non-existing element */
- GNUNET_break (0);
+ /* Client tried to remove non-existing element. */
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 = {
@@ -958,6 +954,9 @@ send_client_element (struct Set *set)
struct GNUNET_SET_IterResponseMessage *msg;
GNUNET_assert (NULL != set->iter);
+
+again:
+
ret = GNUNET_CONTAINER_multihashmap_iterator_next (set->iter,
NULL,
(const void **) &ee);
@@ -997,6 +996,10 @@ send_client_element (struct Set *set)
else
{
GNUNET_assert (NULL != ee);
+
+ if (GNUNET_NO == is_element_of_iteration (ee, set))
+ goto again;
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Sending iteration element on %p.\n",
(void *) set);
@@ -1046,13 +1049,15 @@ handle_client_iterate (void *cls,
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Iterating set %p with %u elements\n",
+ "Iterating set %p in gen %u with %u content elements\n",
(void *) set,
+ set->current_generation,
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);
+ set->iter_generation = set->current_generation;
send_client_element (set);
}
@@ -1529,6 +1534,17 @@ handle_client_copy_lazy_connect (void *cls,
set->state = set->vt->copy_state (cr->source_set);
set->content = cr->source_set->content;
set->content->refcount += 1;
+
+ set->current_generation = cr->source_set->current_generation;
+ set->excluded_generations_size = cr->source_set->excluded_generations_size;
+ set->excluded_generations = GNUNET_memdup (cr->source_set->excluded_generations,
+ set->excluded_generations_size * sizeof (struct GenerationRange));
+
+ /* Advance the generation of the new set, so that mutations to the
+ of the cloned set and the source set are independent. */
+ advance_generation (set);
+
+
set->client = client;
set->client_mq = GNUNET_MQ_queue_for_server_client (client);
GNUNET_CONTAINER_DLL_insert (sets_head,
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h
index c3650aa9b0..bc3052f02e 100644
--- a/src/set/gnunet-service-set.h
+++ b/src/set/gnunet-service-set.h
@@ -560,6 +560,9 @@ struct Set
*/
struct GenerationRange *excluded_generations;
+ /**
+ * Number of elements in array @a excluded_generations.
+ */
unsigned int excluded_generations_size;
/**
@@ -574,6 +577,11 @@ struct Set
uint16_t iteration_id;
/**
+ * Generation we're currently iteration over.
+ */
+ unsigned int iter_generation;
+
+ /**
* Content, possibly shared by multiple sets,
* and thus reference counted.
*/
diff --git a/src/set/test_set.conf b/src/set/test_set.conf
index 4f32b88543..ae7708c2d0 100644
--- a/src/set/test_set.conf
+++ b/src/set/test_set.conf
@@ -6,7 +6,7 @@ GNUNET_TEST_HOME = /tmp/test-gnunet-set/
[set]
AUTOSTART = YES
#PREFIX = valgrind
-PREFIX = valgrind --leak-check=full
+#PREFIX = valgrind --leak-check=full
#PREFIX = gdbserver :1234
OPTIONS = -L INFO
diff --git a/src/set/test_set_union_copy.c b/src/set/test_set_union_copy.c
index bb8d576317..47520588a9 100644
--- a/src/set/test_set_union_copy.c
+++ b/src/set/test_set_union_copy.c
@@ -157,7 +157,7 @@ void test_done (void *cls)
void check_new_set_count (void *cls)
{
- check_count (set2, "new set", 2, &test_done, NULL);
+ check_count (set2, "new set", 4, &test_done, NULL);
}
@@ -166,8 +166,13 @@ void copy_done (void *cls, struct GNUNET_SET_Handle *new_set)
printf ("copy done\n");
set2 = new_set;
remove_element_str (set2, "spam");
+ add_element_str (set2, "new1");
+ add_element_str (set2, "new2");
+ remove_element_str (set2, "new2");
+ remove_element_str (set2, "new3");
// Check that set1 didn't change.
- check_count (set1, "old set", 3, &check_new_set_count, NULL);
+ check_count (set1, "old set", 3,
+ &check_new_set_count, NULL);
}
@@ -203,8 +208,14 @@ run (void *cls,
set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
add_element_str (set1, "foo");
add_element_str (set1, "bar");
+ /* duplicate -- ignored */
+ add_element_str (set1, "bar");
remove_element_str (set1, "foo");
+ /* non-existent -- ignored */
+ remove_element_str (set1, "nonexist1");
add_element_str (set1, "spam");
+ /* duplicate -- ignored */
+ remove_element_str (set1, "foo");
add_element_str (set1, "eggs");
check_count (set1, "initial test", 3, &test_copy, NULL);
@@ -214,7 +225,7 @@ run (void *cls,
int
main (int argc, char **argv)
{
- if (0 != GNUNET_TESTING_peer_run ("test_set_api",
+ if (0 != GNUNET_TESTING_peer_run ("test_set_union_copy",
"test_set.conf",
&run, NULL))
{