{
struct MutationEvent *mut;
int is_present;
+ unsigned int i;
- if (NULL == ee->mutations)
- return GNUNET_YES;
+ GNUNET_assert (NULL != ee->mutations);
if (GNUNET_YES == is_excluded_generation (query_generation, excluded, excluded_size))
{
return GNUNET_NO;
}
- is_present = GNUNET_YES;
+ is_present = GNUNET_NO;
- // Could be made faster with binary search, but lists
- // are small, so why bother.
- for (mut = ee->mutations; 0 != mut->generation; mut++)
+ /* Could be made faster with binary search, but lists
+ are small, so why bother. */
+ for (i = 0; i < ee->mutations_size; i++)
{
- if ( (mut->generation > query_generation) ||
- (GNUNET_YES == is_excluded_generation (mut->generation, excluded, excluded_size)) )
+ mut = &ee->mutations[i];
+
+ if (mut->generation > query_generation)
{
+ /* The mutation doesn't apply to our generation
+ anymore. We can'b break here, since mutations aren't
+ sorted by generation. */
continue;
}
- // This would be an inconsistency in how we manage mutations.
+ if (GNUNET_YES == is_excluded_generation (mut->generation, excluded, excluded_size))
+ {
+ /* The generation is excluded (because it belongs to another
+ fork via a lazy copy) and thus mutations aren't considered
+ for membership testing. */
+ continue;
+ }
+
+ /* This would be an inconsistency in how we manage mutations. */
if ( (GNUNET_YES == is_present) && (GNUNET_YES == mut->added) )
GNUNET_assert (0);
+ /* Likewise. */
+ if ( (GNUNET_NO == is_present) && (GNUNET_NO == mut->added) )
+ GNUNET_assert (0);
+
is_present = mut->added;
}
- return GNUNET_YES;
+ return is_present;
}
}
+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)
NULL);
GNUNET_CONTAINER_multihashmap_destroy (content->elements);
content->elements = NULL;
+ GNUNET_free (content);
}
}
GNUNET_free_non_null (set->excluded_generations);
ee->mutations = NULL;
ee->mutations_size = 0;
ee->element_hash = hash;
- } else if (GNUNET_YES == _GSS_is_element_of_set (ee, 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,
.added = GNUNET_YES
};
GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
- ee->mutations_size += 1;
}
GNUNET_break (GNUNET_YES ==
&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 = {
.added = GNUNET_NO
};
GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
- ee->mutations_size += 1;
}
set->vt->remove (set->state, ee);
}
struct GNUNET_SET_IterResponseMessage *msg;
GNUNET_assert (NULL != set->iter);
+
+again:
+
ret = GNUNET_CONTAINER_multihashmap_iterator_next (set->iter,
NULL,
(const void **) &ee);
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);
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);
}
GNUNET_array_append (set->excluded_generations,
set->excluded_generations_size,
r);
-
- set->excluded_generations_size += 1;
}
/**
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,
{ &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST, 0},
{ &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF, 0},
{ &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS, 0},
- { &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE, 0},
+ { &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OFFER, 0},
+ { &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY, 0},
+ { &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND, 0},
{ &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS, 0},
+ { &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE, 0},
{ &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE, 0},
{ &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO, 0},
{ &dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF, 0},