diff options
author | Florian Dold <florian.dold@gmail.com> | 2015-10-03 22:36:37 +0000 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2015-10-03 22:36:37 +0000 |
commit | 8c85bda93a8ece52f02af7f20fb797ad6ac79337 (patch) | |
tree | 9170d89d46bae30e60a3f45e852e0469700a7eab /src/set | |
parent | 03b62462b4db11dbbb3e121cb6992c8d0fb9152a (diff) |
- another fix to generation handling and lazy copying
Diffstat (limited to 'src/set')
-rw-r--r-- | src/set/gnunet-service-set.c | 54 | ||||
-rw-r--r-- | src/set/gnunet-service-set.h | 8 | ||||
-rw-r--r-- | src/set/test_set.conf | 2 | ||||
-rw-r--r-- | src/set/test_set_union_copy.c | 17 |
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)) { |