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 xbt_assert0(type,"called with NULL type descriptor");
346 errcode = gras_datadesc_send_rec(sock,state,refs,type,(char*)src, type->cycle);
348 xbt_dict_free(&refs);
349 gras_cbps_free(&state);
355 * gras_datadesc_recv_rec:
357 * Do the data reception job recursively.
359 * subsize used only to deal with vicious case of reference to dynamic array.
360 * This size is needed at the reference reception level (to allocate enough
361 * space) and at the array reception level (to fill enough room).
363 * Having this size passed as an argument of the recursive function is a crude
364 * hack, but I was told that working code is sometimes better than neat one ;)
367 gras_datadesc_recv_rec(gras_socket_t sock,
370 gras_datadesc_type_t type,
380 gras_datadesc_type_t sub_type;
382 VERB2("Recv a %s @%p", type->name, (void*)l_data);
385 switch (type->category_code) {
386 case e_gras_datadesc_type_cat_scalar:
387 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
388 TRY(gras_trp_chunk_recv(sock, (char*)l_data, type->size[r_arch]));
389 if (r_arch != GRAS_THISARCH)
390 TRY(gras_dd_convert_elm(type,1,r_arch, l_data,l_data));
392 void *ptr = xbt_malloc(type->size[r_arch]);
394 TRY(gras_trp_chunk_recv(sock, (char*)ptr, type->size[r_arch]));
395 if (r_arch != GRAS_THISARCH)
396 TRY(gras_dd_convert_elm(type,1,r_arch, ptr,l_data));
401 case e_gras_datadesc_type_cat_struct: {
402 gras_dd_cat_struct_t struct_data;
403 gras_dd_cat_field_t field;
405 struct_data = type->category.struct_data;
407 xbt_assert1(struct_data.closed,
408 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
410 VERB1(">> Receive all fields of the structure %s",type->name);
411 xbt_dynar_foreach(struct_data.fields, cpt, field) {
412 char *field_data = l_data + field->offset[GRAS_THISARCH];
414 sub_type = field->type;
416 TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
419 detect_cycle || sub_type->cycle));
421 VERB1("<< Received all fields of the structure %s", type->name);
426 case e_gras_datadesc_type_cat_union: {
427 gras_dd_cat_union_t union_data;
428 gras_dd_cat_field_t field=NULL;
431 union_data = type->category.union_data;
433 xbt_assert1(union_data.closed,
434 "Please call gras_datadesc_declare_union_close on %s before receiving it",
436 /* retrieve the field number */
437 TRY(gras_dd_recv_int(sock, r_arch, &field_num));
439 RAISE1(mismatch_error,
440 "Received union field for %s is negative", type->name);
441 if (field_num < xbt_dynar_length(union_data.fields))
442 RAISE3(mismatch_error,
443 "Received union field for %s is %d but there is only %lu fields",
444 type->name, field_num, xbt_dynar_length(union_data.fields));
446 /* Recv the content */
447 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
448 sub_type = field->type;
450 TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
453 detect_cycle || sub_type->cycle));
457 case e_gras_datadesc_type_cat_ref: {
460 gras_dd_cat_ref_t ref_data;
462 ref_data = type->category.ref_data;
464 /* Get the referenced type locally or from peer */
465 sub_type = ref_data.type;
466 if (sub_type == NULL) {
468 TRY(gras_dd_recv_int(sock, r_arch, &ref_code));
469 TRY(gras_datadesc_by_id(ref_code, &sub_type));
472 /* Get the actual value of the pointer for cycle handling */
474 pointer_type = gras_datadesc_by_name("data pointer");
475 xbt_assert(pointer_type);
478 r_ref = xbt_malloc(pointer_type->size[r_arch]);
480 TRY(gras_trp_chunk_recv(sock, (char*)r_ref,
481 pointer_type->size[r_arch]));
483 /* Receive the pointed data only if not already sent */
484 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
485 VERB1("Not receiving data remotely referenced @%p since it's NULL",
487 *(void**)l_data = NULL;
492 errcode = detect_cycle
493 ? xbt_dict_get_ext(refs,
494 (char*)r_ref, pointer_type->size[r_arch],
498 if (errcode == mismatch_error) {
500 void *l_referenced=NULL;
502 VERB2("Receiving a ref to '%s', remotely @%p",
503 sub_type->name, *(void**)r_ref);
504 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
505 /* Damn. Reference to a dynamic array. Allocating the size for it
506 is more complicated */
507 gras_dd_cat_array_t array_data = sub_type->category.array_data;
508 gras_datadesc_type_t subsub_type;
510 subsubcount = array_data.fixed_size;
511 if (subsubcount == 0)
512 TRY(gras_dd_recv_int(sock, r_arch, &subsubcount));
514 subsub_type = array_data.type;
517 TRY(gras_dd_alloc_ref(refs,
518 subsub_type->size[GRAS_THISARCH] * subsubcount,
519 r_ref,pointer_type->size[r_arch],
520 (char**)&l_referenced,
523 TRY(gras_dd_alloc_ref(refs,sub_type->size[GRAS_THISARCH],
524 r_ref,pointer_type->size[r_arch],
525 (char**)&l_referenced,
529 TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
530 r_arch,r_ref,pointer_type->size[r_arch],
531 (char*)l_referenced, subsubcount,
532 detect_cycle || sub_type->cycle));
533 *(void**)l_data=l_referenced;
534 VERB3("'%s' remotely referenced at %p locally at %p",
535 sub_type->name, *(void**)r_ref, l_referenced);
537 } else if (errcode == no_error) {
538 VERB2("NOT receiving data remotely referenced @%p (already done, @%p here)",
539 *(void**)r_ref, *(void**)l_ref);
541 *(void**)l_data=*l_ref;
550 case e_gras_datadesc_type_cat_array: {
551 gras_dd_cat_array_t array_data;
556 array_data = type->category.array_data;
557 /* determine element count locally, or from caller, or from peer */
558 count = array_data.fixed_size;
562 TRY(gras_dd_recv_int(sock, r_arch, &count));
564 RAISE1(mismatch_error,
565 "Invalid (=0) array size for type %s",type->name);
567 /* receive the content */
568 sub_type = array_data.type;
569 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
570 VERB1("Array of %d scalars, get it in one shoot", count);
571 if (sub_type->aligned_size[GRAS_THISARCH] >=
572 sub_type->aligned_size[r_arch]) {
573 TRY(gras_trp_chunk_recv(sock, (char*)l_data,
574 sub_type->aligned_size[r_arch] * count));
575 if (r_arch != GRAS_THISARCH)
576 TRY(gras_dd_convert_elm(sub_type,count,r_arch, l_data,l_data));
578 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
580 TRY(gras_trp_chunk_recv(sock, (char*)ptr,
581 sub_type->size[r_arch] * count));
582 if (r_arch != GRAS_THISARCH)
583 TRY(gras_dd_convert_elm(sub_type,count,r_arch, ptr,l_data));
586 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
587 sub_type->category.array_data.fixed_size > 0 &&
588 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
589 gras_datadesc_type_t subsub_type;
590 array_data = sub_type->category.array_data;
591 subsub_type = array_data.type;
593 VERB1("Array of %d fixed array of scalars, get it in one shot",count);
594 if (subsub_type->aligned_size[GRAS_THISARCH] >=
595 subsub_type->aligned_size[r_arch]) {
596 TRY(gras_trp_chunk_recv(sock, (char*)l_data,
597 subsub_type->aligned_size[r_arch] * count *
598 array_data.fixed_size));
599 if (r_arch != GRAS_THISARCH)
600 TRY(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, l_data,l_data));
602 ptr = xbt_malloc(subsub_type->aligned_size[r_arch] * count*array_data.fixed_size);
604 TRY(gras_trp_chunk_recv(sock, (char*)ptr,
605 subsub_type->size[r_arch] * count*array_data.fixed_size));
606 if (r_arch != GRAS_THISARCH)
607 TRY(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, ptr,l_data));
613 /* not scalar content, get it recursively (may contain pointers) */
614 elm_size = sub_type->aligned_size[GRAS_THISARCH];
615 VERB2("Receive a %d-long array of %s",count, sub_type->name);
618 for (cpt=0; cpt<count; cpt++) {
619 TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
620 r_arch, NULL, 0, ptr,-1,
621 detect_cycle || sub_type->cycle));
629 xbt_assert0(0, "Invalid type");
633 type->recv(state,l_data);
639 * gras_datadesc_recv:
641 * Get an instance of the datatype described by @type from the @socket,
642 * and store a pointer to it in @dst
646 gras_datadesc_recv(gras_socket_t sock,
647 gras_datadesc_type_t type,
652 gras_cbps_t state; /* callback persistent state */
653 xbt_dict_t refs; /* all references already sent */
655 refs = xbt_dict_new();
656 state = gras_cbps_new();
658 xbt_assert0(type,"called with NULL type descriptor");
659 errcode = gras_datadesc_recv_rec(sock, state, refs, type,
664 xbt_dict_free(&refs);
665 gras_cbps_free(&state);
672 *** IDL compiling functions
675 #define gras_datadesc_send_rec foo /* Just to make sure the copypast was ok */
676 #define gras_datadesc_send foo /* Just to make sure the copypast was ok */
677 #define gras_datadesc_recv_rec foo /* Just to make sure the copypast was ok */
678 #define gras_datadesc_recv foo /* Just to make sure the copypast was ok */
681 gras_datadesc_gen_send_rec(gras_socket_t sock,
684 gras_datadesc_type_t type,
690 gras_datadesc_type_t sub_type; /* type on which we recurse */
692 printf(" VERB2(\"Send a %s (%s)\");\n",
693 type->name, gras_datadesc_cat_names[type->category_code]);
695 xbt_assert0(!type->send, "Callbacks not implemented in IDL compiler");
697 switch (type->category_code) {
698 case e_gras_datadesc_type_cat_scalar:
699 printf(" TRY(gras_trp_chunk_send(sock, data, %lu));\n",type->size[GRAS_THISARCH]);
702 case e_gras_datadesc_type_cat_struct: {
703 gras_dd_cat_struct_t struct_data;
704 gras_dd_cat_field_t field;
707 struct_data = type->category.struct_data;
708 xbt_assert1(struct_data.closed,
709 "Please call gras_datadesc_declare_struct_close on %s before sending it",
711 printf(" VERB1(\">> Send all fields of the structure %s\");\n",type->name);
712 xbt_dynar_foreach(struct_data.fields, cpt, field) {
714 field_data += field->offset[GRAS_THISARCH];
716 sub_type = field->type;
718 xbt_assert0(!field->pre, "Callbacks not implemented in IDL compiler");
720 printf(" VERB1(\"Send field %s\");\n",field->name);
721 printf(" data += %lu;\n",field->offset[GRAS_THISARCH]);
722 TRY(gras_datadesc_gen_send_rec(sock,state,refs,sub_type, field_data, detect_cycle || sub_type->cycle));
723 printf(" data -= %lu;\n",field->offset[GRAS_THISARCH]);
725 xbt_assert0(!field->post, "Callbacks not implemented in IDL compiler");
727 printf(" VERB1(\"<< Sent all fields of the structure %s\"", type->name);
732 case e_gras_datadesc_type_cat_union: {
733 gras_dd_cat_union_t union_data;
734 gras_dd_cat_field_t field=NULL;
737 union_data = type->category.union_data;
739 xbt_assert1(union_data.closed,
740 "Please call gras_datadesc_declare_union_close on %s before sending it",
742 /* retrieve the field number */
743 printf(" field_num = union_data.selector(state, data);\n");
745 printf(" xbt_assert0(field_num > 0,\n");
746 printf(" \"union field selector of %s gave a negative value\");\n",type->name);
748 printf(" xbt_assert3(field_num < xbt_dynar_length(union_data.fields),\n");
749 printf(" \"union field selector of %s returned %%d but there is only %lu fields\",field_num);\n",
750 type->name, xbt_dynar_length(union_data.fields));
752 /* Send the field number */
753 printf("TRY(gras_dd_send_int(sock, field_num));\n");
755 /* Send the content */
756 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
757 sub_type = field->type;
760 field->pre(state,data);
762 TRY(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, data, detect_cycle || sub_type->cycle));
765 field->post(state,data);
770 case e_gras_datadesc_type_cat_ref: {
771 gras_dd_cat_ref_t ref_data;
773 void **ref=(void**)data;
776 ref_data = type->category.ref_data;
778 /* Detect the referenced type and send it to peer if needed */
779 sub_type = ref_data.type;
780 if (sub_type == NULL) {
781 sub_type = (*ref_data.selector)(state,data);
782 TRY(gras_dd_send_int(sock, sub_type->code));
785 /* Send the actual value of the pointer for cycle handling */
787 pointer_type = gras_datadesc_by_name("data pointer");
788 xbt_assert(pointer_type);
791 TRY(gras_trp_chunk_send(sock, (char*)data,
792 pointer_type->size[GRAS_THISARCH]));
794 /* Send the pointed data only if not already sent */
795 if (*(void**)data == NULL) {
796 VERB0("Not sending NULL referenced data");
799 errcode = detect_cycle
800 ? xbt_dict_get_ext(refs,(char*)ref, sizeof(void*), &dummy)
802 if (errcode == mismatch_error) {
803 VERB1("Sending data referenced at %p", (void*)*ref);
805 xbt_dict_set_ext(refs, (char*)ref, sizeof(void*), ref, NULL);
806 TRY(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, *ref, detect_cycle || sub_type->cycle));
808 } else if (errcode == no_error) {
809 VERB1("Not sending data referenced at %p (already done)", (void*)*ref);
817 case e_gras_datadesc_type_cat_array: {
818 gras_dd_cat_array_t array_data;
823 array_data = type->category.array_data;
825 /* determine and send the element count */
826 count = array_data.fixed_size;
828 count = array_data.dynamic_size(state,data);
829 xbt_assert1(count >=0,
830 "Invalid (negative) array size for type %s",type->name);
831 TRY(gras_dd_send_int(sock, count));
834 /* send the content */
835 sub_type = array_data.type;
836 elm_size = sub_type->aligned_size[GRAS_THISARCH];
837 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
838 VERB1("Array of %ld scalars, send it in one shot",count);
839 TRY(gras_trp_chunk_send(sock, data,
840 sub_type->aligned_size[GRAS_THISARCH] * count));
841 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
842 sub_type->category.array_data.fixed_size > 0 &&
843 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
845 VERB1("Array of %ld fixed array of scalars, send it in one shot",count);
846 TRY(gras_trp_chunk_send(sock, data,
847 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
848 * count * sub_type->category.array_data.fixed_size));
851 for (cpt=0; cpt<count; cpt++) {
852 TRY(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, ptr, detect_cycle || sub_type->cycle));
860 xbt_assert0(0, "Invalid type");
867 * gras_datadesc_gen_send:
869 * Copy the data pointed by src and described by type to the socket
872 xbt_error_t gras_datadesc_gen_send(gras_socket_t sock,
873 gras_datadesc_type_t type,
878 xbt_dict_t refs; /* all references already sent */
880 refs = xbt_dict_new();
881 state = gras_cbps_new();
883 printf("xbt_error_t gras_%s_send(gras_socket_t sock,void *dst){\n",
885 errcode = gras_datadesc_gen_send_rec(sock,state,refs,type,(char*)src, type->cycle);
888 xbt_dict_free(&refs);
889 gras_cbps_free(&state);
895 * gras_datadesc_gen_recv_rec:
897 * Do the data reception job recursively.
899 * subsize used only to deal with vicious case of reference to dynamic array.
900 * This size is needed at the reference reception level (to allocate enough
901 * space) and at the array reception level (to fill enough room).
903 * Having this size passed as an argument of the recursive function is a crude
904 * hack, but I was told that working code is sometimes better than neat one ;)
907 gras_datadesc_gen_recv_rec(gras_socket_t sock,
910 gras_datadesc_type_t type,
920 gras_datadesc_type_t sub_type;
922 VERB2("Recv a %s @%p", type->name, (void*)l_data);
925 switch (type->category_code) {
926 case e_gras_datadesc_type_cat_scalar:
927 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
928 TRY(gras_trp_chunk_recv(sock, (char*)l_data, type->size[r_arch]));
929 if (r_arch != GRAS_THISARCH)
930 TRY(gras_dd_convert_elm(type,1,r_arch, l_data,l_data));
932 void *ptr = xbt_malloc(type->size[r_arch]);
934 TRY(gras_trp_chunk_recv(sock, (char*)ptr, type->size[r_arch]));
935 if (r_arch != GRAS_THISARCH)
936 TRY(gras_dd_convert_elm(type,1,r_arch, ptr,l_data));
941 case e_gras_datadesc_type_cat_struct: {
942 gras_dd_cat_struct_t struct_data;
943 gras_dd_cat_field_t field;
945 struct_data = type->category.struct_data;
947 xbt_assert1(struct_data.closed,
948 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
950 VERB1(">> Receive all fields of the structure %s",type->name);
951 xbt_dynar_foreach(struct_data.fields, cpt, field) {
952 char *field_data = l_data + field->offset[GRAS_THISARCH];
954 sub_type = field->type;
956 TRY(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
959 detect_cycle || sub_type->cycle));
961 VERB1("<< Received all fields of the structure %s", type->name);
966 case e_gras_datadesc_type_cat_union: {
967 gras_dd_cat_union_t union_data;
968 gras_dd_cat_field_t field=NULL;
971 union_data = type->category.union_data;
973 xbt_assert1(union_data.closed,
974 "Please call gras_datadesc_declare_union_close on %s before receiving it",
976 /* retrieve the field number */
977 TRY(gras_dd_recv_int(sock, r_arch, &field_num));
979 RAISE1(mismatch_error,
980 "Received union field for %s is negative", type->name);
981 if (field_num < xbt_dynar_length(union_data.fields))
982 RAISE3(mismatch_error,
983 "Received union field for %s is %d but there is only %lu fields",
984 type->name, field_num, xbt_dynar_length(union_data.fields));
986 /* Recv the content */
987 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
988 sub_type = field->type;
990 TRY(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
993 detect_cycle || sub_type->cycle));
997 case e_gras_datadesc_type_cat_ref: {
1000 gras_dd_cat_ref_t ref_data;
1002 ref_data = type->category.ref_data;
1004 /* Get the referenced type locally or from peer */
1005 sub_type = ref_data.type;
1006 if (sub_type == NULL) {
1008 TRY(gras_dd_recv_int(sock, r_arch, &ref_code));
1009 TRY(gras_datadesc_by_id(ref_code, &sub_type));
1012 /* Get the actual value of the pointer for cycle handling */
1013 if (!pointer_type) {
1014 pointer_type = gras_datadesc_by_name("data pointer");
1015 xbt_assert(pointer_type);
1018 r_ref = xbt_malloc(pointer_type->size[r_arch]);
1020 TRY(gras_trp_chunk_recv(sock, (char*)r_ref,
1021 pointer_type->size[r_arch]));
1023 /* Receive the pointed data only if not already sent */
1024 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
1025 VERB1("Not receiving data remotely referenced @%p since it's NULL",
1027 *(void**)l_data = NULL;
1032 errcode = detect_cycle
1033 ? xbt_dict_get_ext(refs,
1034 (char*)r_ref, pointer_type->size[r_arch],
1038 if (errcode == mismatch_error) {
1039 int subsubcount = 0;
1040 void *l_referenced=NULL;
1042 VERB2("Receiving a ref to '%s', remotely @%p",
1043 sub_type->name, *(void**)r_ref);
1044 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
1045 /* Damn. Reference to a dynamic array. Allocating the size for it
1046 is more complicated */
1047 gras_dd_cat_array_t array_data = sub_type->category.array_data;
1048 gras_datadesc_type_t subsub_type;
1050 subsubcount = array_data.fixed_size;
1051 if (subsubcount == 0)
1052 TRY(gras_dd_recv_int(sock, r_arch, &subsubcount));
1054 subsub_type = array_data.type;
1057 TRY(gras_dd_alloc_ref(refs,
1058 subsub_type->size[GRAS_THISARCH] * subsubcount,
1059 r_ref,pointer_type->size[r_arch],
1060 (char**)&l_referenced,
1063 TRY(gras_dd_alloc_ref(refs,sub_type->size[GRAS_THISARCH],
1064 r_ref,pointer_type->size[r_arch],
1065 (char**)&l_referenced,
1069 TRY(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
1070 r_arch,r_ref,pointer_type->size[r_arch],
1071 (char*)l_referenced, subsubcount,
1072 detect_cycle || sub_type->cycle));
1073 *(void**)l_data=l_referenced;
1074 VERB3("'%s' remotely referenced at %p locally at %p",
1075 sub_type->name, *(void**)r_ref, l_referenced);
1077 } else if (errcode == no_error) {
1078 VERB2("NOT receiving data remotely referenced @%p (already done, @%p here)",
1079 *(void**)r_ref, *(void**)l_ref);
1081 *(void**)l_data=*l_ref;
1090 case e_gras_datadesc_type_cat_array: {
1091 gras_dd_cat_array_t array_data;
1096 array_data = type->category.array_data;
1097 /* determine element count locally, or from caller, or from peer */
1098 count = array_data.fixed_size;
1102 TRY(gras_dd_recv_int(sock, r_arch, &count));
1104 RAISE1(mismatch_error,
1105 "Invalid (=0) array size for type %s",type->name);
1107 /* receive the content */
1108 sub_type = array_data.type;
1109 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
1110 VERB1("Array of %d scalars, get it in one shoot", count);
1111 if (sub_type->aligned_size[GRAS_THISARCH] >=
1112 sub_type->aligned_size[r_arch]) {
1113 TRY(gras_trp_chunk_recv(sock, (char*)l_data,
1114 sub_type->aligned_size[r_arch] * count));
1115 if (r_arch != GRAS_THISARCH)
1116 TRY(gras_dd_convert_elm(sub_type,count,r_arch, l_data,l_data));
1118 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
1120 TRY(gras_trp_chunk_recv(sock, (char*)ptr,
1121 sub_type->size[r_arch] * count));
1122 if (r_arch != GRAS_THISARCH)
1123 TRY(gras_dd_convert_elm(sub_type,count,r_arch, ptr,l_data));
1126 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
1127 sub_type->category.array_data.fixed_size > 0 &&
1128 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
1129 gras_datadesc_type_t subsub_type;
1130 array_data = sub_type->category.array_data;
1131 subsub_type = array_data.type;
1133 VERB1("Array of %d fixed array of scalars, get it in one shot",count);
1134 if (subsub_type->aligned_size[GRAS_THISARCH] >=
1135 subsub_type->aligned_size[r_arch]) {
1136 TRY(gras_trp_chunk_recv(sock, (char*)l_data,
1137 subsub_type->aligned_size[r_arch] * count *
1138 array_data.fixed_size));
1139 if (r_arch != GRAS_THISARCH)
1140 TRY(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, l_data,l_data));
1142 ptr = xbt_malloc(subsub_type->aligned_size[r_arch] * count*array_data.fixed_size);
1144 TRY(gras_trp_chunk_recv(sock, (char*)ptr,
1145 subsub_type->size[r_arch] * count*array_data.fixed_size));
1146 if (r_arch != GRAS_THISARCH)
1147 TRY(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, ptr,l_data));
1153 /* not scalar content, get it recursively (may contain pointers) */
1154 elm_size = sub_type->aligned_size[GRAS_THISARCH];
1155 VERB2("Receive a %d-long array of %s",count, sub_type->name);
1158 for (cpt=0; cpt<count; cpt++) {
1159 TRY(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
1160 r_arch, NULL, 0, ptr,-1,
1161 detect_cycle || sub_type->cycle));
1169 xbt_assert0(0, "Invalid type");
1173 type->recv(state,l_data);
1179 * gras_datadesc_gen_recv:
1181 * Get an instance of the datatype described by @type from the @socket,
1182 * and store a pointer to it in @dst
1186 gras_datadesc_gen_recv(gras_socket_t sock,
1187 gras_datadesc_type_t type,
1191 xbt_error_t errcode;
1192 gras_cbps_t state; /* callback persistent state */
1193 xbt_dict_t refs; /* all references already sent */
1195 refs = xbt_dict_new();
1196 state = gras_cbps_new();
1198 printf("xbt_error_t gras_%s_recv(gras_socket_t sock,void *dst){\n",
1201 errcode = gras_datadesc_gen_recv_rec(sock, state, refs, type,
1207 xbt_dict_free(&refs);
1208 gras_cbps_free(&state);