3 /* ddt_exchange - send/recv data described */
5 /* Copyright (c) 2003-2009 The SimGrid Team. All rights reserved. */
7 /* This program is free software; you can redistribute it and/or modify it
8 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include "gras/DataDesc/datadesc_private.h"
12 #include "gras/Transport/transport_interface.h" /* gras_trp_send/recv */
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_ddt_exchange, gras_ddt,
15 "Sending data over the network");
16 const char *gras_datadesc_cat_names[9] = {
18 "scalar", "struct", "union", "ref", "array", "ignored",
22 static gras_datadesc_type_t int_type = NULL;
23 static gras_datadesc_type_t pointer_type = NULL;
25 static XBT_INLINE void
26 gras_dd_send_int(gras_socket_t sock, int *i, int stable)
30 int_type = gras_datadesc_by_name("int");
34 DEBUG1("send_int(%u)", *i);
35 gras_trp_send(sock, (char *) i, int_type->size[GRAS_THISARCH], stable);
38 static XBT_INLINE void
39 gras_dd_recv_int(gras_socket_t sock, int r_arch, int *i)
43 int_type = gras_datadesc_by_name("int");
47 if (int_type->size[GRAS_THISARCH] >= int_type->size[r_arch]) {
48 gras_trp_recv(sock, (char *) i, int_type->size[r_arch]);
49 if (r_arch != GRAS_THISARCH)
50 gras_dd_convert_elm(int_type, 1, r_arch, i, i);
52 void *ptr = xbt_malloc(int_type->size[r_arch]);
54 gras_trp_recv(sock, (char *) ptr, int_type->size[r_arch]);
55 if (r_arch != GRAS_THISARCH)
56 gras_dd_convert_elm(int_type, 1, r_arch, ptr, i);
59 DEBUG1("recv_int(%u)", *i);
63 * Note: here we suppose that the remote NULL is a sequence
64 * of 'length' bytes set to 0.
65 * FIXME: Check in configure?
67 static XBT_INLINE int gras_dd_is_r_null(char **r_ptr, long int length)
71 for (i = 0; i < length; i++) {
72 if (((unsigned char *) r_ptr)[i]) {
80 static XBT_INLINE void gras_dd_alloc_ref(xbt_dict_t refs, long int size, char **r_ref, long int r_len, /* pointer_type->size[r_arch] */
81 char **l_ref, int detect_cycle)
85 xbt_assert1(size > 0, "Cannot allocate %ld bytes!", size);
86 l_data = xbt_malloc((size_t) size);
89 DEBUG5("alloc_ref: l_data=%p, &l_data=%p; r_ref=%p; *r_ref=%p, r_len=%ld",
90 (void *) l_data, (void *) &l_data,
91 (void *) r_ref, (void *) (r_ref ? *r_ref : NULL), r_len);
92 if (detect_cycle && r_ref && !gras_dd_is_r_null(r_ref, r_len)) {
93 void *ptr = xbt_malloc(sizeof(void *));
95 memcpy(ptr, l_ref, sizeof(void *));
97 DEBUG2("Insert l_ref=%p under r_ref=%p", *(void **) ptr,
101 xbt_dict_set_ext(refs, (const char *) r_ref, r_len, ptr, xbt_free_f);
106 gras_datadesc_memcpy_rec(gras_cbps_t state,
108 gras_datadesc_type_t type,
109 char *src, char *dst, int subsize, int detect_cycle)
115 gras_datadesc_type_t sub_type; /* type on which we recurse */
118 VERB5("Copy a %s (%s) from %p to %p (local sizeof=%ld)",
119 type->name, gras_datadesc_cat_names[type->category_code],
120 src, dst, type->size[GRAS_THISARCH]);
123 type->send(type, state, src);
126 switch (type->category_code) {
127 case e_gras_datadesc_type_cat_scalar:
128 memcpy(dst, src, type->size[GRAS_THISARCH]);
129 count += type->size[GRAS_THISARCH];
132 case e_gras_datadesc_type_cat_struct:{
133 gras_dd_cat_struct_t struct_data;
134 gras_dd_cat_field_t field;
138 struct_data = type->category.struct_data;
139 xbt_assert1(struct_data.closed,
140 "Please call gras_datadesc_declare_struct_close on %s before copying it",
142 VERB1(">> Copy all fields of the structure %s", type->name);
143 xbt_dynar_foreach(struct_data.fields, cpt, field) {
144 field_src = src + field->offset[GRAS_THISARCH];
145 field_dst = dst + field->offset[GRAS_THISARCH];
147 sub_type = field->type;
150 field->send(type, state, field_src);
152 DEBUG1("Copy field %s", field->name);
154 gras_datadesc_memcpy_rec(state, refs, sub_type, field_src,
155 field_dst, 0, detect_cycle
158 if (XBT_LOG_ISENABLED(gras_ddt_exchange, xbt_log_priority_verbose)) {
159 if (sub_type == gras_datadesc_by_name("unsigned int")) {
160 VERB2("Copied value for field '%s': %d (type: unsigned int)",
161 field->name, *(unsigned int *) field_dst);
162 } else if (sub_type == gras_datadesc_by_name("int")) {
163 VERB2("Copied value for field '%s': %d (type: int)", field->name,
166 } else if (sub_type == gras_datadesc_by_name("unsigned long int")) {
168 ("Copied value for field '%s': %ld (type: unsigned long int)",
169 field->name, *(unsigned long int *) field_dst);
170 } else if (sub_type == gras_datadesc_by_name("long int")) {
171 VERB2("Copied value for field '%s': %ld (type: long int)",
172 field->name, *(long int *) field_dst);
174 } else if (sub_type == gras_datadesc_by_name("string")) {
175 VERB2("Copied value for field '%s': '%s' (type: string)",
176 field->name, *(char **) field_dst);
178 VERB1("Copied a value for field '%s' (type not scalar?)",
184 VERB1("<< Copied all fields of the structure %s", type->name);
189 case e_gras_datadesc_type_cat_union:{
190 gras_dd_cat_union_t union_data;
191 gras_dd_cat_field_t field = NULL;
192 unsigned int field_num;
194 union_data = type->category.union_data;
196 xbt_assert1(union_data.closed,
197 "Please call gras_datadesc_declare_union_close on %s before copying it",
199 /* retrieve the field number */
200 field_num = union_data.selector(type, state, src);
202 xbt_assert1(field_num > 0,
203 "union field selector of %s gave a negative value",
206 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
207 "union field selector of %s returned %d but there is only %lu fields",
208 type->name, field_num, xbt_dynar_length(union_data.fields));
210 /* Copy the content */
212 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
213 sub_type = field->type;
216 field->send(type, state, src);
218 count += gras_datadesc_memcpy_rec(state, refs, sub_type, src, dst, 0,
219 detect_cycle || sub_type->cycle);
224 case e_gras_datadesc_type_cat_ref:{
225 gras_dd_cat_ref_t ref_data;
228 int reference_is_to_cpy;
230 ref_data = type->category.ref_data;
232 /* Detect the referenced type */
233 sub_type = ref_data.type;
234 if (sub_type == NULL) {
235 sub_type = (*ref_data.selector) (type, state, src);
238 /* Send the pointed data only if not already sent */
239 if (*(void **) src == NULL) {
240 VERB0("Not copying NULL referenced data");
241 *(void **) dst = NULL;
244 o_ref = (char **) src;
246 reference_is_to_cpy = 0;
249 /* return ignored. Just checking whether it's known or not */
250 n_ref = xbt_dict_get_ext(refs, (char *) o_ref, sizeof(char *));
252 reference_is_to_cpy = 1;
256 if (e.category != not_found_error)
258 reference_is_to_cpy = 1;
262 if (reference_is_to_cpy) {
263 int subsubcount = -1;
264 void *l_referenced = NULL;
265 VERB2("Copy a ref to '%s' referenced at %p", sub_type->name,
269 pointer_type = gras_datadesc_by_name("data pointer");
270 xbt_assert(pointer_type);
273 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
274 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
275 gras_dd_cat_array_t array_data = sub_type->category.array_data;
276 gras_datadesc_type_t subsub_type;
278 subsub_type = array_data.type;
279 subsubcount = array_data.fixed_size;
280 if (subsubcount == -1)
281 subsubcount = array_data.dynamic_size(subsub_type, state, *o_ref);
283 if (subsubcount != 0)
284 gras_dd_alloc_ref(refs,
285 subsub_type->size[GRAS_THISARCH] * subsubcount,
286 o_ref, pointer_type->size[GRAS_THISARCH],
287 (char **) &l_referenced, detect_cycle);
289 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
290 o_ref, pointer_type->size[GRAS_THISARCH],
291 (char **) &l_referenced, detect_cycle);
294 count += gras_datadesc_memcpy_rec(state, refs, sub_type,
295 *o_ref, (char *) l_referenced,
296 subsubcount, detect_cycle
299 *(void **) dst = l_referenced;
300 VERB3("'%s' previously referenced at %p now at %p",
301 sub_type->name, *(void **) o_ref, l_referenced);
305 ("NOT copying data previously referenced @%p (already done, @%p now)",
306 *(void **) o_ref, *(void **) n_ref);
308 *(void **) dst = *n_ref;
314 case e_gras_datadesc_type_cat_array:{
315 gras_dd_cat_array_t array_data;
316 unsigned long int array_count;
321 array_data = type->category.array_data;
323 /* determine and send the element count */
324 array_count = array_data.fixed_size;
325 if (array_count == -1)
326 array_count = subsize;
327 if (array_count == -1) {
328 array_count = array_data.dynamic_size(type, state, src);
329 xbt_assert1(array_count >= 0,
330 "Invalid (negative) array size for type %s", type->name);
333 /* send the content */
334 sub_type = array_data.type;
335 elm_size = sub_type->aligned_size[GRAS_THISARCH];
336 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
337 VERB1("Array of %ld scalars, copy it in one shot", array_count);
338 memcpy(dst, src, sub_type->aligned_size[GRAS_THISARCH] * array_count);
339 count += sub_type->aligned_size[GRAS_THISARCH] * array_count;
340 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
341 sub_type->category.array_data.fixed_size > 0 &&
342 sub_type->category.array_data.type->category_code ==
343 e_gras_datadesc_type_cat_scalar) {
345 VERB1("Array of %ld fixed array of scalars, copy it in one shot",
348 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
349 * array_count * sub_type->category.array_data.fixed_size);
351 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
352 * array_count * sub_type->category.array_data.fixed_size;
355 VERB1("Array of %ld stuff, copy it in one after the other",
357 for (cpt = 0; cpt < array_count; cpt++) {
358 VERB2("Copy the %dth stuff out of %ld", cpt, array_count);
360 gras_datadesc_memcpy_rec(state, refs, sub_type, src_ptr, dst_ptr,
361 0, detect_cycle || sub_type->cycle);
370 xbt_die("Invalid type");
377 * gras_datadesc_memcpy:
379 * Copy the data pointed by src and described by type
380 * to a new location, and store a pointer to it in dst.
383 int gras_datadesc_memcpy(gras_datadesc_type_t type, void *src, void *dst)
386 static gras_cbps_t state = NULL;
387 static xbt_dict_t refs = NULL; /* all references already sent */
390 xbt_assert0(type, "called with NULL type descriptor");
392 DEBUG3("Memcopy a %s from %p to %p", gras_datadesc_get_name(type), src,
395 state = gras_cbps_new();
396 refs = xbt_dict_new();
401 gras_datadesc_memcpy_rec(state, refs, type, (char *) src, (char *) dst,
404 xbt_dict_reset(refs);
405 gras_cbps_reset(state);
413 *** Direct use functions
417 gras_datadesc_send_rec(gras_socket_t sock,
420 gras_datadesc_type_t type,
421 char *data, int detect_cycle)
426 gras_datadesc_type_t sub_type; /* type on which we recurse */
428 VERB2("Send a %s (%s)",
429 type->name, gras_datadesc_cat_names[type->category_code]);
431 if (!strcmp(type->name, "string"))
432 VERB1("value: '%s'", *(char **) data);
435 type->send(type, state, data);
436 DEBUG0("Run the emission callback");
439 switch (type->category_code) {
440 case e_gras_datadesc_type_cat_scalar:
441 gras_trp_send(sock, data, type->size[GRAS_THISARCH], 1);
444 case e_gras_datadesc_type_cat_struct:{
445 gras_dd_cat_struct_t struct_data;
446 gras_dd_cat_field_t field;
449 struct_data = type->category.struct_data;
450 xbt_assert1(struct_data.closed,
451 "Please call gras_datadesc_declare_struct_close on %s before sending it",
453 VERB1(">> Send all fields of the structure %s", type->name);
454 xbt_dynar_foreach(struct_data.fields, cpt, field) {
456 field_data += field->offset[GRAS_THISARCH];
458 sub_type = field->type;
461 DEBUG1("Run the emission callback of field %s", field->name);
462 field->send(type, state, field_data);
465 VERB1("Send field %s", field->name);
466 gras_datadesc_send_rec(sock, state, refs, sub_type, field_data,
467 detect_cycle || sub_type->cycle);
470 VERB1("<< Sent all fields of the structure %s", type->name);
475 case e_gras_datadesc_type_cat_union:{
476 gras_dd_cat_union_t union_data;
477 gras_dd_cat_field_t field = NULL;
480 union_data = type->category.union_data;
482 xbt_assert1(union_data.closed,
483 "Please call gras_datadesc_declare_union_close on %s before sending it",
485 /* retrieve the field number */
486 field_num = union_data.selector(type, state, data);
488 xbt_assert1(field_num > 0,
489 "union field selector of %s gave a negative value",
492 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
493 "union field selector of %s returned %d but there is only %lu fields",
494 type->name, field_num, xbt_dynar_length(union_data.fields));
496 /* Send the field number */
497 gras_dd_send_int(sock, &field_num, 0 /* not stable */ );
499 /* Send the content */
501 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
502 sub_type = field->type;
505 field->send(type, state, data);
507 gras_datadesc_send_rec(sock, state, refs, sub_type, data,
508 detect_cycle || sub_type->cycle);
513 case e_gras_datadesc_type_cat_ref:{
514 gras_dd_cat_ref_t ref_data;
515 void **ref = (void **) data;
516 int reference_is_to_send;
518 ref_data = type->category.ref_data;
520 /* Detect the referenced type and send it to peer if needed */
521 sub_type = ref_data.type;
522 if (sub_type == NULL) {
523 sub_type = (*ref_data.selector) (type, state, data);
524 gras_dd_send_int(sock, &(sub_type->code), 1 /*stable */ );
527 /* Send the actual value of the pointer for cycle handling */
529 pointer_type = gras_datadesc_by_name("data pointer");
530 xbt_assert(pointer_type);
533 gras_trp_send(sock, (char *) data,
534 pointer_type->size[GRAS_THISARCH], 1 /*stable */ );
536 /* Send the pointed data only if not already sent */
537 if (*(void **) data == NULL) {
538 VERB0("Not sending NULL referenced data");
542 reference_is_to_send = 0;
545 /* return ignored. Just checking whether it's known or not */
546 xbt_dict_get_ext(refs, (char *) ref, sizeof(char *));
548 reference_is_to_send = 1;
551 if (e.category != not_found_error)
553 reference_is_to_send = 1;
557 if (reference_is_to_send) {
558 VERB1("Sending data referenced at %p", (void *) *ref);
560 xbt_dict_set_ext(refs, (char *) ref, sizeof(void *), ref, NULL);
561 gras_datadesc_send_rec(sock, state, refs, sub_type, *ref,
562 detect_cycle || sub_type->cycle);
565 VERB1("Not sending data referenced at %p (already done)",
572 case e_gras_datadesc_type_cat_array:{
573 gras_dd_cat_array_t array_data;
578 array_data = type->category.array_data;
580 /* determine and send the element count */
581 count = array_data.fixed_size;
583 count = array_data.dynamic_size(type, state, data);
584 xbt_assert1(count >= 0,
585 "Invalid (negative) array size for type %s", type->name);
586 gras_dd_send_int(sock, &count, 0 /*non-stable */ );
589 /* send the content */
590 sub_type = array_data.type;
591 elm_size = sub_type->aligned_size[GRAS_THISARCH];
592 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
593 VERB1("Array of %d scalars, send it in one shot", count);
594 gras_trp_send(sock, data,
595 sub_type->aligned_size[GRAS_THISARCH] * count,
596 0 /* not stable */ );
597 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
598 sub_type->category.array_data.fixed_size > 0 &&
599 sub_type->category.array_data.type->category_code ==
600 e_gras_datadesc_type_cat_scalar) {
602 VERB1("Array of %d fixed array of scalars, send it in one shot",
604 gras_trp_send(sock, data,
605 sub_type->category.array_data.
606 type->aligned_size[GRAS_THISARCH]
607 * count * sub_type->category.array_data.fixed_size,
608 0 /* not stable */ );
611 for (cpt = 0; cpt < count; cpt++) {
612 gras_datadesc_send_rec(sock, state, refs, sub_type, ptr,
613 detect_cycle || sub_type->cycle);
621 xbt_die("Invalid type");
626 * gras_datadesc_send:
628 * Copy the data pointed by src and described by type to the socket
631 void gras_datadesc_send(gras_socket_t sock,
632 gras_datadesc_type_t type, void *src)
636 static gras_cbps_t state = NULL;
637 static xbt_dict_t refs = NULL; /* all references already sent */
639 xbt_assert0(type, "called with NULL type descriptor");
642 state = gras_cbps_new();
643 refs = xbt_dict_new();
647 gras_datadesc_send_rec(sock, state, refs, type, (char *) src,
650 xbt_dict_reset(refs);
651 gras_cbps_reset(state);
658 * gras_datadesc_recv_rec:
660 * Do the data reception job recursively.
662 * subsize used only to deal with vicious case of reference to dynamic array.
663 * This size is needed at the reference reception level (to allocate enough
664 * space) and at the array reception level (to fill enough room).
666 * Having this size passed as an argument of the recursive function is a crude
667 * hack, but I was told that working code is sometimes better than neat one ;)
670 gras_datadesc_recv_rec(gras_socket_t sock,
673 gras_datadesc_type_t type,
677 char *l_data, int subsize, int detect_cycle)
681 gras_datadesc_type_t sub_type;
684 VERB2("Recv a %s @%p", type->name, (void *) l_data);
687 switch (type->category_code) {
688 case e_gras_datadesc_type_cat_scalar:
689 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
690 gras_trp_recv(sock, (char *) l_data, type->size[r_arch]);
691 if (r_arch != GRAS_THISARCH)
692 gras_dd_convert_elm(type, 1, r_arch, l_data, l_data);
694 void *ptr = xbt_malloc(type->size[r_arch]);
696 gras_trp_recv(sock, (char *) ptr, type->size[r_arch]);
697 if (r_arch != GRAS_THISARCH)
698 gras_dd_convert_elm(type, 1, r_arch, ptr, l_data);
703 case e_gras_datadesc_type_cat_struct:{
704 gras_dd_cat_struct_t struct_data;
705 gras_dd_cat_field_t field;
707 struct_data = type->category.struct_data;
709 xbt_assert1(struct_data.closed,
710 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
712 VERB1(">> Receive all fields of the structure %s", type->name);
713 xbt_dynar_foreach(struct_data.fields, cpt, field) {
714 char *field_data = l_data + field->offset[GRAS_THISARCH];
716 sub_type = field->type;
718 gras_datadesc_recv_rec(sock, state, refs, sub_type,
721 detect_cycle || sub_type->cycle);
724 DEBUG1("Run the reception callback of field %s", field->name);
725 field->recv(type, state, (void *) l_data);
729 VERB1("<< Received all fields of the structure %s", type->name);
734 case e_gras_datadesc_type_cat_union:{
735 gras_dd_cat_union_t union_data;
736 gras_dd_cat_field_t field = NULL;
739 union_data = type->category.union_data;
741 xbt_assert1(union_data.closed,
742 "Please call gras_datadesc_declare_union_close on %s before receiving it",
744 /* retrieve the field number */
745 gras_dd_recv_int(sock, r_arch, &field_num);
747 THROW1(mismatch_error, 0,
748 "Received union field for %s is negative", type->name);
749 if (field_num > xbt_dynar_length(union_data.fields))
750 THROW3(mismatch_error, 0,
751 "Received union field for %s is said to be #%d but there is only %lu fields",
752 type->name, field_num, xbt_dynar_length(union_data.fields));
754 /* Recv the content */
756 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
757 sub_type = field->type;
759 gras_datadesc_recv_rec(sock, state, refs, sub_type,
761 l_data, -1, detect_cycle || sub_type->cycle);
763 field->recv(type, state, l_data);
768 case e_gras_datadesc_type_cat_ref:{
771 gras_dd_cat_ref_t ref_data;
772 int reference_is_to_recv = 0;
774 ref_data = type->category.ref_data;
776 /* Get the referenced type locally or from peer */
777 sub_type = ref_data.type;
778 if (sub_type == NULL) {
780 gras_dd_recv_int(sock, r_arch, &ref_code);
781 sub_type = gras_datadesc_by_id(ref_code);
784 /* Get the actual value of the pointer for cycle handling */
786 pointer_type = gras_datadesc_by_name("data pointer");
787 xbt_assert(pointer_type);
790 r_ref = xbt_malloc(pointer_type->size[r_arch]);
792 gras_trp_recv(sock, (char *) r_ref, pointer_type->size[r_arch]);
794 /* Receive the pointed data only if not already sent */
795 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
796 VERB1("Not receiving data remotely referenced @%p since it's NULL",
798 *(void **) l_data = NULL;
803 reference_is_to_recv = 0;
807 xbt_dict_get_ext(refs, (char *) r_ref,
808 pointer_type->size[r_arch]);
810 reference_is_to_recv = 1;
814 if (e.category != not_found_error)
816 reference_is_to_recv = 1;
820 if (reference_is_to_recv) {
821 int subsubcount = -1;
822 void *l_referenced = NULL;
824 VERB2("Receiving a ref to '%s', remotely @%p",
825 sub_type->name, *(void **) r_ref);
826 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
827 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
828 gras_dd_cat_array_t array_data = sub_type->category.array_data;
829 gras_datadesc_type_t subsub_type;
831 subsubcount = array_data.fixed_size;
832 if (subsubcount == -1)
833 gras_dd_recv_int(sock, r_arch, &subsubcount);
835 subsub_type = array_data.type;
837 if (subsubcount != 0)
838 gras_dd_alloc_ref(refs,
839 subsub_type->size[GRAS_THISARCH] * subsubcount,
840 r_ref, pointer_type->size[r_arch],
841 (char **) &l_referenced, detect_cycle);
845 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
846 r_ref, pointer_type->size[r_arch],
847 (char **) &l_referenced, detect_cycle);
850 if (l_referenced != NULL)
851 gras_datadesc_recv_rec(sock, state, refs, sub_type,
852 r_arch, r_ref, pointer_type->size[r_arch],
853 (char *) l_referenced, subsubcount,
854 detect_cycle || sub_type->cycle);
856 *(void **) l_data = l_referenced;
857 VERB3("'%s' remotely referenced at %p locally at %p",
858 sub_type->name, *(void **) r_ref, l_referenced);
862 ("NOT receiving data remotely referenced @%p (already done, @%p here)",
863 *(void **) r_ref, *(void **) l_ref);
865 *(void **) l_data = *l_ref;
872 case e_gras_datadesc_type_cat_array:{
873 gras_dd_cat_array_t array_data;
878 array_data = type->category.array_data;
879 /* determine element count locally, or from caller, or from peer */
880 count = array_data.fixed_size;
884 gras_dd_recv_int(sock, r_arch, &count);
886 THROW1(mismatch_error, 0,
887 "Invalid (=-1) array size for type %s", type->name);
889 /* receive the content */
890 sub_type = array_data.type;
891 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
892 VERB1("Array of %d scalars, get it in one shoot", count);
893 if (sub_type->aligned_size[GRAS_THISARCH] >=
894 sub_type->aligned_size[r_arch]) {
895 gras_trp_recv(sock, (char *) l_data,
896 sub_type->aligned_size[r_arch] * count);
897 if (r_arch != GRAS_THISARCH)
898 gras_dd_convert_elm(sub_type, count, r_arch, l_data, l_data);
900 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
902 gras_trp_recv(sock, (char *) ptr, sub_type->size[r_arch] * count);
903 if (r_arch != GRAS_THISARCH)
904 gras_dd_convert_elm(sub_type, count, r_arch, ptr, l_data);
907 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
908 sub_type->category.array_data.fixed_size >= 0 &&
909 sub_type->category.array_data.type->category_code ==
910 e_gras_datadesc_type_cat_scalar) {
911 gras_datadesc_type_t subsub_type;
912 array_data = sub_type->category.array_data;
913 subsub_type = array_data.type;
915 VERB1("Array of %d fixed array of scalars, get it in one shot",
917 if (subsub_type->aligned_size[GRAS_THISARCH] >=
918 subsub_type->aligned_size[r_arch]) {
919 gras_trp_recv(sock, (char *) l_data,
920 subsub_type->aligned_size[r_arch] * count *
921 array_data.fixed_size);
922 if (r_arch != GRAS_THISARCH)
923 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
924 r_arch, l_data, l_data);
927 xbt_malloc(subsub_type->aligned_size[r_arch] * count *
928 array_data.fixed_size);
930 gras_trp_recv(sock, (char *) ptr,
931 subsub_type->size[r_arch] * count *
932 array_data.fixed_size);
933 if (r_arch != GRAS_THISARCH)
934 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
935 r_arch, ptr, l_data);
941 /* not scalar content, get it recursively (may contain pointers) */
942 elm_size = sub_type->aligned_size[GRAS_THISARCH];
943 VERB2("Receive a %d-long array of %s", count, sub_type->name);
946 for (cpt = 0; cpt < count; cpt++) {
947 gras_datadesc_recv_rec(sock, state, refs, sub_type,
948 r_arch, NULL, 0, ptr, -1,
949 detect_cycle || sub_type->cycle);
958 xbt_die("Invalid type");
962 type->recv(type, state, l_data);
964 if (!strcmp(type->name, "string"))
965 VERB1("value: '%s'", *(char **) l_data);
970 * gras_datadesc_recv:
972 * Get an instance of the datatype described by @type from the @socket,
973 * and store a pointer to it in @dst
977 gras_datadesc_recv(gras_socket_t sock,
978 gras_datadesc_type_t type, int r_arch, void *dst)
982 static gras_cbps_t state = NULL; /* callback persistent state */
983 static xbt_dict_t refs = NULL; /* all references already sent */
986 state = gras_cbps_new();
987 refs = xbt_dict_new();
990 xbt_assert0(type, "called with NULL type descriptor");
992 gras_datadesc_recv_rec(sock, state, refs, type,
993 r_arch, NULL, 0, (char *) dst, -1, type->cycle);
995 xbt_dict_reset(refs);
996 gras_cbps_reset(state);