1 /* ddt_exchange - send/recv data described */
3 /* Copyright (c) 2004, 2005, 2006, 2007, 2009, 2010. The SimGrid Team.
4 * All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
10 #include "gras/DataDesc/datadesc_private.h"
11 #include "gras/Transport/transport_interface.h" /* gras_trp_send/recv */
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_ddt_exchange, gras_ddt,
14 "Sending data over the network");
15 const char *gras_datadesc_cat_names[9] = {
17 "scalar", "struct", "union", "ref", "array", "ignored",
21 static gras_datadesc_type_t int_type = NULL;
22 static gras_datadesc_type_t pointer_type = NULL;
24 static XBT_INLINE void
25 gras_dd_send_int(gras_socket_t sock, int *i, int stable)
29 int_type = gras_datadesc_by_name("int");
33 DEBUG1("send_int(%u)", *i);
34 gras_trp_send(sock, (char *) i, int_type->size[GRAS_THISARCH], stable);
37 static XBT_INLINE void
38 gras_dd_recv_int(gras_socket_t sock, int r_arch, int *i)
42 int_type = gras_datadesc_by_name("int");
46 if (int_type->size[GRAS_THISARCH] >= int_type->size[r_arch]) {
47 gras_trp_recv(sock, (char *) i, int_type->size[r_arch]);
48 if (r_arch != GRAS_THISARCH)
49 gras_dd_convert_elm(int_type, 1, r_arch, i, i);
51 void *ptr = xbt_malloc(int_type->size[r_arch]);
53 gras_trp_recv(sock, (char *) ptr, int_type->size[r_arch]);
54 if (r_arch != GRAS_THISARCH)
55 gras_dd_convert_elm(int_type, 1, r_arch, ptr, i);
58 DEBUG1("recv_int(%u)", *i);
62 * Note: here we suppose that the remote NULL is a sequence
63 * of 'length' bytes set to 0.
64 * FIXME: Check in configure?
66 static XBT_INLINE int gras_dd_is_r_null(char **r_ptr, long int length)
70 for (i = 0; i < length; i++) {
71 if (((unsigned char *) r_ptr)[i]) {
79 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] */
80 char **l_ref, int detect_cycle)
84 xbt_assert1(size > 0, "Cannot allocate %ld bytes!", size);
85 l_data = xbt_malloc((size_t) size);
88 DEBUG5("alloc_ref: l_data=%p, &l_data=%p; r_ref=%p; *r_ref=%p, r_len=%ld",
89 (void *) l_data, (void *) &l_data,
90 (void *) r_ref, (void *) (r_ref ? *r_ref : NULL), r_len);
91 if (detect_cycle && r_ref && !gras_dd_is_r_null(r_ref, r_len)) {
92 void *ptr = xbt_malloc(sizeof(void *));
94 memcpy(ptr, l_ref, sizeof(void *));
96 DEBUG2("Insert l_ref=%p under r_ref=%p", *(void **) ptr,
100 xbt_dict_set_ext(refs, (const char *) r_ref, r_len, ptr, xbt_free_f);
105 gras_datadesc_memcpy_rec(gras_cbps_t state,
107 gras_datadesc_type_t type,
108 char *src, char *dst, int subsize, int detect_cycle)
113 gras_datadesc_type_t sub_type; /* type on which we recurse */
116 VERB5("Copy a %s (%s) from %p to %p (local sizeof=%ld)",
117 type->name, gras_datadesc_cat_names[type->category_code],
118 src, dst, type->size[GRAS_THISARCH]);
121 type->send(type, state, src);
124 switch (type->category_code) {
125 case e_gras_datadesc_type_cat_scalar:
126 memcpy(dst, src, type->size[GRAS_THISARCH]);
127 count += type->size[GRAS_THISARCH];
130 case e_gras_datadesc_type_cat_struct:{
131 gras_dd_cat_struct_t struct_data;
132 gras_dd_cat_field_t field;
136 struct_data = type->category.struct_data;
137 xbt_assert1(struct_data.closed,
138 "Please call gras_datadesc_declare_struct_close on %s before copying it",
140 VERB1(">> Copy all fields of the structure %s", type->name);
141 xbt_dynar_foreach(struct_data.fields, cpt, field) {
142 field_src = src + field->offset[GRAS_THISARCH];
143 field_dst = dst + field->offset[GRAS_THISARCH];
145 sub_type = field->type;
148 field->send(type, state, field_src);
150 DEBUG1("Copy field %s", field->name);
152 gras_datadesc_memcpy_rec(state, refs, sub_type, field_src,
153 field_dst, 0, detect_cycle
156 if (XBT_LOG_ISENABLED(gras_ddt_exchange, xbt_log_priority_verbose)) {
157 if (sub_type == gras_datadesc_by_name("unsigned int")) {
158 VERB2("Copied value for field '%s': %d (type: unsigned int)",
159 field->name, *(unsigned int *) field_dst);
160 } else if (sub_type == gras_datadesc_by_name("int")) {
161 VERB2("Copied value for field '%s': %d (type: int)", field->name,
164 } else if (sub_type == gras_datadesc_by_name("unsigned long int")) {
166 ("Copied value for field '%s': %ld (type: unsigned long int)",
167 field->name, *(unsigned long int *) field_dst);
168 } else if (sub_type == gras_datadesc_by_name("long int")) {
169 VERB2("Copied value for field '%s': %ld (type: long int)",
170 field->name, *(long int *) field_dst);
172 } else if (sub_type == gras_datadesc_by_name("string")) {
173 VERB2("Copied value for field '%s': '%s' (type: string)",
174 field->name, *(char **) field_dst);
176 VERB1("Copied a value for field '%s' (type not scalar?)",
182 VERB1("<< Copied all fields of the structure %s", type->name);
187 case e_gras_datadesc_type_cat_union:{
188 gras_dd_cat_union_t union_data;
189 gras_dd_cat_field_t field = NULL;
190 unsigned int field_num;
192 union_data = type->category.union_data;
194 xbt_assert1(union_data.closed,
195 "Please call gras_datadesc_declare_union_close on %s before copying it",
197 /* retrieve the field number */
198 field_num = union_data.selector(type, state, src);
200 xbt_assert1(field_num > 0,
201 "union field selector of %s gave a negative value",
204 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
205 "union field selector of %s returned %d but there is only %lu fields",
206 type->name, field_num, xbt_dynar_length(union_data.fields));
208 /* Copy the content */
210 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
211 sub_type = field->type;
214 field->send(type, state, src);
216 count += gras_datadesc_memcpy_rec(state, refs, sub_type, src, dst, 0,
217 detect_cycle || sub_type->cycle);
222 case e_gras_datadesc_type_cat_ref:{
223 gras_dd_cat_ref_t ref_data;
226 int reference_is_to_cpy;
228 ref_data = type->category.ref_data;
230 /* Detect the referenced type */
231 sub_type = ref_data.type;
232 if (sub_type == NULL) {
233 sub_type = (*ref_data.selector) (type, state, src);
236 /* Send the pointed data only if not already sent */
237 if (*(void **) src == NULL) {
238 VERB0("Not copying NULL referenced data");
239 *(void **) dst = NULL;
242 o_ref = (char **) src;
244 reference_is_to_cpy = 1;
246 (n_ref=xbt_dict_get_or_null_ext(refs, (char *) o_ref, sizeof(char *)))) {
247 /* already known, no need to copy it */
248 //INFO0("Cycle detected");
249 reference_is_to_cpy = 0;
252 if (reference_is_to_cpy) {
253 int subsubcount = -1;
254 void *l_referenced = NULL;
255 VERB2("Copy a ref to '%s' referenced at %p", sub_type->name,
259 pointer_type = gras_datadesc_by_name("data pointer");
260 xbt_assert(pointer_type);
263 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
264 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
265 gras_dd_cat_array_t array_data = sub_type->category.array_data;
266 gras_datadesc_type_t subsub_type;
268 subsub_type = array_data.type;
269 subsubcount = array_data.fixed_size;
270 if (subsubcount == -1)
271 subsubcount = array_data.dynamic_size(subsub_type, state, *o_ref);
273 if (subsubcount != 0)
274 gras_dd_alloc_ref(refs,
275 subsub_type->size[GRAS_THISARCH] * subsubcount,
276 o_ref, pointer_type->size[GRAS_THISARCH],
277 (char **) &l_referenced, detect_cycle);
279 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
280 o_ref, pointer_type->size[GRAS_THISARCH],
281 (char **) &l_referenced, detect_cycle);
284 count += gras_datadesc_memcpy_rec(state, refs, sub_type,
285 *o_ref, (char *) l_referenced,
286 subsubcount, detect_cycle
289 *(void **) dst = l_referenced;
290 VERB3("'%s' previously referenced at %p now at %p",
291 sub_type->name, *(void **) o_ref, l_referenced);
295 ("NOT copying data previously referenced @%p (already done, @%p now)",
296 *(void **) o_ref, *(void **) n_ref);
298 *(void **) dst = *n_ref;
304 case e_gras_datadesc_type_cat_array:{
305 gras_dd_cat_array_t array_data;
306 unsigned long int array_count;
311 array_data = type->category.array_data;
313 /* determine and send the element count */
314 array_count = array_data.fixed_size;
315 if (array_count == -1)
316 array_count = subsize;
317 if (array_count == -1) {
318 array_count = array_data.dynamic_size(type, state, src);
319 xbt_assert1(array_count >= 0,
320 "Invalid (negative) array size for type %s", type->name);
323 /* send the content */
324 sub_type = array_data.type;
325 elm_size = sub_type->aligned_size[GRAS_THISARCH];
326 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
327 VERB1("Array of %ld scalars, copy it in one shot", array_count);
328 memcpy(dst, src, sub_type->aligned_size[GRAS_THISARCH] * array_count);
329 count += sub_type->aligned_size[GRAS_THISARCH] * array_count;
330 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
331 sub_type->category.array_data.fixed_size > 0 &&
332 sub_type->category.array_data.type->category_code ==
333 e_gras_datadesc_type_cat_scalar) {
335 VERB1("Array of %ld fixed array of scalars, copy it in one shot",
338 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
339 * array_count * sub_type->category.array_data.fixed_size);
341 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
342 * array_count * sub_type->category.array_data.fixed_size;
345 VERB1("Array of %ld stuff, copy it in one after the other",
347 for (cpt = 0; cpt < array_count; cpt++) {
348 VERB2("Copy the %dth stuff out of %ld", cpt, array_count);
350 gras_datadesc_memcpy_rec(state, refs, sub_type, src_ptr, dst_ptr,
351 0, detect_cycle || sub_type->cycle);
360 xbt_die("Invalid type");
367 * gras_datadesc_memcpy:
369 * Copy the data pointed by src and described by type
370 * to a new location, and store a pointer to it in dst.
373 int gras_datadesc_memcpy(gras_datadesc_type_t type, void *src, void *dst)
376 static gras_cbps_t state = NULL;
377 static xbt_dict_t refs = NULL; /* all references already sent */
380 xbt_assert0(type, "called with NULL type descriptor");
382 DEBUG3("Memcopy a %s from %p to %p", gras_datadesc_get_name(type), src,
385 state = gras_cbps_new();
386 refs = xbt_dict_new();
391 gras_datadesc_memcpy_rec(state, refs, type, (char *) src, (char *) dst,
394 xbt_dict_reset(refs);
395 gras_cbps_reset(state);
403 *** Direct use functions
407 gras_datadesc_send_rec(gras_socket_t sock,
410 gras_datadesc_type_t type,
411 char *data, int detect_cycle)
415 gras_datadesc_type_t sub_type; /* type on which we recurse */
417 VERB2("Send a %s (%s)",
418 type->name, gras_datadesc_cat_names[type->category_code]);
420 if (!strcmp(type->name, "string"))
421 VERB1("value: '%s'", *(char **) data);
424 type->send(type, state, data);
425 DEBUG0("Run the emission callback");
428 switch (type->category_code) {
429 case e_gras_datadesc_type_cat_scalar:
430 gras_trp_send(sock, data, type->size[GRAS_THISARCH], 1);
433 case e_gras_datadesc_type_cat_struct:{
434 gras_dd_cat_struct_t struct_data;
435 gras_dd_cat_field_t field;
438 struct_data = type->category.struct_data;
439 xbt_assert1(struct_data.closed,
440 "Please call gras_datadesc_declare_struct_close on %s before sending it",
442 VERB1(">> Send all fields of the structure %s", type->name);
443 xbt_dynar_foreach(struct_data.fields, cpt, field) {
445 field_data += field->offset[GRAS_THISARCH];
447 sub_type = field->type;
450 DEBUG1("Run the emission callback of field %s", field->name);
451 field->send(type, state, field_data);
454 VERB1("Send field %s", field->name);
455 gras_datadesc_send_rec(sock, state, refs, sub_type, field_data,
456 detect_cycle || sub_type->cycle);
459 VERB1("<< Sent all fields of the structure %s", type->name);
464 case e_gras_datadesc_type_cat_union:{
465 gras_dd_cat_union_t union_data;
466 gras_dd_cat_field_t field = NULL;
469 union_data = type->category.union_data;
471 xbt_assert1(union_data.closed,
472 "Please call gras_datadesc_declare_union_close on %s before sending it",
474 /* retrieve the field number */
475 field_num = union_data.selector(type, state, data);
477 xbt_assert1(field_num > 0,
478 "union field selector of %s gave a negative value",
481 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
482 "union field selector of %s returned %d but there is only %lu fields",
483 type->name, field_num, xbt_dynar_length(union_data.fields));
485 /* Send the field number */
486 gras_dd_send_int(sock, &field_num, 0 /* not stable */ );
488 /* Send the content */
490 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
491 sub_type = field->type;
494 field->send(type, state, data);
496 gras_datadesc_send_rec(sock, state, refs, sub_type, data,
497 detect_cycle || sub_type->cycle);
502 case e_gras_datadesc_type_cat_ref:{
503 gras_dd_cat_ref_t ref_data;
504 void **ref = (void **) data;
505 int reference_is_to_send;
507 ref_data = type->category.ref_data;
509 /* Detect the referenced type and send it to peer if needed */
510 sub_type = ref_data.type;
511 if (sub_type == NULL) {
512 sub_type = (*ref_data.selector) (type, state, data);
513 gras_dd_send_int(sock, &(sub_type->code), 1 /*stable */ );
516 /* Send the actual value of the pointer for cycle handling */
518 pointer_type = gras_datadesc_by_name("data pointer");
519 xbt_assert(pointer_type);
522 gras_trp_send(sock, (char *) data,
523 pointer_type->size[GRAS_THISARCH], 1 /*stable */ );
525 /* Send the pointed data only if not already sent */
526 if (*(void **) data == NULL) {
527 VERB0("Not sending NULL referenced data");
531 reference_is_to_send = 1;
532 /* return ignored. Just checking whether it's known or not */
533 if (detect_cycle && xbt_dict_get_or_null_ext(refs, (char *) ref, sizeof(char *))) {
534 //INFO0("Cycle detected");
535 reference_is_to_send = 0;
538 if (reference_is_to_send) {
539 VERB1("Sending data referenced at %p", (void *) *ref);
541 xbt_dict_set_ext(refs, (char *) ref, sizeof(void *), ref, NULL);
542 gras_datadesc_send_rec(sock, state, refs, sub_type, *ref,
543 detect_cycle || sub_type->cycle);
546 VERB1("Not sending data referenced at %p (already done)",
553 case e_gras_datadesc_type_cat_array:{
554 gras_dd_cat_array_t array_data;
559 array_data = type->category.array_data;
561 /* determine and send the element count */
562 count = array_data.fixed_size;
564 count = array_data.dynamic_size(type, state, data);
565 xbt_assert1(count >= 0,
566 "Invalid (negative) array size for type %s", type->name);
567 gras_dd_send_int(sock, &count, 0 /*non-stable */ );
570 /* send the content */
571 sub_type = array_data.type;
572 elm_size = sub_type->aligned_size[GRAS_THISARCH];
573 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
574 VERB1("Array of %d scalars, send it in one shot", count);
575 gras_trp_send(sock, data,
576 sub_type->aligned_size[GRAS_THISARCH] * count,
577 0 /* not stable */ );
578 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
579 sub_type->category.array_data.fixed_size > 0 &&
580 sub_type->category.array_data.type->category_code ==
581 e_gras_datadesc_type_cat_scalar) {
583 VERB1("Array of %d fixed array of scalars, send it in one shot",
585 gras_trp_send(sock, data,
586 sub_type->category.array_data.
587 type->aligned_size[GRAS_THISARCH]
588 * count * sub_type->category.array_data.fixed_size,
589 0 /* not stable */ );
592 for (cpt = 0; cpt < count; cpt++) {
593 gras_datadesc_send_rec(sock, state, refs, sub_type, ptr,
594 detect_cycle || sub_type->cycle);
602 xbt_die("Invalid type");
607 * gras_datadesc_send:
609 * Copy the data pointed by src and described by type to the socket
612 void gras_datadesc_send(gras_socket_t sock,
613 gras_datadesc_type_t type, void *src)
617 static gras_cbps_t state = NULL;
618 static xbt_dict_t refs = NULL; /* all references already sent */
620 xbt_assert0(type, "called with NULL type descriptor");
623 state = gras_cbps_new();
624 refs = xbt_dict_new();
628 gras_datadesc_send_rec(sock, state, refs, type, (char *) src,
631 xbt_dict_reset(refs);
632 gras_cbps_reset(state);
639 * gras_datadesc_recv_rec:
641 * Do the data reception job recursively.
643 * subsize used only to deal with vicious case of reference to dynamic array.
644 * This size is needed at the reference reception level (to allocate enough
645 * space) and at the array reception level (to fill enough room).
647 * Having this size passed as an argument of the recursive function is a crude
648 * hack, but I was told that working code is sometimes better than neat one ;)
651 gras_datadesc_recv_rec(gras_socket_t sock,
654 gras_datadesc_type_t type,
658 char *l_data, int subsize, int detect_cycle)
662 gras_datadesc_type_t sub_type;
664 VERB2("Recv a %s @%p", type->name, (void *) l_data);
667 switch (type->category_code) {
668 case e_gras_datadesc_type_cat_scalar:
669 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
670 gras_trp_recv(sock, (char *) l_data, type->size[r_arch]);
671 if (r_arch != GRAS_THISARCH)
672 gras_dd_convert_elm(type, 1, r_arch, l_data, l_data);
674 void *ptr = xbt_malloc(type->size[r_arch]);
676 gras_trp_recv(sock, (char *) ptr, type->size[r_arch]);
677 if (r_arch != GRAS_THISARCH)
678 gras_dd_convert_elm(type, 1, r_arch, ptr, l_data);
683 case e_gras_datadesc_type_cat_struct:{
684 gras_dd_cat_struct_t struct_data;
685 gras_dd_cat_field_t field;
687 struct_data = type->category.struct_data;
689 xbt_assert1(struct_data.closed,
690 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
692 VERB1(">> Receive all fields of the structure %s", type->name);
693 xbt_dynar_foreach(struct_data.fields, cpt, field) {
694 char *field_data = l_data + field->offset[GRAS_THISARCH];
696 sub_type = field->type;
698 gras_datadesc_recv_rec(sock, state, refs, sub_type,
701 detect_cycle || sub_type->cycle);
704 DEBUG1("Run the reception callback of field %s", field->name);
705 field->recv(type, state, (void *) l_data);
709 VERB1("<< Received all fields of the structure %s", type->name);
714 case e_gras_datadesc_type_cat_union:{
715 gras_dd_cat_union_t union_data;
716 gras_dd_cat_field_t field = NULL;
719 union_data = type->category.union_data;
721 xbt_assert1(union_data.closed,
722 "Please call gras_datadesc_declare_union_close on %s before receiving it",
724 /* retrieve the field number */
725 gras_dd_recv_int(sock, r_arch, &field_num);
727 THROW1(mismatch_error, 0,
728 "Received union field for %s is negative", type->name);
729 if (field_num > xbt_dynar_length(union_data.fields))
730 THROW3(mismatch_error, 0,
731 "Received union field for %s is said to be #%d but there is only %lu fields",
732 type->name, field_num, xbt_dynar_length(union_data.fields));
734 /* Recv the content */
736 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
737 sub_type = field->type;
739 gras_datadesc_recv_rec(sock, state, refs, sub_type,
741 l_data, -1, detect_cycle || sub_type->cycle);
743 field->recv(type, state, l_data);
748 case e_gras_datadesc_type_cat_ref:{
751 gras_dd_cat_ref_t ref_data;
752 int reference_is_to_recv = 0;
754 ref_data = type->category.ref_data;
756 /* Get the referenced type locally or from peer */
757 sub_type = ref_data.type;
758 if (sub_type == NULL) {
760 gras_dd_recv_int(sock, r_arch, &ref_code);
761 sub_type = gras_datadesc_by_id(ref_code);
764 /* Get the actual value of the pointer for cycle handling */
766 pointer_type = gras_datadesc_by_name("data pointer");
767 xbt_assert(pointer_type);
770 r_ref = xbt_malloc(pointer_type->size[r_arch]);
772 gras_trp_recv(sock, (char *) r_ref, pointer_type->size[r_arch]);
774 /* Receive the pointed data only if not already sent */
775 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
776 VERB1("Not receiving data remotely referenced @%p since it's NULL",
778 *(void **) l_data = NULL;
783 reference_is_to_recv = 1;
784 if (detect_cycle && (l_ref =
785 xbt_dict_get_or_null_ext(refs, (char *) r_ref,
786 pointer_type->size[r_arch]))) {
787 reference_is_to_recv = 0;
788 //INFO0("Cycle detected");
791 if (reference_is_to_recv) {
792 int subsubcount = -1;
793 void *l_referenced = NULL;
795 VERB2("Receiving a ref to '%s', remotely @%p",
796 sub_type->name, *(void **) r_ref);
797 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
798 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
799 gras_dd_cat_array_t array_data = sub_type->category.array_data;
800 gras_datadesc_type_t subsub_type;
802 subsubcount = array_data.fixed_size;
803 if (subsubcount == -1)
804 gras_dd_recv_int(sock, r_arch, &subsubcount);
806 subsub_type = array_data.type;
808 if (subsubcount != 0)
809 gras_dd_alloc_ref(refs,
810 subsub_type->size[GRAS_THISARCH] * subsubcount,
811 r_ref, pointer_type->size[r_arch],
812 (char **) &l_referenced, detect_cycle);
816 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
817 r_ref, pointer_type->size[r_arch],
818 (char **) &l_referenced, detect_cycle);
821 if (l_referenced != NULL)
822 gras_datadesc_recv_rec(sock, state, refs, sub_type,
823 r_arch, r_ref, pointer_type->size[r_arch],
824 (char *) l_referenced, subsubcount,
825 detect_cycle || sub_type->cycle);
827 *(void **) l_data = l_referenced;
828 VERB3("'%s' remotely referenced at %p locally at %p",
829 sub_type->name, *(void **) r_ref, l_referenced);
833 ("NOT receiving data remotely referenced @%p (already done, @%p here)",
834 *(void **) r_ref, *(void **) l_ref);
836 *(void **) l_data = *l_ref;
843 case e_gras_datadesc_type_cat_array:{
844 gras_dd_cat_array_t array_data;
849 array_data = type->category.array_data;
850 /* determine element count locally, or from caller, or from peer */
851 count = array_data.fixed_size;
855 gras_dd_recv_int(sock, r_arch, &count);
857 THROW1(mismatch_error, 0,
858 "Invalid (=-1) array size for type %s", type->name);
860 /* receive the content */
861 sub_type = array_data.type;
862 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
863 VERB1("Array of %d scalars, get it in one shoot", count);
864 if (sub_type->aligned_size[GRAS_THISARCH] >=
865 sub_type->aligned_size[r_arch]) {
866 gras_trp_recv(sock, (char *) l_data,
867 sub_type->aligned_size[r_arch] * count);
868 if (r_arch != GRAS_THISARCH)
869 gras_dd_convert_elm(sub_type, count, r_arch, l_data, l_data);
871 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
873 gras_trp_recv(sock, (char *) ptr, sub_type->size[r_arch] * count);
874 if (r_arch != GRAS_THISARCH)
875 gras_dd_convert_elm(sub_type, count, r_arch, ptr, l_data);
878 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
879 sub_type->category.array_data.fixed_size >= 0 &&
880 sub_type->category.array_data.type->category_code ==
881 e_gras_datadesc_type_cat_scalar) {
882 gras_datadesc_type_t subsub_type;
883 array_data = sub_type->category.array_data;
884 subsub_type = array_data.type;
886 VERB1("Array of %d fixed array of scalars, get it in one shot",
888 if (subsub_type->aligned_size[GRAS_THISARCH] >=
889 subsub_type->aligned_size[r_arch]) {
890 gras_trp_recv(sock, (char *) l_data,
891 subsub_type->aligned_size[r_arch] * count *
892 array_data.fixed_size);
893 if (r_arch != GRAS_THISARCH)
894 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
895 r_arch, l_data, l_data);
898 xbt_malloc(subsub_type->aligned_size[r_arch] * count *
899 array_data.fixed_size);
901 gras_trp_recv(sock, (char *) ptr,
902 subsub_type->size[r_arch] * count *
903 array_data.fixed_size);
904 if (r_arch != GRAS_THISARCH)
905 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
906 r_arch, ptr, l_data);
912 /* not scalar content, get it recursively (may contain pointers) */
913 elm_size = sub_type->aligned_size[GRAS_THISARCH];
914 VERB2("Receive a %d-long array of %s", count, sub_type->name);
917 for (cpt = 0; cpt < count; cpt++) {
918 gras_datadesc_recv_rec(sock, state, refs, sub_type,
919 r_arch, NULL, 0, ptr, -1,
920 detect_cycle || sub_type->cycle);
929 xbt_die("Invalid type");
933 type->recv(type, state, l_data);
935 if (!strcmp(type->name, "string"))
936 VERB1("value: '%s'", *(char **) l_data);
941 * gras_datadesc_recv:
943 * Get an instance of the datatype described by @type from the @socket,
944 * and store a pointer to it in @dst
948 gras_datadesc_recv(gras_socket_t sock,
949 gras_datadesc_type_t type, int r_arch, void *dst)
953 static gras_cbps_t state = NULL; /* callback persistent state */
954 static xbt_dict_t refs = NULL; /* all references already sent */
957 state = gras_cbps_new();
958 refs = xbt_dict_new();
961 xbt_assert0(type, "called with NULL type descriptor");
963 gras_datadesc_recv_rec(sock, state, refs, type,
964 r_arch, NULL, 0, (char *) dst, -1, type->cycle);
966 xbt_dict_reset(refs);
967 gras_cbps_reset(state);