aboutsummaryrefslogtreecommitdiff
path: root/src/set/gnunet-service-set.c
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2015-08-30 20:54:44 +0000
committerFlorian Dold <florian.dold@gmail.com>2015-08-30 20:54:44 +0000
commit2e25d8c868521f318381a8b87c9f8c1c7c402b7c (patch)
treea5d9b8fca78e55da9d8c62ff8fe6d1d480a459e0 /src/set/gnunet-service-set.c
parentc92948f72526fe599680c06cbe80d0ffdc11f597 (diff)
downloadgnunet-2e25d8c868521f318381a8b87c9f8c1c7c402b7c.tar.gz
gnunet-2e25d8c868521f318381a8b87c9f8c1c7c402b7c.zip
add test case for 'GNUNET_SET_copy_lazy', fix bugs
Diffstat (limited to 'src/set/gnunet-service-set.c')
-rw-r--r--src/set/gnunet-service-set.c363
1 files changed, 236 insertions, 127 deletions
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c
index b2ad01d1b..75b33536d 100644
--- a/src/set/gnunet-service-set.c
+++ b/src/set/gnunet-service-set.c
@@ -510,8 +510,24 @@ set_destroy (struct Set *set)
510 } 510 }
511 { 511 {
512 struct SetContent *content; 512 struct SetContent *content;
513 struct PendingMutation *pm;
514 struct PendingMutation *pm_current;
513 515
514 content = set->content; 516 content = set->content;
517
518 // discard any pending mutations that reference this set
519 pm = content->pending_mutations_head;
520 while (NULL != pm)
521 {
522 pm_current = pm;
523 pm = pm->next;
524 if (pm_current-> set == set)
525 GNUNET_CONTAINER_DLL_remove (content->pending_mutations_head,
526 content->pending_mutations_tail,
527 pm_current);
528
529 }
530
515 set->content = NULL; 531 set->content = NULL;
516 GNUNET_assert (0 != content->refcount); 532 GNUNET_assert (0 != content->refcount);
517 content->refcount -= 1; 533 content->refcount -= 1;
@@ -531,7 +547,21 @@ set_destroy (struct Set *set)
531 sets_tail, 547 sets_tail,
532 set); 548 set);
533 549
534 // FIXME: remove from lazy copy requests 550 // remove set from pending copy requests
551 {
552 struct LazyCopyRequest *lcr;
553 lcr = lazy_copy_head;
554 while (NULL != lcr)
555 {
556 struct LazyCopyRequest *lcr_current;
557 lcr_current = lcr;
558 lcr = lcr->next;
559 if (lcr_current->source_set == set)
560 GNUNET_CONTAINER_DLL_remove (lazy_copy_head,
561 lazy_copy_tail,
562 lcr_current);
563 }
564 }
535 565
536 GNUNET_free (set); 566 GNUNET_free (set);
537} 567}
@@ -750,6 +780,140 @@ handle_incoming_msg (struct Operation *op,
750} 780}
751 781
752 782
783static void
784execute_add (struct Set *set,
785 const struct GNUNET_MessageHeader *m)
786{
787 const struct GNUNET_SET_ElementMessage *msg;
788 struct GNUNET_SET_Element el;
789 struct ElementEntry *ee;
790 struct GNUNET_HashCode hash;
791
792 GNUNET_assert (GNUNET_MESSAGE_TYPE_SET_ADD == ntohs (m->type));
793
794 msg = (const struct GNUNET_SET_ElementMessage *) m;
795 el.size = ntohs (m->size) - sizeof *msg;
796 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
797 "Client inserts element of size %u\n",
798 el.size);
799 el.data = &msg[1];
800 GNUNET_CRYPTO_hash (el.data,
801 el.size,
802 &hash);
803
804 ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
805 &hash);
806
807 if (NULL == ee)
808 {
809 ee = GNUNET_malloc (el.size + sizeof *ee);
810 ee->element.size = el.size;
811 memcpy (&ee[1],
812 el.data,
813 el.size);
814 ee->element.data = &ee[1];
815 ee->remote = GNUNET_NO;
816 ee->mutations = NULL;
817 ee->mutations_size = 0;
818 ee->element_hash = hash;
819 } else if (GNUNET_YES == _GSS_is_element_of_set (ee, set)) {
820 /* same element inserted twice */
821 GNUNET_break (0);
822 return;
823 }
824
825 if (0 != set->current_generation)
826 {
827 struct MutationEvent mut = {
828 .generation = set->current_generation,
829 .added = GNUNET_YES
830 };
831 GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
832 ee->mutations_size += 1;
833 }
834
835 GNUNET_break (GNUNET_YES ==
836 GNUNET_CONTAINER_multihashmap_put (set->content->elements,
837 &ee->element_hash,
838 ee,
839 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
840 set->vt->add (set->state, ee);
841}
842
843
844static void
845execute_remove (struct Set *set,
846 const struct GNUNET_MessageHeader *m)
847{
848 const struct GNUNET_SET_ElementMessage *msg;
849 struct GNUNET_SET_Element el;
850 struct ElementEntry *ee;
851 struct GNUNET_HashCode hash;
852
853 GNUNET_assert (GNUNET_MESSAGE_TYPE_SET_REMOVE == ntohs (m->type));
854
855 msg = (const struct GNUNET_SET_ElementMessage *) m;
856 el.size = ntohs (m->size) - sizeof *msg;
857 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
858 "Client removes element of size %u\n",
859 el.size);
860 el.data = &msg[1];
861 GNUNET_CRYPTO_hash (el.data,
862 el.size,
863 &hash);
864 ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
865 &hash);
866 if (NULL == ee)
867 {
868 /* Client tried to remove non-existing element */
869 GNUNET_break (0);
870 return;
871 }
872 if (GNUNET_NO == _GSS_is_element_of_set (ee, set))
873 {
874 /* Client tried to remove element twice */
875 GNUNET_break (0);
876 return;
877 }
878 else if (0 == set->current_generation)
879 {
880 // If current_generation is 0, then there are no running set operations
881 // or lazy copies, thus we can safely remove the element.
882 (void) GNUNET_CONTAINER_multihashmap_remove_all (set->content->elements, &hash);
883 }
884 else
885 {
886 struct MutationEvent mut = {
887 .generation = set->current_generation,
888 .added = GNUNET_NO
889 };
890 GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
891 ee->mutations_size += 1;
892 }
893 set->vt->remove (set->state, ee);
894}
895
896
897
898static void
899execute_mutation (struct Set *set,
900 const struct GNUNET_MessageHeader *m)
901{
902 switch (ntohs (m->type))
903 {
904 case GNUNET_MESSAGE_TYPE_SET_ADD:
905 execute_add (set, m);
906 break;
907 case GNUNET_MESSAGE_TYPE_SET_REMOVE:
908 execute_remove (set, m);
909 break;
910 default:
911 GNUNET_break (0);
912 }
913}
914
915
916
753/** 917/**
754 * Send the next element of a set to the set's client. The next element is given by 918 * Send the next element of a set to the set's client. The next element is given by
755 * the set's current hashmap iterator. The set's iterator will be set to NULL if there 919 * the set's current hashmap iterator. The set's iterator will be set to NULL if there
@@ -777,14 +941,43 @@ send_client_element (struct Set *set)
777 (const void **) &ee); 941 (const void **) &ee);
778 if (GNUNET_NO == ret) 942 if (GNUNET_NO == ret)
779 { 943 {
944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
945 "Iteration on %p done.\n",
946 (void *) set);
780 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_DONE); 947 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_DONE);
781 GNUNET_CONTAINER_multihashmap_iterator_destroy (set->iter); 948 GNUNET_CONTAINER_multihashmap_iterator_destroy (set->iter);
782 set->iter = NULL; 949 set->iter = NULL;
783 set->iteration_id++; 950 set->iteration_id++;
951
952 GNUNET_assert (set->content->iterator_count > 0);
953 set->content->iterator_count -= 1;
954
955 if (0 == set->content->iterator_count)
956 {
957 while (NULL != set->content->pending_mutations_head)
958 {
959 struct PendingMutation *pm;
960
961 pm = set->content->pending_mutations_head;
962 GNUNET_CONTAINER_DLL_remove (set->content->pending_mutations_head,
963 set->content->pending_mutations_tail,
964 pm);
965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
966 "Executing pending mutation on %p.\n",
967 (void *) pm->set);
968 execute_mutation (pm->set, pm->mutation_message);
969 GNUNET_free (pm->mutation_message);
970 GNUNET_free (pm);
971 }
972 }
973
784 } 974 }
785 else 975 else
786 { 976 {
787 GNUNET_assert (NULL != ee); 977 GNUNET_assert (NULL != ee);
978 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
979 "Sending iteration element on %p.\n",
980 (void *) set);
788 ev = GNUNET_MQ_msg_extra (msg, 981 ev = GNUNET_MQ_msg_extra (msg,
789 ee->element.size, 982 ee->element.size,
790 GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT); 983 GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT);
@@ -831,10 +1024,12 @@ handle_client_iterate (void *cls,
831 return; 1024 return;
832 } 1025 }
833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1026 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
834 "Iterating set with %u elements\n", 1027 "Iterating set %p with %u elements\n",
1028 (void *) set,
835 GNUNET_CONTAINER_multihashmap_size (set->content->elements)); 1029 GNUNET_CONTAINER_multihashmap_size (set->content->elements));
836 GNUNET_SERVER_receive_done (client, 1030 GNUNET_SERVER_receive_done (client,
837 GNUNET_OK); 1031 GNUNET_OK);
1032 set->content->iterator_count += 1;
838 set->iter = GNUNET_CONTAINER_multihashmap_iterator_create (set->content->elements); 1033 set->iter = GNUNET_CONTAINER_multihashmap_iterator_create (set->content->elements);
839 send_client_element (set); 1034 send_client_element (set);
840} 1035}
@@ -992,23 +1187,20 @@ handle_client_reject (void *cls,
992} 1187}
993 1188
994 1189
1190
995/** 1191/**
996 * Called when a client wants to add an element to a set it inhabits. 1192 * Called when a client wants to add or remove an element to a set it inhabits.
997 * 1193 *
998 * @param cls unused 1194 * @param cls unused
999 * @param client client that sent the message 1195 * @param client client that sent the message
1000 * @param m message sent by the client 1196 * @param m message sent by the client
1001 */ 1197 */
1002static void 1198static void
1003handle_client_add (void *cls, 1199handle_client_mutation (void *cls,
1004 struct GNUNET_SERVER_Client *client, 1200 struct GNUNET_SERVER_Client *client,
1005 const struct GNUNET_MessageHeader *m) 1201 const struct GNUNET_MessageHeader *m)
1006{ 1202{
1007 struct Set *set; 1203 struct Set *set;
1008 const struct GNUNET_SET_ElementMessage *msg;
1009 struct GNUNET_SET_Element el;
1010 struct ElementEntry *ee;
1011 struct GNUNET_HashCode hash;
1012 1204
1013 set = set_get (client); 1205 set = set_get (client);
1014 if (NULL == set) 1206 if (NULL == set)
@@ -1018,128 +1210,28 @@ handle_client_add (void *cls,
1018 GNUNET_SERVER_client_disconnect (client); 1210 GNUNET_SERVER_client_disconnect (client);
1019 return; 1211 return;
1020 } 1212 }
1213
1021 GNUNET_SERVER_receive_done (client, 1214 GNUNET_SERVER_receive_done (client,
1022 GNUNET_OK); 1215 GNUNET_OK);
1023 msg = (const struct GNUNET_SET_ElementMessage *) m;
1024 el.size = ntohs (m->size) - sizeof *msg;
1025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1026 "Client inserts element of size %u\n",
1027 el.size);
1028 el.data = &msg[1];
1029 GNUNET_CRYPTO_hash (el.data,
1030 el.size,
1031 &hash);
1032 1216
1033 ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements, 1217 if (0 != set->content->iterator_count)
1034 &hash);
1035
1036 if (NULL == ee)
1037 { 1218 {
1038 ee = GNUNET_malloc (el.size + sizeof *ee); 1219 struct PendingMutation *pm;
1039 ee->element.size = el.size;
1040 memcpy (&ee[1],
1041 el.data,
1042 el.size);
1043 ee->element.data = &ee[1];
1044 ee->remote = GNUNET_NO;
1045 ee->mutations = NULL;
1046 ee->mutations_size = 0;
1047 ee->element_hash = hash;
1048 } else if (GNUNET_YES == _GSS_is_element_of_set (ee, set)) {
1049 /* same element inserted twice */
1050 GNUNET_break (0);
1051 return;
1052 }
1053 1220
1054 if (0 != set->current_generation) 1221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1055 { 1222 "Scheduling mutation on set\n");
1056 struct MutationEvent mut = { 1223
1057 .generation = set->current_generation, 1224 pm = GNUNET_new (struct PendingMutation);
1058 .added = GNUNET_YES 1225 pm->mutation_message = GNUNET_copy_message (m);
1059 }; 1226 pm->set = set;
1060 GNUNET_array_append (ee->mutations, ee->mutations_size, mut); 1227 GNUNET_CONTAINER_DLL_insert (set->content->pending_mutations_head,
1061 ee->mutations_size += 1; 1228 set->content->pending_mutations_tail,
1062 } 1229 pm);
1063
1064 GNUNET_break (GNUNET_YES ==
1065 GNUNET_CONTAINER_multihashmap_put (set->content->elements,
1066 &ee->element_hash,
1067 ee,
1068 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1069 set->vt->add (set->state, ee);
1070}
1071
1072
1073/**
1074 * Called when a client wants to remove an element from a set it
1075 * inhabits.
1076 *
1077 * @param cls unused
1078 * @param client client that sent the message
1079 * @param m message sent by the client
1080 */
1081static void
1082handle_client_remove (void *cls,
1083 struct GNUNET_SERVER_Client *client,
1084 const struct GNUNET_MessageHeader *m)
1085{
1086 struct Set *set;
1087 const struct GNUNET_SET_ElementMessage *msg;
1088 struct GNUNET_SET_Element el;
1089 struct ElementEntry *ee;
1090 struct GNUNET_HashCode hash;
1091
1092 set = set_get (client);
1093 if (NULL == set)
1094 {
1095 /* client without a set requested an operation */
1096 GNUNET_break (0);
1097 GNUNET_SERVER_client_disconnect (client);
1098 return;
1099 }
1100 GNUNET_SERVER_receive_done (client,
1101 GNUNET_OK);
1102 msg = (const struct GNUNET_SET_ElementMessage *) m;
1103 el.size = ntohs (m->size) - sizeof *msg;
1104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105 "Client removes element of size %u\n",
1106 el.size);
1107 el.data = &msg[1];
1108 GNUNET_CRYPTO_hash (el.data,
1109 el.size,
1110 &hash);
1111 ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
1112 &hash);
1113 if (NULL == ee)
1114 {
1115 /* Client tried to remove non-existing element */
1116 GNUNET_break (0);
1117 return;
1118 }
1119 if (GNUNET_NO == _GSS_is_element_of_set (ee, set))
1120 {
1121 /* Client tried to remove element twice */
1122 GNUNET_break (0);
1123 return; 1230 return;
1124 } 1231 }
1125 else if (0 == set->current_generation)
1126 {
1127 // If current_generation is 0, then there are no running set operations
1128 // or lazy copies, thus we can safely remove the element.
1129 (void) GNUNET_CONTAINER_multihashmap_remove_all (set->content->elements, &hash);
1130 }
1131 else
1132 {
1133 struct MutationEvent mut = {
1134 .generation = set->current_generation,
1135 .added = GNUNET_NO
1136 };
1137 GNUNET_array_append (ee->mutations, ee->mutations_size, mut);
1138 ee->mutations_size += 1;
1139 }
1140 set->vt->remove (set->state, ee);
1141}
1142 1232
1233 execute_mutation (set, m);
1234}
1143 1235
1144 1236
1145/** 1237/**
@@ -1302,6 +1394,8 @@ handle_client_copy_lazy_prepare (void *cls,
1302{ 1394{
1303 struct Set *set; 1395 struct Set *set;
1304 struct LazyCopyRequest *cr; 1396 struct LazyCopyRequest *cr;
1397 struct GNUNET_MQ_Envelope *ev;
1398 struct GNUNET_SET_CopyLazyResponseMessage *resp_msg;
1305 1399
1306 set = set_get (client); 1400 set = set_get (client);
1307 if (NULL == set) 1401 if (NULL == set)
@@ -1321,8 +1415,19 @@ handle_client_copy_lazy_prepare (void *cls,
1321 GNUNET_CONTAINER_DLL_insert (lazy_copy_head, 1415 GNUNET_CONTAINER_DLL_insert (lazy_copy_head,
1322 lazy_copy_tail, 1416 lazy_copy_tail,
1323 cr); 1417 cr);
1418
1419
1420 ev = GNUNET_MQ_msg (resp_msg,
1421 GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_RESPONSE);
1422 resp_msg->cookie = cr->cookie;
1423 GNUNET_MQ_send (set->client_mq, ev);
1424
1425
1324 GNUNET_SERVER_receive_done (client, 1426 GNUNET_SERVER_receive_done (client,
1325 GNUNET_OK); 1427 GNUNET_OK);
1428
1429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1430 "Client requested lazy copy\n");
1326} 1431}
1327 1432
1328 1433
@@ -1396,11 +1501,12 @@ handle_client_copy_lazy_connect (void *cls,
1396 GNUNET_break (0); 1501 GNUNET_break (0);
1397 GNUNET_free (set); 1502 GNUNET_free (set);
1398 GNUNET_free (cr); 1503 GNUNET_free (cr);
1504 GNUNET_SERVER_client_disconnect (client);
1399 return; 1505 return;
1400 } 1506 }
1401 1507
1402 set->operation = cr->source_set->operation; 1508 set->operation = cr->source_set->operation;
1403 set->state = set->vt->copy_state (set); 1509 set->state = set->vt->copy_state (cr->source_set);
1404 set->content = cr->source_set->content; 1510 set->content = cr->source_set->content;
1405 set->content->refcount += 1; 1511 set->content->refcount += 1;
1406 set->client = client; 1512 set->client = client;
@@ -1413,6 +1519,9 @@ handle_client_copy_lazy_connect (void *cls,
1413 1519
1414 GNUNET_SERVER_receive_done (client, 1520 GNUNET_SERVER_receive_done (client,
1415 GNUNET_OK); 1521 GNUNET_OK);
1522
1523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1524 "Client connected to lazy set\n");
1416} 1525}
1417 1526
1418 1527
@@ -1787,7 +1896,7 @@ run (void *cls,
1787 { &handle_client_iter_ack, NULL, 1896 { &handle_client_iter_ack, NULL,
1788 GNUNET_MESSAGE_TYPE_SET_ITER_ACK, 1897 GNUNET_MESSAGE_TYPE_SET_ITER_ACK,
1789 sizeof (struct GNUNET_SET_IterAckMessage) }, 1898 sizeof (struct GNUNET_SET_IterAckMessage) },
1790 { &handle_client_add, NULL, 1899 { &handle_client_mutation, NULL,
1791 GNUNET_MESSAGE_TYPE_SET_ADD, 1900 GNUNET_MESSAGE_TYPE_SET_ADD,
1792 0}, 1901 0},
1793 { &handle_client_create_set, NULL, 1902 { &handle_client_create_set, NULL,
@@ -1805,7 +1914,7 @@ run (void *cls,
1805 { &handle_client_reject, NULL, 1914 { &handle_client_reject, NULL,
1806 GNUNET_MESSAGE_TYPE_SET_REJECT, 1915 GNUNET_MESSAGE_TYPE_SET_REJECT,
1807 sizeof (struct GNUNET_SET_RejectMessage)}, 1916 sizeof (struct GNUNET_SET_RejectMessage)},
1808 { &handle_client_remove, NULL, 1917 { &handle_client_mutation, NULL,
1809 GNUNET_MESSAGE_TYPE_SET_REMOVE, 1918 GNUNET_MESSAGE_TYPE_SET_REMOVE,
1810 0}, 1919 0},
1811 { &handle_client_cancel, NULL, 1920 { &handle_client_cancel, NULL,