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)
114 gras_datadesc_type_t sub_type; /* type on which we recurse */
117 VERB5("Copy a %s (%s) from %p to %p (local sizeof=%ld)",
118 type->name, gras_datadesc_cat_names[type->category_code],
119 src, dst, type->size[GRAS_THISARCH]);
122 type->send(type, state, src);
125 switch (type->category_code) {
126 case e_gras_datadesc_type_cat_scalar:
127 memcpy(dst, src, type->size[GRAS_THISARCH]);
128 count += type->size[GRAS_THISARCH];
131 case e_gras_datadesc_type_cat_struct:{
132 gras_dd_cat_struct_t struct_data;
133 gras_dd_cat_field_t field;
137 struct_data = type->category.struct_data;
138 xbt_assert1(struct_data.closed,
139 "Please call gras_datadesc_declare_struct_close on %s before copying it",
141 VERB1(">> Copy all fields of the structure %s", type->name);
142 xbt_dynar_foreach(struct_data.fields, cpt, field) {
143 field_src = src + field->offset[GRAS_THISARCH];
144 field_dst = dst + field->offset[GRAS_THISARCH];
146 sub_type = field->type;
149 field->send(type, state, field_src);
151 DEBUG1("Copy field %s", field->name);
153 gras_datadesc_memcpy_rec(state, refs, sub_type, field_src,
154 field_dst, 0, detect_cycle
157 if (XBT_LOG_ISENABLED(gras_ddt_exchange, xbt_log_priority_verbose)) {
158 if (sub_type == gras_datadesc_by_name("unsigned int")) {
159 VERB2("Copied value for field '%s': %d (type: unsigned int)",
160 field->name, *(unsigned int *) field_dst);
161 } else if (sub_type == gras_datadesc_by_name("int")) {
162 VERB2("Copied value for field '%s': %d (type: int)", field->name,
165 } else if (sub_type == gras_datadesc_by_name("unsigned long int")) {
167 ("Copied value for field '%s': %ld (type: unsigned long int)",
168 field->name, *(unsigned long int *) field_dst);
169 } else if (sub_type == gras_datadesc_by_name("long int")) {
170 VERB2("Copied value for field '%s': %ld (type: long int)",
171 field->name, *(long int *) field_dst);
173 } else if (sub_type == gras_datadesc_by_name("string")) {
174 VERB2("Copied value for field '%s': '%s' (type: string)",
175 field->name, *(char **) field_dst);
177 VERB1("Copied a value for field '%s' (type not scalar?)",
183 VERB1("<< Copied all fields of the structure %s", type->name);
188 case e_gras_datadesc_type_cat_union:{
189 gras_dd_cat_union_t union_data;
190 gras_dd_cat_field_t field = NULL;
191 unsigned int field_num;
193 union_data = type->category.union_data;
195 xbt_assert1(union_data.closed,
196 "Please call gras_datadesc_declare_union_close on %s before copying it",
198 /* retrieve the field number */
199 field_num = union_data.selector(type, state, src);
201 xbt_assert1(field_num > 0,
202 "union field selector of %s gave a negative value",
205 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
206 "union field selector of %s returned %d but there is only %lu fields",
207 type->name, field_num, xbt_dynar_length(union_data.fields));
209 /* Copy the content */
211 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
212 sub_type = field->type;
215 field->send(type, state, src);
217 count += gras_datadesc_memcpy_rec(state, refs, sub_type, src, dst, 0,
218 detect_cycle || sub_type->cycle);
223 case e_gras_datadesc_type_cat_ref:{
224 gras_dd_cat_ref_t ref_data;
227 int reference_is_to_cpy;
229 ref_data = type->category.ref_data;
231 /* Detect the referenced type */
232 sub_type = ref_data.type;
233 if (sub_type == NULL) {
234 sub_type = (*ref_data.selector) (type, state, src);
237 /* Send the pointed data only if not already sent */
238 if (*(void **) src == NULL) {
239 VERB0("Not copying NULL referenced data");
240 *(void **) dst = NULL;
243 o_ref = (char **) src;
245 reference_is_to_cpy = 1;
247 (n_ref=xbt_dict_get_or_null_ext(refs, (char *) o_ref, sizeof(char *))))
248 /* already known, no need to copy it */
249 reference_is_to_cpy = 0;
251 if (reference_is_to_cpy) {
252 int subsubcount = -1;
253 void *l_referenced = NULL;
254 VERB2("Copy a ref to '%s' referenced at %p", sub_type->name,
258 pointer_type = gras_datadesc_by_name("data pointer");
259 xbt_assert(pointer_type);
262 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
263 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
264 gras_dd_cat_array_t array_data = sub_type->category.array_data;
265 gras_datadesc_type_t subsub_type;
267 subsub_type = array_data.type;
268 subsubcount = array_data.fixed_size;
269 if (subsubcount == -1)
270 subsubcount = array_data.dynamic_size(subsub_type, state, *o_ref);
272 if (subsubcount != 0)
273 gras_dd_alloc_ref(refs,
274 subsub_type->size[GRAS_THISARCH] * subsubcount,
275 o_ref, pointer_type->size[GRAS_THISARCH],
276 (char **) &l_referenced, detect_cycle);
278 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
279 o_ref, pointer_type->size[GRAS_THISARCH],
280 (char **) &l_referenced, detect_cycle);
283 count += gras_datadesc_memcpy_rec(state, refs, sub_type,
284 *o_ref, (char *) l_referenced,
285 subsubcount, detect_cycle
288 *(void **) dst = l_referenced;
289 VERB3("'%s' previously referenced at %p now at %p",
290 sub_type->name, *(void **) o_ref, l_referenced);
294 ("NOT copying data previously referenced @%p (already done, @%p now)",
295 *(void **) o_ref, *(void **) n_ref);
297 *(void **) dst = *n_ref;
303 case e_gras_datadesc_type_cat_array:{
304 gras_dd_cat_array_t array_data;
305 unsigned long int array_count;
310 array_data = type->category.array_data;
312 /* determine and send the element count */
313 array_count = array_data.fixed_size;
314 if (array_count == -1)
315 array_count = subsize;
316 if (array_count == -1) {
317 array_count = array_data.dynamic_size(type, state, src);
318 xbt_assert1(array_count >= 0,
319 "Invalid (negative) array size for type %s", type->name);
322 /* send the content */
323 sub_type = array_data.type;
324 elm_size = sub_type->aligned_size[GRAS_THISARCH];
325 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
326 VERB1("Array of %ld scalars, copy it in one shot", array_count);
327 memcpy(dst, src, sub_type->aligned_size[GRAS_THISARCH] * array_count);
328 count += sub_type->aligned_size[GRAS_THISARCH] * array_count;
329 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
330 sub_type->category.array_data.fixed_size > 0 &&
331 sub_type->category.array_data.type->category_code ==
332 e_gras_datadesc_type_cat_scalar) {
334 VERB1("Array of %ld fixed array of scalars, copy it in one shot",
337 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
338 * array_count * sub_type->category.array_data.fixed_size);
340 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
341 * array_count * sub_type->category.array_data.fixed_size;
344 VERB1("Array of %ld stuff, copy it in one after the other",
346 for (cpt = 0; cpt < array_count; cpt++) {
347 VERB2("Copy the %dth stuff out of %ld", cpt, array_count);
349 gras_datadesc_memcpy_rec(state, refs, sub_type, src_ptr, dst_ptr,
350 0, detect_cycle || sub_type->cycle);
359 xbt_die("Invalid type");
366 * gras_datadesc_memcpy:
368 * Copy the data pointed by src and described by type
369 * to a new location, and store a pointer to it in dst.
372 int gras_datadesc_memcpy(gras_datadesc_type_t type, void *src, void *dst)
375 static gras_cbps_t state = NULL;
376 static xbt_dict_t refs = NULL; /* all references already sent */
379 xbt_assert0(type, "called with NULL type descriptor");
381 DEBUG3("Memcopy a %s from %p to %p", gras_datadesc_get_name(type), src,
384 state = gras_cbps_new();
385 refs = xbt_dict_new();
390 gras_datadesc_memcpy_rec(state, refs, type, (char *) src, (char *) dst,
393 xbt_dict_reset(refs);
394 gras_cbps_reset(state);
402 *** Direct use functions
406 gras_datadesc_send_rec(gras_socket_t sock,
409 gras_datadesc_type_t type,
410 char *data, int detect_cycle)
414 gras_datadesc_type_t sub_type; /* type on which we recurse */
416 VERB2("Send a %s (%s)",
417 type->name, gras_datadesc_cat_names[type->category_code]);
419 if (!strcmp(type->name, "string"))
420 VERB1("value: '%s'", *(char **) data);
423 type->send(type, state, data);
424 DEBUG0("Run the emission callback");
427 switch (type->category_code) {
428 case e_gras_datadesc_type_cat_scalar:
429 gras_trp_send(sock, data, type->size[GRAS_THISARCH], 1);
432 case e_gras_datadesc_type_cat_struct:{
433 gras_dd_cat_struct_t struct_data;
434 gras_dd_cat_field_t field;
437 struct_data = type->category.struct_data;
438 xbt_assert1(struct_data.closed,
439 "Please call gras_datadesc_declare_struct_close on %s before sending it",
441 VERB1(">> Send all fields of the structure %s", type->name);
442 xbt_dynar_foreach(struct_data.fields, cpt, field) {
444 field_data += field->offset[GRAS_THISARCH];
446 sub_type = field->type;
449 DEBUG1("Run the emission callback of field %s", field->name);
450 field->send(type, state, field_data);
453 VERB1("Send field %s", field->name);
454 gras_datadesc_send_rec(sock, state, refs, sub_type, field_data,
455 detect_cycle || sub_type->cycle);
458 VERB1("<< Sent all fields of the structure %s", type->name);
463 case e_gras_datadesc_type_cat_union:{
464 gras_dd_cat_union_t union_data;
465 gras_dd_cat_field_t field = NULL;
468 union_data = type->category.union_data;
470 xbt_assert1(union_data.closed,
471 "Please call gras_datadesc_declare_union_close on %s before sending it",
473 /* retrieve the field number */
474 field_num = union_data.selector(type, state, data);
476 xbt_assert1(field_num > 0,
477 "union field selector of %s gave a negative value",
480 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
481 "union field selector of %s returned %d but there is only %lu fields",
482 type->name, field_num, xbt_dynar_length(union_data.fields));
484 /* Send the field number */
485 gras_dd_send_int(sock, &field_num, 0 /* not stable */ );
487 /* Send the content */
489 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
490 sub_type = field->type;
493 field->send(type, state, data);
495 gras_datadesc_send_rec(sock, state, refs, sub_type, data,
496 detect_cycle || sub_type->cycle);
501 case e_gras_datadesc_type_cat_ref:{
502 gras_dd_cat_ref_t ref_data;
503 void **ref = (void **) data;
504 int reference_is_to_send;
506 ref_data = type->category.ref_data;
508 /* Detect the referenced type and send it to peer if needed */
509 sub_type = ref_data.type;
510 if (sub_type == NULL) {
511 sub_type = (*ref_data.selector) (type, state, data);
512 gras_dd_send_int(sock, &(sub_type->code), 1 /*stable */ );
515 /* Send the actual value of the pointer for cycle handling */
517 pointer_type = gras_datadesc_by_name("data pointer");
518 xbt_assert(pointer_type);
521 gras_trp_send(sock, (char *) data,
522 pointer_type->size[GRAS_THISARCH], 1 /*stable */ );
524 /* Send the pointed data only if not already sent */
525 if (*(void **) data == NULL) {
526 VERB0("Not sending NULL referenced data");
530 reference_is_to_send = 1;
531 /* return ignored. Just checking whether it's known or not */
532 if (detect_cycle && xbt_dict_get_or_null_ext(refs, (char *) ref, sizeof(char *)))
533 reference_is_to_send = 0;
535 if (reference_is_to_send) {
536 VERB1("Sending data referenced at %p", (void *) *ref);
538 xbt_dict_set_ext(refs, (char *) ref, sizeof(void *), ref, NULL);
539 gras_datadesc_send_rec(sock, state, refs, sub_type, *ref,
540 detect_cycle || sub_type->cycle);
543 VERB1("Not sending data referenced at %p (already done)",
550 case e_gras_datadesc_type_cat_array:{
551 gras_dd_cat_array_t array_data;
556 array_data = type->category.array_data;
558 /* determine and send the element count */
559 count = array_data.fixed_size;
561 count = array_data.dynamic_size(type, state, data);
562 xbt_assert1(count >= 0,
563 "Invalid (negative) array size for type %s", type->name);
564 gras_dd_send_int(sock, &count, 0 /*non-stable */ );
567 /* send the content */
568 sub_type = array_data.type;
569 elm_size = sub_type->aligned_size[GRAS_THISARCH];
570 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
571 VERB1("Array of %d scalars, send it in one shot", count);
572 gras_trp_send(sock, data,
573 sub_type->aligned_size[GRAS_THISARCH] * count,
574 0 /* not stable */ );
575 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
576 sub_type->category.array_data.fixed_size > 0 &&
577 sub_type->category.array_data.type->category_code ==
578 e_gras_datadesc_type_cat_scalar) {
580 VERB1("Array of %d fixed array of scalars, send it in one shot",
582 gras_trp_send(sock, data,
583 sub_type->category.array_data.
584 type->aligned_size[GRAS_THISARCH]
585 * count * sub_type->category.array_data.fixed_size,
586 0 /* not stable */ );
589 for (cpt = 0; cpt < count; cpt++) {
590 gras_datadesc_send_rec(sock, state, refs, sub_type, ptr,
591 detect_cycle || sub_type->cycle);
599 xbt_die("Invalid type");
604 * gras_datadesc_send:
606 * Copy the data pointed by src and described by type to the socket
609 void gras_datadesc_send(gras_socket_t sock,
610 gras_datadesc_type_t type, void *src)
614 static gras_cbps_t state = NULL;
615 static xbt_dict_t refs = NULL; /* all references already sent */
617 xbt_assert0(type, "called with NULL type descriptor");
620 state = gras_cbps_new();
621 refs = xbt_dict_new();
625 gras_datadesc_send_rec(sock, state, refs, type, (char *) src,
628 xbt_dict_reset(refs);
629 gras_cbps_reset(state);
636 * gras_datadesc_recv_rec:
638 * Do the data reception job recursively.
640 * subsize used only to deal with vicious case of reference to dynamic array.
641 * This size is needed at the reference reception level (to allocate enough
642 * space) and at the array reception level (to fill enough room).
644 * Having this size passed as an argument of the recursive function is a crude
645 * hack, but I was told that working code is sometimes better than neat one ;)
648 gras_datadesc_recv_rec(gras_socket_t sock,
651 gras_datadesc_type_t type,
655 char *l_data, int subsize, int detect_cycle)
659 gras_datadesc_type_t sub_type;
661 VERB2("Recv a %s @%p", type->name, (void *) l_data);
664 switch (type->category_code) {
665 case e_gras_datadesc_type_cat_scalar:
666 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
667 gras_trp_recv(sock, (char *) l_data, type->size[r_arch]);
668 if (r_arch != GRAS_THISARCH)
669 gras_dd_convert_elm(type, 1, r_arch, l_data, l_data);
671 void *ptr = xbt_malloc(type->size[r_arch]);
673 gras_trp_recv(sock, (char *) ptr, type->size[r_arch]);
674 if (r_arch != GRAS_THISARCH)
675 gras_dd_convert_elm(type, 1, r_arch, ptr, l_data);
680 case e_gras_datadesc_type_cat_struct:{
681 gras_dd_cat_struct_t struct_data;
682 gras_dd_cat_field_t field;
684 struct_data = type->category.struct_data;
686 xbt_assert1(struct_data.closed,
687 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
689 VERB1(">> Receive all fields of the structure %s", type->name);
690 xbt_dynar_foreach(struct_data.fields, cpt, field) {
691 char *field_data = l_data + field->offset[GRAS_THISARCH];
693 sub_type = field->type;
695 gras_datadesc_recv_rec(sock, state, refs, sub_type,
698 detect_cycle || sub_type->cycle);
701 DEBUG1("Run the reception callback of field %s", field->name);
702 field->recv(type, state, (void *) l_data);
706 VERB1("<< Received all fields of the structure %s", type->name);
711 case e_gras_datadesc_type_cat_union:{
712 gras_dd_cat_union_t union_data;
713 gras_dd_cat_field_t field = NULL;
716 union_data = type->category.union_data;
718 xbt_assert1(union_data.closed,
719 "Please call gras_datadesc_declare_union_close on %s before receiving it",
721 /* retrieve the field number */
722 gras_dd_recv_int(sock, r_arch, &field_num);
724 THROW1(mismatch_error, 0,
725 "Received union field for %s is negative", type->name);
726 if (field_num > xbt_dynar_length(union_data.fields))
727 THROW3(mismatch_error, 0,
728 "Received union field for %s is said to be #%d but there is only %lu fields",
729 type->name, field_num, xbt_dynar_length(union_data.fields));
731 /* Recv the content */
733 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
734 sub_type = field->type;
736 gras_datadesc_recv_rec(sock, state, refs, sub_type,
738 l_data, -1, detect_cycle || sub_type->cycle);
740 field->recv(type, state, l_data);
745 case e_gras_datadesc_type_cat_ref:{
748 gras_dd_cat_ref_t ref_data;
749 int reference_is_to_recv = 0;
751 ref_data = type->category.ref_data;
753 /* Get the referenced type locally or from peer */
754 sub_type = ref_data.type;
755 if (sub_type == NULL) {
757 gras_dd_recv_int(sock, r_arch, &ref_code);
758 sub_type = gras_datadesc_by_id(ref_code);
761 /* Get the actual value of the pointer for cycle handling */
763 pointer_type = gras_datadesc_by_name("data pointer");
764 xbt_assert(pointer_type);
767 r_ref = xbt_malloc(pointer_type->size[r_arch]);
769 gras_trp_recv(sock, (char *) r_ref, pointer_type->size[r_arch]);
771 /* Receive the pointed data only if not already sent */
772 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
773 VERB1("Not receiving data remotely referenced @%p since it's NULL",
775 *(void **) l_data = NULL;
780 reference_is_to_recv = 1;
781 if (detect_cycle && (l_ref =
782 xbt_dict_get_or_null_ext(refs, (char *) r_ref,
783 pointer_type->size[r_arch])))
784 reference_is_to_recv = 0;
786 if (reference_is_to_recv) {
787 int subsubcount = -1;
788 void *l_referenced = NULL;
790 VERB2("Receiving a ref to '%s', remotely @%p",
791 sub_type->name, *(void **) r_ref);
792 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
793 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
794 gras_dd_cat_array_t array_data = sub_type->category.array_data;
795 gras_datadesc_type_t subsub_type;
797 subsubcount = array_data.fixed_size;
798 if (subsubcount == -1)
799 gras_dd_recv_int(sock, r_arch, &subsubcount);
801 subsub_type = array_data.type;
803 if (subsubcount != 0)
804 gras_dd_alloc_ref(refs,
805 subsub_type->size[GRAS_THISARCH] * subsubcount,
806 r_ref, pointer_type->size[r_arch],
807 (char **) &l_referenced, detect_cycle);
811 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
812 r_ref, pointer_type->size[r_arch],
813 (char **) &l_referenced, detect_cycle);
816 if (l_referenced != NULL)
817 gras_datadesc_recv_rec(sock, state, refs, sub_type,
818 r_arch, r_ref, pointer_type->size[r_arch],
819 (char *) l_referenced, subsubcount,
820 detect_cycle || sub_type->cycle);
822 *(void **) l_data = l_referenced;
823 VERB3("'%s' remotely referenced at %p locally at %p",
824 sub_type->name, *(void **) r_ref, l_referenced);
828 ("NOT receiving data remotely referenced @%p (already done, @%p here)",
829 *(void **) r_ref, *(void **) l_ref);
831 *(void **) l_data = *l_ref;
838 case e_gras_datadesc_type_cat_array:{
839 gras_dd_cat_array_t array_data;
844 array_data = type->category.array_data;
845 /* determine element count locally, or from caller, or from peer */
846 count = array_data.fixed_size;
850 gras_dd_recv_int(sock, r_arch, &count);
852 THROW1(mismatch_error, 0,
853 "Invalid (=-1) array size for type %s", type->name);
855 /* receive the content */
856 sub_type = array_data.type;
857 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
858 VERB1("Array of %d scalars, get it in one shoot", count);
859 if (sub_type->aligned_size[GRAS_THISARCH] >=
860 sub_type->aligned_size[r_arch]) {
861 gras_trp_recv(sock, (char *) l_data,
862 sub_type->aligned_size[r_arch] * count);
863 if (r_arch != GRAS_THISARCH)
864 gras_dd_convert_elm(sub_type, count, r_arch, l_data, l_data);
866 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
868 gras_trp_recv(sock, (char *) ptr, sub_type->size[r_arch] * count);
869 if (r_arch != GRAS_THISARCH)
870 gras_dd_convert_elm(sub_type, count, r_arch, ptr, l_data);
873 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
874 sub_type->category.array_data.fixed_size >= 0 &&
875 sub_type->category.array_data.type->category_code ==
876 e_gras_datadesc_type_cat_scalar) {
877 gras_datadesc_type_t subsub_type;
878 array_data = sub_type->category.array_data;
879 subsub_type = array_data.type;
881 VERB1("Array of %d fixed array of scalars, get it in one shot",
883 if (subsub_type->aligned_size[GRAS_THISARCH] >=
884 subsub_type->aligned_size[r_arch]) {
885 gras_trp_recv(sock, (char *) l_data,
886 subsub_type->aligned_size[r_arch] * count *
887 array_data.fixed_size);
888 if (r_arch != GRAS_THISARCH)
889 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
890 r_arch, l_data, l_data);
893 xbt_malloc(subsub_type->aligned_size[r_arch] * count *
894 array_data.fixed_size);
896 gras_trp_recv(sock, (char *) ptr,
897 subsub_type->size[r_arch] * count *
898 array_data.fixed_size);
899 if (r_arch != GRAS_THISARCH)
900 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
901 r_arch, ptr, l_data);
907 /* not scalar content, get it recursively (may contain pointers) */
908 elm_size = sub_type->aligned_size[GRAS_THISARCH];
909 VERB2("Receive a %d-long array of %s", count, sub_type->name);
912 for (cpt = 0; cpt < count; cpt++) {
913 gras_datadesc_recv_rec(sock, state, refs, sub_type,
914 r_arch, NULL, 0, ptr, -1,
915 detect_cycle || sub_type->cycle);
924 xbt_die("Invalid type");
928 type->recv(type, state, l_data);
930 if (!strcmp(type->name, "string"))
931 VERB1("value: '%s'", *(char **) l_data);
936 * gras_datadesc_recv:
938 * Get an instance of the datatype described by @type from the @socket,
939 * and store a pointer to it in @dst
943 gras_datadesc_recv(gras_socket_t sock,
944 gras_datadesc_type_t type, int r_arch, void *dst)
948 static gras_cbps_t state = NULL; /* callback persistent state */
949 static xbt_dict_t refs = NULL; /* all references already sent */
952 state = gras_cbps_new();
953 refs = xbt_dict_new();
956 xbt_assert0(type, "called with NULL type descriptor");
958 gras_datadesc_recv_rec(sock, state, refs, type,
959 r_arch, NULL, 0, (char *) dst, -1, type->cycle);
961 xbt_dict_reset(refs);
962 gras_cbps_reset(state);