3 /* ddt_exchange - send/recv data described */
5 /* Copyright (c) 2003 Olivier Aumage. */
6 /* Copyright (c) 2003, 2004 Martin Quinson. */
7 /* All rights reserved. */
9 /* This program is free software; you can redistribute it and/or modify it
10 * under the terms of the license (GNU LGPL) which comes with this package. */
12 #include "gras/DataDesc/datadesc_private.h"
13 #include "gras/Transport/transport_interface.h" /* gras_trp_chunk_send/recv */
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ddt_exchange,datadesc,
16 "Sending data over the network");
17 const char *gras_datadesc_cat_names[9] = {
19 "scalar", "struct", "union", "ref", "array", "ignored",
22 static gras_datadesc_type_t int_type = NULL;
23 static gras_datadesc_type_t pointer_type = NULL;
24 static _XBT_INLINE xbt_error_t gras_dd_send_int(gras_socket_t sock, int i);
25 static _XBT_INLINE xbt_error_t gras_dd_recv_int(gras_socket_t sock, int r_arch, int *i);
27 static _XBT_INLINE xbt_error_t
28 gras_dd_alloc_ref(xbt_dict_t refs, long int size,
29 char **r_ref, long int r_len,
30 char **l_ref, int detect_cycle);
32 static _XBT_INLINE int
33 gras_dd_is_r_null(char **r_ptr, long int length);
35 static _XBT_INLINE xbt_error_t
36 gras_dd_send_int(gras_socket_t sock,int i) {
39 int_type = gras_datadesc_by_name("int");
43 DEBUG1("send_int(%d)",i);
44 return gras_trp_chunk_send(sock, (char*)&i, int_type->size[GRAS_THISARCH]);
47 static _XBT_INLINE xbt_error_t
48 gras_dd_recv_int(gras_socket_t sock, int r_arch, int *i) {
52 int_type = gras_datadesc_by_name("int");
56 if (int_type->size[GRAS_THISARCH] >= int_type->size[r_arch]) {
57 TRY(gras_trp_chunk_recv(sock, (char*)i, int_type->size[r_arch]));
58 if (r_arch != GRAS_THISARCH)
59 TRY(gras_dd_convert_elm(int_type,1,r_arch, i,i));
61 void *ptr = xbt_malloc(int_type->size[r_arch]);
63 TRY(gras_trp_chunk_recv(sock, (char*)ptr, int_type->size[r_arch]));
64 if (r_arch != GRAS_THISARCH)
65 TRY(gras_dd_convert_elm(int_type,1,r_arch, ptr,i));
68 DEBUG1("recv_int(%d)",*i);
74 * Note: here we suppose that the remote NULL is a sequence
75 * of 'length' bytes set to 0.
76 * FIXME: Check in configure?
78 static _XBT_INLINE int
79 gras_dd_is_r_null(char **r_ptr, long int length) {
82 for (i=0; i<length; i++) {
83 if ( ((unsigned char*)r_ptr) [i]) {
91 static _XBT_INLINE xbt_error_t
92 gras_dd_alloc_ref(xbt_dict_t refs,
95 long int r_len, /* pointer_type->size[r_arch] */
100 xbt_assert1(size>0,"Cannot allocate %ld bytes!", size);
101 l_data = xbt_malloc((size_t)size);
104 DEBUG2("l_data=%p, &l_data=%p",(void*)l_data,(void*)&l_data);
106 DEBUG3("alloc_ref: r_ref=%p; *r_ref=%p, r_len=%ld",
107 (void*)r_ref, (void*)(r_ref?*r_ref:NULL), r_len);
108 if (detect_cycle && r_ref && !gras_dd_is_r_null( r_ref, r_len)) {
109 void *ptr = xbt_malloc(sizeof(void *));
111 CRITICAL0("detect_cycle");
112 memcpy(ptr,l_ref, sizeof(void *));
114 DEBUG2("Insert %p under %p",*(void**)ptr, *(void**)r_ref);
117 xbt_dict_set_ext(refs,(const char *) r_ref, r_len, ptr, free);
125 * Copy the data pointed by src and described by type
126 * to a new location, and store a pointer to it in dst.
129 xbt_error_t gras_datadesc_cpy(gras_datadesc_type_t type,
136 *** Direct use functions
140 gras_datadesc_send_rec(gras_socket_t sock,
143 gras_datadesc_type_t type,
149 gras_datadesc_type_t sub_type; /* type on which we recurse */
151 VERB2("Send a %s (%s)",
152 type->name, gras_datadesc_cat_names[type->category_code]);
155 type->send(state,data);
158 switch (type->category_code) {
159 case e_gras_datadesc_type_cat_scalar:
160 TRY(gras_trp_chunk_send(sock, data, type->size[GRAS_THISARCH]));
163 case e_gras_datadesc_type_cat_struct: {
164 gras_dd_cat_struct_t struct_data;
165 gras_dd_cat_field_t field;
168 struct_data = type->category.struct_data;
169 xbt_assert1(struct_data.closed,
170 "Please call gras_datadesc_declare_struct_close on %s before sending it",
172 VERB1(">> Send all fields of the structure %s",type->name);
173 xbt_dynar_foreach(struct_data.fields, cpt, field) {
175 field_data += field->offset[GRAS_THISARCH];
177 sub_type = field->type;
180 field->pre(state,field_data);
182 VERB1("Send field %s",field->name);
183 TRY(gras_datadesc_send_rec(sock,state,refs,sub_type, field_data, detect_cycle || sub_type->cycle));
186 field->post(state,field_data);
188 VERB1("<< Sent all fields of the structure %s", type->name);
193 case e_gras_datadesc_type_cat_union: {
194 gras_dd_cat_union_t union_data;
195 gras_dd_cat_field_t field=NULL;
198 union_data = type->category.union_data;
200 xbt_assert1(union_data.closed,
201 "Please call gras_datadesc_declare_union_close on %s before sending it",
203 /* retrieve the field number */
204 field_num = union_data.selector(state, data);
206 xbt_assert1(field_num > 0,
207 "union field selector of %s gave a negative value",
210 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
211 "union field selector of %s returned %d but there is only %lu fields",
212 type->name, field_num, xbt_dynar_length(union_data.fields));
214 /* Send the field number */
215 TRY(gras_dd_send_int(sock, field_num));
217 /* Send the content */
218 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
219 sub_type = field->type;
222 field->pre(state,data);
224 TRY(gras_datadesc_send_rec(sock,state,refs, sub_type, data, detect_cycle || sub_type->cycle));
227 field->post(state,data);
232 case e_gras_datadesc_type_cat_ref: {
233 gras_dd_cat_ref_t ref_data;
235 void **ref=(void**)data;
238 ref_data = type->category.ref_data;
240 /* Detect the referenced type and send it to peer if needed */
241 sub_type = ref_data.type;
242 if (sub_type == NULL) {
243 sub_type = (*ref_data.selector)(state,data);
244 TRY(gras_dd_send_int(sock, sub_type->code));
247 /* Send the actual value of the pointer for cycle handling */
249 pointer_type = gras_datadesc_by_name("data pointer");
250 xbt_assert(pointer_type);
253 TRY(gras_trp_chunk_send(sock, (char*)data,
254 pointer_type->size[GRAS_THISARCH]));
256 /* Send the pointed data only if not already sent */
257 if (*(void**)data == NULL) {
258 VERB0("Not sending NULL referenced data");
261 errcode = detect_cycle
262 ? xbt_dict_get_ext(refs,(char*)ref, sizeof(void*), &dummy)
264 if (errcode == mismatch_error) {
265 VERB1("Sending data referenced at %p", (void*)*ref);
267 xbt_dict_set_ext(refs, (char*)ref, sizeof(void*), ref, NULL);
268 TRY(gras_datadesc_send_rec(sock,state,refs, sub_type, *ref, detect_cycle || sub_type->cycle));
270 } else if (errcode == no_error) {
271 VERB1("Not sending data referenced at %p (already done)", (void*)*ref);
279 case e_gras_datadesc_type_cat_array: {
280 gras_dd_cat_array_t array_data;
285 array_data = type->category.array_data;
287 /* determine and send the element count */
288 count = array_data.fixed_size;
290 count = array_data.dynamic_size(state,data);
291 xbt_assert1(count >=0,
292 "Invalid (negative) array size for type %s",type->name);
293 TRY(gras_dd_send_int(sock, count));
296 /* send the content */
297 sub_type = array_data.type;
298 elm_size = sub_type->aligned_size[GRAS_THISARCH];
299 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
300 VERB1("Array of %ld scalars, send it in one shot",count);
301 TRY(gras_trp_chunk_send(sock, data,
302 sub_type->aligned_size[GRAS_THISARCH] * count));
303 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
304 sub_type->category.array_data.fixed_size > 0 &&
305 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
307 VERB1("Array of %ld fixed array of scalars, send it in one shot",count);
308 TRY(gras_trp_chunk_send(sock, data,
309 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
310 * count * sub_type->category.array_data.fixed_size));
313 for (cpt=0; cpt<count; cpt++) {
314 TRY(gras_datadesc_send_rec(sock,state,refs, sub_type, ptr, detect_cycle || sub_type->cycle));
322 xbt_assert0(0, "Invalid type");
329 * gras_datadesc_send:
331 * Copy the data pointed by src and described by type to the socket
334 xbt_error_t gras_datadesc_send(gras_socket_t sock,
335 gras_datadesc_type_t type,
340 xbt_dict_t refs; /* all references already sent */
342 refs = xbt_dict_new();
343 state = gras_cbps_new();
345 errcode = gras_datadesc_send_rec(sock,state,refs,type,(char*)src, type->cycle);
347 xbt_dict_free(&refs);
348 gras_cbps_free(&state);
354 * gras_datadesc_recv_rec:
356 * Do the data reception job recursively.
358 * subsize used only to deal with vicious case of reference to dynamic array.
359 * This size is needed at the reference reception level (to allocate enough
360 * space) and at the array reception level (to fill enough room).
362 * Having this size passed as an argument of the recursive function is a crude
363 * hack, but I was told that working code is sometimes better than neat one ;)
366 gras_datadesc_recv_rec(gras_socket_t sock,
369 gras_datadesc_type_t type,
379 gras_datadesc_type_t sub_type;
381 VERB2("Recv a %s @%p", type->name, (void*)l_data);
384 switch (type->category_code) {
385 case e_gras_datadesc_type_cat_scalar:
386 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
387 TRY(gras_trp_chunk_recv(sock, (char*)l_data, type->size[r_arch]));
388 if (r_arch != GRAS_THISARCH)
389 TRY(gras_dd_convert_elm(type,1,r_arch, l_data,l_data));
391 void *ptr = xbt_malloc(type->size[r_arch]);
393 TRY(gras_trp_chunk_recv(sock, (char*)ptr, type->size[r_arch]));
394 if (r_arch != GRAS_THISARCH)
395 TRY(gras_dd_convert_elm(type,1,r_arch, ptr,l_data));
400 case e_gras_datadesc_type_cat_struct: {
401 gras_dd_cat_struct_t struct_data;
402 gras_dd_cat_field_t field;
404 struct_data = type->category.struct_data;
406 xbt_assert1(struct_data.closed,
407 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
409 VERB1(">> Receive all fields of the structure %s",type->name);
410 xbt_dynar_foreach(struct_data.fields, cpt, field) {
411 char *field_data = l_data + field->offset[GRAS_THISARCH];
413 sub_type = field->type;
415 TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
418 detect_cycle || sub_type->cycle));
420 VERB1("<< Received all fields of the structure %s", type->name);
425 case e_gras_datadesc_type_cat_union: {
426 gras_dd_cat_union_t union_data;
427 gras_dd_cat_field_t field=NULL;
430 union_data = type->category.union_data;
432 xbt_assert1(union_data.closed,
433 "Please call gras_datadesc_declare_union_close on %s before receiving it",
435 /* retrieve the field number */
436 TRY(gras_dd_recv_int(sock, r_arch, &field_num));
438 RAISE1(mismatch_error,
439 "Received union field for %s is negative", type->name);
440 if (field_num < xbt_dynar_length(union_data.fields))
441 RAISE3(mismatch_error,
442 "Received union field for %s is %d but there is only %lu fields",
443 type->name, field_num, xbt_dynar_length(union_data.fields));
445 /* Recv the content */
446 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
447 sub_type = field->type;
449 TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
452 detect_cycle || sub_type->cycle));
456 case e_gras_datadesc_type_cat_ref: {
459 gras_dd_cat_ref_t ref_data;
461 ref_data = type->category.ref_data;
463 /* Get the referenced type locally or from peer */
464 sub_type = ref_data.type;
465 if (sub_type == NULL) {
467 TRY(gras_dd_recv_int(sock, r_arch, &ref_code));
468 TRY(gras_datadesc_by_id(ref_code, &sub_type));
471 /* Get the actual value of the pointer for cycle handling */
473 pointer_type = gras_datadesc_by_name("data pointer");
474 xbt_assert(pointer_type);
477 r_ref = xbt_malloc(pointer_type->size[r_arch]);
479 TRY(gras_trp_chunk_recv(sock, (char*)r_ref,
480 pointer_type->size[r_arch]));
482 /* Receive the pointed data only if not already sent */
483 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
484 VERB1("Not receiving data remotely referenced @%p since it's NULL",
486 *(void**)l_data = NULL;
491 errcode = detect_cycle
492 ? xbt_dict_get_ext(refs,
493 (char*)r_ref, pointer_type->size[r_arch],
497 if (errcode == mismatch_error) {
499 void *l_referenced=NULL;
501 VERB2("Receiving a ref to '%s', remotely @%p",
502 sub_type->name, *(void**)r_ref);
503 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
504 /* Damn. Reference to a dynamic array. Allocating the size for it
505 is more complicated */
506 gras_dd_cat_array_t array_data = sub_type->category.array_data;
507 gras_datadesc_type_t subsub_type;
509 subsubcount = array_data.fixed_size;
510 if (subsubcount == 0)
511 TRY(gras_dd_recv_int(sock, r_arch, &subsubcount));
513 subsub_type = array_data.type;
516 TRY(gras_dd_alloc_ref(refs,
517 subsub_type->size[GRAS_THISARCH] * subsubcount,
518 r_ref,pointer_type->size[r_arch],
519 (char**)&l_referenced,
522 TRY(gras_dd_alloc_ref(refs,sub_type->size[GRAS_THISARCH],
523 r_ref,pointer_type->size[r_arch],
524 (char**)&l_referenced,
528 TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
529 r_arch,r_ref,pointer_type->size[r_arch],
530 (char*)l_referenced, subsubcount,
531 detect_cycle || sub_type->cycle));
532 *(void**)l_data=l_referenced;
533 VERB3("'%s' remotely referenced at %p locally at %p",
534 sub_type->name, *(void**)r_ref, l_referenced);
536 } else if (errcode == no_error) {
537 VERB2("NOT receiving data remotely referenced @%p (already done, @%p here)",
538 *(void**)r_ref, *(void**)l_ref);
540 *(void**)l_data=*l_ref;
549 case e_gras_datadesc_type_cat_array: {
550 gras_dd_cat_array_t array_data;
555 array_data = type->category.array_data;
556 /* determine element count locally, or from caller, or from peer */
557 count = array_data.fixed_size;
561 TRY(gras_dd_recv_int(sock, r_arch, &count));
563 RAISE1(mismatch_error,
564 "Invalid (=0) array size for type %s",type->name);
566 /* receive the content */
567 sub_type = array_data.type;
568 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
569 VERB1("Array of %d scalars, get it in one shoot", count);
570 if (sub_type->aligned_size[GRAS_THISARCH] >=
571 sub_type->aligned_size[r_arch]) {
572 TRY(gras_trp_chunk_recv(sock, (char*)l_data,
573 sub_type->aligned_size[r_arch] * count));
574 if (r_arch != GRAS_THISARCH)
575 TRY(gras_dd_convert_elm(sub_type,count,r_arch, l_data,l_data));
577 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
579 TRY(gras_trp_chunk_recv(sock, (char*)ptr,
580 sub_type->size[r_arch] * count));
581 if (r_arch != GRAS_THISARCH)
582 TRY(gras_dd_convert_elm(sub_type,count,r_arch, ptr,l_data));
585 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
586 sub_type->category.array_data.fixed_size > 0 &&
587 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
588 gras_datadesc_type_t subsub_type;
589 array_data = sub_type->category.array_data;
590 subsub_type = array_data.type;
592 VERB1("Array of %d fixed array of scalars, get it in one shot",count);
593 if (subsub_type->aligned_size[GRAS_THISARCH] >=
594 subsub_type->aligned_size[r_arch]) {
595 TRY(gras_trp_chunk_recv(sock, (char*)l_data,
596 subsub_type->aligned_size[r_arch] * count *
597 array_data.fixed_size));
598 if (r_arch != GRAS_THISARCH)
599 TRY(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, l_data,l_data));
601 ptr = xbt_malloc(subsub_type->aligned_size[r_arch] * count*array_data.fixed_size);
603 TRY(gras_trp_chunk_recv(sock, (char*)ptr,
604 subsub_type->size[r_arch] * count*array_data.fixed_size));
605 if (r_arch != GRAS_THISARCH)
606 TRY(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, ptr,l_data));
612 /* not scalar content, get it recursively (may contain pointers) */
613 elm_size = sub_type->aligned_size[GRAS_THISARCH];
614 VERB2("Receive a %d-long array of %s",count, sub_type->name);
617 for (cpt=0; cpt<count; cpt++) {
618 TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
619 r_arch, NULL, 0, ptr,-1,
620 detect_cycle || sub_type->cycle));
628 xbt_assert0(0, "Invalid type");
632 type->recv(state,l_data);
638 * gras_datadesc_recv:
640 * Get an instance of the datatype described by @type from the @socket,
641 * and store a pointer to it in @dst
645 gras_datadesc_recv(gras_socket_t sock,
646 gras_datadesc_type_t type,
651 gras_cbps_t state; /* callback persistent state */
652 xbt_dict_t refs; /* all references already sent */
654 refs = xbt_dict_new();
655 state = gras_cbps_new();
657 errcode = gras_datadesc_recv_rec(sock, state, refs, type,
662 xbt_dict_free(&refs);
663 gras_cbps_free(&state);
670 *** IDL compiling functions
673 #define gras_datadesc_send_rec foo /* Just to make sure the copypast was ok */
674 #define gras_datadesc_send foo /* Just to make sure the copypast was ok */
675 #define gras_datadesc_recv_rec foo /* Just to make sure the copypast was ok */
676 #define gras_datadesc_recv foo /* Just to make sure the copypast was ok */
679 gras_datadesc_gen_send_rec(gras_socket_t sock,
682 gras_datadesc_type_t type,
688 gras_datadesc_type_t sub_type; /* type on which we recurse */
690 printf(" VERB2(\"Send a %s (%s)\");\n",
691 type->name, gras_datadesc_cat_names[type->category_code]);
693 xbt_assert0(!type->send, "Callbacks not implemented in IDL compiler");
695 switch (type->category_code) {
696 case e_gras_datadesc_type_cat_scalar:
697 printf(" TRY(gras_trp_chunk_send(sock, data, %lu));\n",type->size[GRAS_THISARCH]);
700 case e_gras_datadesc_type_cat_struct: {
701 gras_dd_cat_struct_t struct_data;
702 gras_dd_cat_field_t field;
705 struct_data = type->category.struct_data;
706 xbt_assert1(struct_data.closed,
707 "Please call gras_datadesc_declare_struct_close on %s before sending it",
709 printf(" VERB1(\">> Send all fields of the structure %s\");\n",type->name);
710 xbt_dynar_foreach(struct_data.fields, cpt, field) {
712 field_data += field->offset[GRAS_THISARCH];
714 sub_type = field->type;
716 xbt_assert0(!field->pre, "Callbacks not implemented in IDL compiler");
718 printf(" VERB1(\"Send field %s\");\n",field->name);
719 printf(" data += %lu;\n",field->offset[GRAS_THISARCH]);
720 TRY(gras_datadesc_gen_send_rec(sock,state,refs,sub_type, field_data, detect_cycle || sub_type->cycle));
721 printf(" data -= %lu;\n",field->offset[GRAS_THISARCH]);
723 xbt_assert0(!field->post, "Callbacks not implemented in IDL compiler");
725 printf(" VERB1(\"<< Sent all fields of the structure %s\"", type->name);
730 case e_gras_datadesc_type_cat_union: {
731 gras_dd_cat_union_t union_data;
732 gras_dd_cat_field_t field=NULL;
735 union_data = type->category.union_data;
737 xbt_assert1(union_data.closed,
738 "Please call gras_datadesc_declare_union_close on %s before sending it",
740 /* retrieve the field number */
741 printf(" field_num = union_data.selector(state, data);\n");
743 printf(" xbt_assert0(field_num > 0,\n");
744 printf(" \"union field selector of %s gave a negative value\");\n",type->name);
746 printf(" xbt_assert3(field_num < xbt_dynar_length(union_data.fields),\n");
747 printf(" \"union field selector of %s returned %%d but there is only %lu fields\",field_num);\n",
748 type->name, xbt_dynar_length(union_data.fields));
750 /* Send the field number */
751 printf("TRY(gras_dd_send_int(sock, field_num));\n");
753 /* Send the content */
754 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
755 sub_type = field->type;
758 field->pre(state,data);
760 TRY(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, data, detect_cycle || sub_type->cycle));
763 field->post(state,data);
768 case e_gras_datadesc_type_cat_ref: {
769 gras_dd_cat_ref_t ref_data;
771 void **ref=(void**)data;
774 ref_data = type->category.ref_data;
776 /* Detect the referenced type and send it to peer if needed */
777 sub_type = ref_data.type;
778 if (sub_type == NULL) {
779 sub_type = (*ref_data.selector)(state,data);
780 TRY(gras_dd_send_int(sock, sub_type->code));
783 /* Send the actual value of the pointer for cycle handling */
785 pointer_type = gras_datadesc_by_name("data pointer");
786 xbt_assert(pointer_type);
789 TRY(gras_trp_chunk_send(sock, (char*)data,
790 pointer_type->size[GRAS_THISARCH]));
792 /* Send the pointed data only if not already sent */
793 if (*(void**)data == NULL) {
794 VERB0("Not sending NULL referenced data");
797 errcode = detect_cycle
798 ? xbt_dict_get_ext(refs,(char*)ref, sizeof(void*), &dummy)
800 if (errcode == mismatch_error) {
801 VERB1("Sending data referenced at %p", (void*)*ref);
803 xbt_dict_set_ext(refs, (char*)ref, sizeof(void*), ref, NULL);
804 TRY(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, *ref, detect_cycle || sub_type->cycle));
806 } else if (errcode == no_error) {
807 VERB1("Not sending data referenced at %p (already done)", (void*)*ref);
815 case e_gras_datadesc_type_cat_array: {
816 gras_dd_cat_array_t array_data;
821 array_data = type->category.array_data;
823 /* determine and send the element count */
824 count = array_data.fixed_size;
826 count = array_data.dynamic_size(state,data);
827 xbt_assert1(count >=0,
828 "Invalid (negative) array size for type %s",type->name);
829 TRY(gras_dd_send_int(sock, count));
832 /* send the content */
833 sub_type = array_data.type;
834 elm_size = sub_type->aligned_size[GRAS_THISARCH];
835 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
836 VERB1("Array of %ld scalars, send it in one shot",count);
837 TRY(gras_trp_chunk_send(sock, data,
838 sub_type->aligned_size[GRAS_THISARCH] * count));
839 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
840 sub_type->category.array_data.fixed_size > 0 &&
841 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
843 VERB1("Array of %ld fixed array of scalars, send it in one shot",count);
844 TRY(gras_trp_chunk_send(sock, data,
845 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
846 * count * sub_type->category.array_data.fixed_size));
849 for (cpt=0; cpt<count; cpt++) {
850 TRY(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, ptr, detect_cycle || sub_type->cycle));
858 xbt_assert0(0, "Invalid type");
865 * gras_datadesc_gen_send:
867 * Copy the data pointed by src and described by type to the socket
870 xbt_error_t gras_datadesc_gen_send(gras_socket_t sock,
871 gras_datadesc_type_t type,
876 xbt_dict_t refs; /* all references already sent */
878 refs = xbt_dict_new();
879 state = gras_cbps_new();
881 printf("xbt_error_t gras_%s_send(gras_socket_t sock,void *dst){\n",
883 errcode = gras_datadesc_gen_send_rec(sock,state,refs,type,(char*)src, type->cycle);
886 xbt_dict_free(&refs);
887 gras_cbps_free(&state);
893 * gras_datadesc_gen_recv_rec:
895 * Do the data reception job recursively.
897 * subsize used only to deal with vicious case of reference to dynamic array.
898 * This size is needed at the reference reception level (to allocate enough
899 * space) and at the array reception level (to fill enough room).
901 * Having this size passed as an argument of the recursive function is a crude
902 * hack, but I was told that working code is sometimes better than neat one ;)
905 gras_datadesc_gen_recv_rec(gras_socket_t sock,
908 gras_datadesc_type_t type,
918 gras_datadesc_type_t sub_type;
920 VERB2("Recv a %s @%p", type->name, (void*)l_data);
923 switch (type->category_code) {
924 case e_gras_datadesc_type_cat_scalar:
925 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
926 TRY(gras_trp_chunk_recv(sock, (char*)l_data, type->size[r_arch]));
927 if (r_arch != GRAS_THISARCH)
928 TRY(gras_dd_convert_elm(type,1,r_arch, l_data,l_data));
930 void *ptr = xbt_malloc(type->size[r_arch]);
932 TRY(gras_trp_chunk_recv(sock, (char*)ptr, type->size[r_arch]));
933 if (r_arch != GRAS_THISARCH)
934 TRY(gras_dd_convert_elm(type,1,r_arch, ptr,l_data));
939 case e_gras_datadesc_type_cat_struct: {
940 gras_dd_cat_struct_t struct_data;
941 gras_dd_cat_field_t field;
943 struct_data = type->category.struct_data;
945 xbt_assert1(struct_data.closed,
946 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
948 VERB1(">> Receive all fields of the structure %s",type->name);
949 xbt_dynar_foreach(struct_data.fields, cpt, field) {
950 char *field_data = l_data + field->offset[GRAS_THISARCH];
952 sub_type = field->type;
954 TRY(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
957 detect_cycle || sub_type->cycle));
959 VERB1("<< Received all fields of the structure %s", type->name);
964 case e_gras_datadesc_type_cat_union: {
965 gras_dd_cat_union_t union_data;
966 gras_dd_cat_field_t field=NULL;
969 union_data = type->category.union_data;
971 xbt_assert1(union_data.closed,
972 "Please call gras_datadesc_declare_union_close on %s before receiving it",
974 /* retrieve the field number */
975 TRY(gras_dd_recv_int(sock, r_arch, &field_num));
977 RAISE1(mismatch_error,
978 "Received union field for %s is negative", type->name);
979 if (field_num < xbt_dynar_length(union_data.fields))
980 RAISE3(mismatch_error,
981 "Received union field for %s is %d but there is only %lu fields",
982 type->name, field_num, xbt_dynar_length(union_data.fields));
984 /* Recv the content */
985 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
986 sub_type = field->type;
988 TRY(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
991 detect_cycle || sub_type->cycle));
995 case e_gras_datadesc_type_cat_ref: {
998 gras_dd_cat_ref_t ref_data;
1000 ref_data = type->category.ref_data;
1002 /* Get the referenced type locally or from peer */
1003 sub_type = ref_data.type;
1004 if (sub_type == NULL) {
1006 TRY(gras_dd_recv_int(sock, r_arch, &ref_code));
1007 TRY(gras_datadesc_by_id(ref_code, &sub_type));
1010 /* Get the actual value of the pointer for cycle handling */
1011 if (!pointer_type) {
1012 pointer_type = gras_datadesc_by_name("data pointer");
1013 xbt_assert(pointer_type);
1016 r_ref = xbt_malloc(pointer_type->size[r_arch]);
1018 TRY(gras_trp_chunk_recv(sock, (char*)r_ref,
1019 pointer_type->size[r_arch]));
1021 /* Receive the pointed data only if not already sent */
1022 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
1023 VERB1("Not receiving data remotely referenced @%p since it's NULL",
1025 *(void**)l_data = NULL;
1030 errcode = detect_cycle
1031 ? xbt_dict_get_ext(refs,
1032 (char*)r_ref, pointer_type->size[r_arch],
1036 if (errcode == mismatch_error) {
1037 int subsubcount = 0;
1038 void *l_referenced=NULL;
1040 VERB2("Receiving a ref to '%s', remotely @%p",
1041 sub_type->name, *(void**)r_ref);
1042 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
1043 /* Damn. Reference to a dynamic array. Allocating the size for it
1044 is more complicated */
1045 gras_dd_cat_array_t array_data = sub_type->category.array_data;
1046 gras_datadesc_type_t subsub_type;
1048 subsubcount = array_data.fixed_size;
1049 if (subsubcount == 0)
1050 TRY(gras_dd_recv_int(sock, r_arch, &subsubcount));
1052 subsub_type = array_data.type;
1055 TRY(gras_dd_alloc_ref(refs,
1056 subsub_type->size[GRAS_THISARCH] * subsubcount,
1057 r_ref,pointer_type->size[r_arch],
1058 (char**)&l_referenced,
1061 TRY(gras_dd_alloc_ref(refs,sub_type->size[GRAS_THISARCH],
1062 r_ref,pointer_type->size[r_arch],
1063 (char**)&l_referenced,
1067 TRY(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
1068 r_arch,r_ref,pointer_type->size[r_arch],
1069 (char*)l_referenced, subsubcount,
1070 detect_cycle || sub_type->cycle));
1071 *(void**)l_data=l_referenced;
1072 VERB3("'%s' remotely referenced at %p locally at %p",
1073 sub_type->name, *(void**)r_ref, l_referenced);
1075 } else if (errcode == no_error) {
1076 VERB2("NOT receiving data remotely referenced @%p (already done, @%p here)",
1077 *(void**)r_ref, *(void**)l_ref);
1079 *(void**)l_data=*l_ref;
1088 case e_gras_datadesc_type_cat_array: {
1089 gras_dd_cat_array_t array_data;
1094 array_data = type->category.array_data;
1095 /* determine element count locally, or from caller, or from peer */
1096 count = array_data.fixed_size;
1100 TRY(gras_dd_recv_int(sock, r_arch, &count));
1102 RAISE1(mismatch_error,
1103 "Invalid (=0) array size for type %s",type->name);
1105 /* receive the content */
1106 sub_type = array_data.type;
1107 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
1108 VERB1("Array of %d scalars, get it in one shoot", count);
1109 if (sub_type->aligned_size[GRAS_THISARCH] >=
1110 sub_type->aligned_size[r_arch]) {
1111 TRY(gras_trp_chunk_recv(sock, (char*)l_data,
1112 sub_type->aligned_size[r_arch] * count));
1113 if (r_arch != GRAS_THISARCH)
1114 TRY(gras_dd_convert_elm(sub_type,count,r_arch, l_data,l_data));
1116 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
1118 TRY(gras_trp_chunk_recv(sock, (char*)ptr,
1119 sub_type->size[r_arch] * count));
1120 if (r_arch != GRAS_THISARCH)
1121 TRY(gras_dd_convert_elm(sub_type,count,r_arch, ptr,l_data));
1124 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
1125 sub_type->category.array_data.fixed_size > 0 &&
1126 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
1127 gras_datadesc_type_t subsub_type;
1128 array_data = sub_type->category.array_data;
1129 subsub_type = array_data.type;
1131 VERB1("Array of %d fixed array of scalars, get it in one shot",count);
1132 if (subsub_type->aligned_size[GRAS_THISARCH] >=
1133 subsub_type->aligned_size[r_arch]) {
1134 TRY(gras_trp_chunk_recv(sock, (char*)l_data,
1135 subsub_type->aligned_size[r_arch] * count *
1136 array_data.fixed_size));
1137 if (r_arch != GRAS_THISARCH)
1138 TRY(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, l_data,l_data));
1140 ptr = xbt_malloc(subsub_type->aligned_size[r_arch] * count*array_data.fixed_size);
1142 TRY(gras_trp_chunk_recv(sock, (char*)ptr,
1143 subsub_type->size[r_arch] * count*array_data.fixed_size));
1144 if (r_arch != GRAS_THISARCH)
1145 TRY(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, ptr,l_data));
1151 /* not scalar content, get it recursively (may contain pointers) */
1152 elm_size = sub_type->aligned_size[GRAS_THISARCH];
1153 VERB2("Receive a %d-long array of %s",count, sub_type->name);
1156 for (cpt=0; cpt<count; cpt++) {
1157 TRY(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
1158 r_arch, NULL, 0, ptr,-1,
1159 detect_cycle || sub_type->cycle));
1167 xbt_assert0(0, "Invalid type");
1171 type->recv(state,l_data);
1177 * gras_datadesc_gen_recv:
1179 * Get an instance of the datatype described by @type from the @socket,
1180 * and store a pointer to it in @dst
1184 gras_datadesc_gen_recv(gras_socket_t sock,
1185 gras_datadesc_type_t type,
1189 xbt_error_t errcode;
1190 gras_cbps_t state; /* callback persistent state */
1191 xbt_dict_t refs; /* all references already sent */
1193 refs = xbt_dict_new();
1194 state = gras_cbps_new();
1196 printf("xbt_error_t gras_%s_recv(gras_socket_t sock,void *dst){\n",
1199 errcode = gras_datadesc_gen_recv_rec(sock, state, refs, type,
1205 xbt_dict_free(&refs);
1206 gras_cbps_free(&state);