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();
390 size = gras_datadesc_memcpy_rec(state, refs, type, (char *) src, (char *) dst,0, type->cycle);
392 xbt_dict_reset(refs);
393 gras_cbps_reset(state);
401 *** Direct use functions
405 gras_datadesc_send_rec(gras_socket_t sock,
408 gras_datadesc_type_t type,
409 char *data, int detect_cycle)
413 gras_datadesc_type_t sub_type; /* type on which we recurse */
415 VERB2("Send a %s (%s)",
416 type->name, gras_datadesc_cat_names[type->category_code]);
418 if (!strcmp(type->name, "string"))
419 VERB1("value: '%s'", *(char **) data);
422 type->send(type, state, data);
423 DEBUG0("Run the emission callback");
426 switch (type->category_code) {
427 case e_gras_datadesc_type_cat_scalar:
428 gras_trp_send(sock, data, type->size[GRAS_THISARCH], 1);
431 case e_gras_datadesc_type_cat_struct:{
432 gras_dd_cat_struct_t struct_data;
433 gras_dd_cat_field_t field;
436 struct_data = type->category.struct_data;
437 xbt_assert1(struct_data.closed,
438 "Please call gras_datadesc_declare_struct_close on %s before sending it",
440 VERB1(">> Send all fields of the structure %s", type->name);
441 xbt_dynar_foreach(struct_data.fields, cpt, field) {
443 field_data += field->offset[GRAS_THISARCH];
445 sub_type = field->type;
448 DEBUG1("Run the emission callback of field %s", field->name);
449 field->send(type, state, field_data);
452 VERB1("Send field %s", field->name);
453 gras_datadesc_send_rec(sock, state, refs, sub_type, field_data,
454 detect_cycle || sub_type->cycle);
457 VERB1("<< Sent all fields of the structure %s", type->name);
462 case e_gras_datadesc_type_cat_union:{
463 gras_dd_cat_union_t union_data;
464 gras_dd_cat_field_t field = NULL;
467 union_data = type->category.union_data;
469 xbt_assert1(union_data.closed,
470 "Please call gras_datadesc_declare_union_close on %s before sending it",
472 /* retrieve the field number */
473 field_num = union_data.selector(type, state, data);
475 xbt_assert1(field_num > 0,
476 "union field selector of %s gave a negative value",
479 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
480 "union field selector of %s returned %d but there is only %lu fields",
481 type->name, field_num, xbt_dynar_length(union_data.fields));
483 /* Send the field number */
484 gras_dd_send_int(sock, &field_num, 0 /* not stable */ );
486 /* Send the content */
488 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
489 sub_type = field->type;
492 field->send(type, state, data);
494 gras_datadesc_send_rec(sock, state, refs, sub_type, data,
495 detect_cycle || sub_type->cycle);
500 case e_gras_datadesc_type_cat_ref:{
501 gras_dd_cat_ref_t ref_data;
502 void **ref = (void **) data;
503 int reference_is_to_send;
505 ref_data = type->category.ref_data;
507 /* Detect the referenced type and send it to peer if needed */
508 sub_type = ref_data.type;
509 if (sub_type == NULL) {
510 sub_type = (*ref_data.selector) (type, state, data);
511 gras_dd_send_int(sock, &(sub_type->code), 1 /*stable */ );
514 /* Send the actual value of the pointer for cycle handling */
516 pointer_type = gras_datadesc_by_name("data pointer");
517 xbt_assert(pointer_type);
520 gras_trp_send(sock, (char *) data,
521 pointer_type->size[GRAS_THISARCH], 1 /*stable */ );
523 /* Send the pointed data only if not already sent */
524 if (*(void **) data == NULL) {
525 VERB0("Not sending NULL referenced data");
529 reference_is_to_send = 1;
530 /* return ignored. Just checking whether it's known or not */
531 if (detect_cycle && xbt_dict_get_or_null_ext(refs, (char *) ref, sizeof(char *))) {
532 //INFO0("Cycle detected");
533 reference_is_to_send = 0;
536 if (reference_is_to_send) {
537 VERB1("Sending data referenced at %p", (void *) *ref);
539 xbt_dict_set_ext(refs, (char *) ref, sizeof(void *), ref, NULL);
540 gras_datadesc_send_rec(sock, state, refs, sub_type, *ref,
541 detect_cycle || sub_type->cycle);
544 VERB1("Not sending data referenced at %p (already done)",
551 case e_gras_datadesc_type_cat_array:{
552 gras_dd_cat_array_t array_data;
557 array_data = type->category.array_data;
559 /* determine and send the element count */
560 count = array_data.fixed_size;
562 count = array_data.dynamic_size(type, state, data);
563 xbt_assert1(count >= 0,
564 "Invalid (negative) array size for type %s", type->name);
565 gras_dd_send_int(sock, &count, 0 /*non-stable */ );
568 /* send the content */
569 sub_type = array_data.type;
570 elm_size = sub_type->aligned_size[GRAS_THISARCH];
571 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
572 VERB1("Array of %d scalars, send it in one shot", count);
573 gras_trp_send(sock, data,
574 sub_type->aligned_size[GRAS_THISARCH] * count,
575 0 /* not stable */ );
576 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
577 sub_type->category.array_data.fixed_size > 0 &&
578 sub_type->category.array_data.type->category_code ==
579 e_gras_datadesc_type_cat_scalar) {
581 VERB1("Array of %d fixed array of scalars, send it in one shot",
583 gras_trp_send(sock, data,
584 sub_type->category.array_data.
585 type->aligned_size[GRAS_THISARCH]
586 * count * sub_type->category.array_data.fixed_size,
587 0 /* not stable */ );
590 for (cpt = 0; cpt < count; cpt++) {
591 gras_datadesc_send_rec(sock, state, refs, sub_type, ptr,
592 detect_cycle || sub_type->cycle);
600 xbt_die("Invalid type");
605 * gras_datadesc_send:
607 * Copy the data pointed by src and described by type to the socket
610 void gras_datadesc_send(gras_socket_t sock,
611 gras_datadesc_type_t type, void *src)
615 static gras_cbps_t state = NULL;
616 static xbt_dict_t refs = NULL; /* all references already sent */
618 xbt_assert0(type, "called with NULL type descriptor");
621 state = gras_cbps_new();
622 refs = xbt_dict_new();
626 gras_datadesc_send_rec(sock, state, refs, type, (char *) src,
629 xbt_dict_reset(refs);
630 gras_cbps_reset(state);
637 * gras_datadesc_recv_rec:
639 * Do the data reception job recursively.
641 * subsize used only to deal with vicious case of reference to dynamic array.
642 * This size is needed at the reference reception level (to allocate enough
643 * space) and at the array reception level (to fill enough room).
645 * Having this size passed as an argument of the recursive function is a crude
646 * hack, but I was told that working code is sometimes better than neat one ;)
649 gras_datadesc_recv_rec(gras_socket_t sock,
652 gras_datadesc_type_t type,
656 char *l_data, int subsize, int detect_cycle)
660 gras_datadesc_type_t sub_type;
662 VERB2("Recv a %s @%p", type->name, (void *) l_data);
665 switch (type->category_code) {
666 case e_gras_datadesc_type_cat_scalar:
667 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
668 gras_trp_recv(sock, (char *) l_data, type->size[r_arch]);
669 if (r_arch != GRAS_THISARCH)
670 gras_dd_convert_elm(type, 1, r_arch, l_data, l_data);
672 void *ptr = xbt_malloc(type->size[r_arch]);
674 gras_trp_recv(sock, (char *) ptr, type->size[r_arch]);
675 if (r_arch != GRAS_THISARCH)
676 gras_dd_convert_elm(type, 1, r_arch, ptr, l_data);
681 case e_gras_datadesc_type_cat_struct:{
682 gras_dd_cat_struct_t struct_data;
683 gras_dd_cat_field_t field;
685 struct_data = type->category.struct_data;
687 xbt_assert1(struct_data.closed,
688 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
690 VERB1(">> Receive all fields of the structure %s", type->name);
691 xbt_dynar_foreach(struct_data.fields, cpt, field) {
692 char *field_data = l_data + field->offset[GRAS_THISARCH];
694 sub_type = field->type;
696 gras_datadesc_recv_rec(sock, state, refs, sub_type,
699 detect_cycle || sub_type->cycle);
702 DEBUG1("Run the reception callback of field %s", field->name);
703 field->recv(type, state, (void *) l_data);
707 VERB1("<< Received all fields of the structure %s", type->name);
712 case e_gras_datadesc_type_cat_union:{
713 gras_dd_cat_union_t union_data;
714 gras_dd_cat_field_t field = NULL;
717 union_data = type->category.union_data;
719 xbt_assert1(union_data.closed,
720 "Please call gras_datadesc_declare_union_close on %s before receiving it",
722 /* retrieve the field number */
723 gras_dd_recv_int(sock, r_arch, &field_num);
725 THROW1(mismatch_error, 0,
726 "Received union field for %s is negative", type->name);
727 if (field_num > xbt_dynar_length(union_data.fields))
728 THROW3(mismatch_error, 0,
729 "Received union field for %s is said to be #%d but there is only %lu fields",
730 type->name, field_num, xbt_dynar_length(union_data.fields));
732 /* Recv the content */
734 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
735 sub_type = field->type;
737 gras_datadesc_recv_rec(sock, state, refs, sub_type,
739 l_data, -1, detect_cycle || sub_type->cycle);
741 field->recv(type, state, l_data);
746 case e_gras_datadesc_type_cat_ref:{
749 gras_dd_cat_ref_t ref_data;
750 int reference_is_to_recv = 0;
752 ref_data = type->category.ref_data;
754 /* Get the referenced type locally or from peer */
755 sub_type = ref_data.type;
756 if (sub_type == NULL) {
758 gras_dd_recv_int(sock, r_arch, &ref_code);
759 sub_type = gras_datadesc_by_id(ref_code);
762 /* Get the actual value of the pointer for cycle handling */
764 pointer_type = gras_datadesc_by_name("data pointer");
765 xbt_assert(pointer_type);
768 r_ref = xbt_malloc(pointer_type->size[r_arch]);
770 gras_trp_recv(sock, (char *) r_ref, pointer_type->size[r_arch]);
772 /* Receive the pointed data only if not already sent */
773 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
774 VERB1("Not receiving data remotely referenced @%p since it's NULL",
776 *(void **) l_data = NULL;
781 reference_is_to_recv = 1;
782 if (detect_cycle && (l_ref =
783 xbt_dict_get_or_null_ext(refs, (char *) r_ref,
784 pointer_type->size[r_arch]))) {
785 reference_is_to_recv = 0;
786 //INFO0("Cycle detected");
789 if (reference_is_to_recv) {
790 int subsubcount = -1;
791 void *l_referenced = NULL;
793 VERB2("Receiving a ref to '%s', remotely @%p",
794 sub_type->name, *(void **) r_ref);
795 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
796 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
797 gras_dd_cat_array_t array_data = sub_type->category.array_data;
798 gras_datadesc_type_t subsub_type;
800 subsubcount = array_data.fixed_size;
801 if (subsubcount == -1)
802 gras_dd_recv_int(sock, r_arch, &subsubcount);
804 subsub_type = array_data.type;
806 if (subsubcount != 0)
807 gras_dd_alloc_ref(refs,
808 subsub_type->size[GRAS_THISARCH] * subsubcount,
809 r_ref, pointer_type->size[r_arch],
810 (char **) &l_referenced, detect_cycle);
814 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
815 r_ref, pointer_type->size[r_arch],
816 (char **) &l_referenced, detect_cycle);
819 if (l_referenced != NULL)
820 gras_datadesc_recv_rec(sock, state, refs, sub_type,
821 r_arch, r_ref, pointer_type->size[r_arch],
822 (char *) l_referenced, subsubcount,
823 detect_cycle || sub_type->cycle);
825 *(void **) l_data = l_referenced;
826 VERB3("'%s' remotely referenced at %p locally at %p",
827 sub_type->name, *(void **) r_ref, l_referenced);
831 ("NOT receiving data remotely referenced @%p (already done, @%p here)",
832 *(void **) r_ref, *(void **) l_ref);
834 *(void **) l_data = *l_ref;
841 case e_gras_datadesc_type_cat_array:{
842 gras_dd_cat_array_t array_data;
847 array_data = type->category.array_data;
848 /* determine element count locally, or from caller, or from peer */
849 count = array_data.fixed_size;
853 gras_dd_recv_int(sock, r_arch, &count);
855 THROW1(mismatch_error, 0,
856 "Invalid (=-1) array size for type %s", type->name);
858 /* receive the content */
859 sub_type = array_data.type;
860 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
861 VERB1("Array of %d scalars, get it in one shoot", count);
862 if (sub_type->aligned_size[GRAS_THISARCH] >=
863 sub_type->aligned_size[r_arch]) {
864 gras_trp_recv(sock, (char *) l_data,
865 sub_type->aligned_size[r_arch] * count);
866 if (r_arch != GRAS_THISARCH)
867 gras_dd_convert_elm(sub_type, count, r_arch, l_data, l_data);
869 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
871 gras_trp_recv(sock, (char *) ptr, sub_type->size[r_arch] * count);
872 if (r_arch != GRAS_THISARCH)
873 gras_dd_convert_elm(sub_type, count, r_arch, ptr, l_data);
876 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
877 sub_type->category.array_data.fixed_size >= 0 &&
878 sub_type->category.array_data.type->category_code ==
879 e_gras_datadesc_type_cat_scalar) {
880 gras_datadesc_type_t subsub_type;
881 array_data = sub_type->category.array_data;
882 subsub_type = array_data.type;
884 VERB1("Array of %d fixed array of scalars, get it in one shot",
886 if (subsub_type->aligned_size[GRAS_THISARCH] >=
887 subsub_type->aligned_size[r_arch]) {
888 gras_trp_recv(sock, (char *) l_data,
889 subsub_type->aligned_size[r_arch] * count *
890 array_data.fixed_size);
891 if (r_arch != GRAS_THISARCH)
892 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
893 r_arch, l_data, l_data);
896 xbt_malloc(subsub_type->aligned_size[r_arch] * count *
897 array_data.fixed_size);
899 gras_trp_recv(sock, (char *) ptr,
900 subsub_type->size[r_arch] * count *
901 array_data.fixed_size);
902 if (r_arch != GRAS_THISARCH)
903 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
904 r_arch, ptr, l_data);
910 /* not scalar content, get it recursively (may contain pointers) */
911 elm_size = sub_type->aligned_size[GRAS_THISARCH];
912 VERB2("Receive a %d-long array of %s", count, sub_type->name);
915 for (cpt = 0; cpt < count; cpt++) {
916 gras_datadesc_recv_rec(sock, state, refs, sub_type,
917 r_arch, NULL, 0, ptr, -1,
918 detect_cycle || sub_type->cycle);
927 xbt_die("Invalid type");
931 type->recv(type, state, l_data);
933 if (!strcmp(type->name, "string"))
934 VERB1("value: '%s'", *(char **) l_data);
939 * gras_datadesc_recv:
941 * Get an instance of the datatype described by @type from the @socket,
942 * and store a pointer to it in @dst
946 gras_datadesc_recv(gras_socket_t sock,
947 gras_datadesc_type_t type, int r_arch, void *dst)
951 static gras_cbps_t state = NULL; /* callback persistent state */
952 static xbt_dict_t refs = NULL; /* all references already sent */
955 state = gras_cbps_new();
956 refs = xbt_dict_new();
959 xbt_assert0(type, "called with NULL type descriptor");
961 gras_datadesc_recv_rec(sock, state, refs, type,
962 r_arch, NULL, 0, (char *) dst, -1, type->cycle);
964 xbt_dict_reset(refs);
965 gras_cbps_reset(state);