3 /* ddt_exchange - send/recv data described */
5 /* Copyright (c) 2003 Olivier Aumage. */
6 /* Copyright (c) 2003, 2004, 2005 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. */
13 #include "gras/DataDesc/datadesc_private.h"
14 #include "gras/Transport/transport_interface.h" /* gras_trp_chunk_send/recv */
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ddt_exchange,datadesc,
17 "Sending data over the network");
18 const char *gras_datadesc_cat_names[9] = {
20 "scalar", "struct", "union", "ref", "array", "ignored",
23 static gras_datadesc_type_t int_type = NULL;
24 static gras_datadesc_type_t pointer_type = NULL;
25 static _XBT_INLINE void gras_dd_send_int(gras_socket_t sock, int i);
26 static _XBT_INLINE void gras_dd_recv_int(gras_socket_t sock, int r_arch, int *i);
28 static _XBT_INLINE xbt_error_t
29 gras_dd_alloc_ref(xbt_dict_t refs, long int size,
30 char **r_ref, long int r_len,
31 char **l_ref, int detect_cycle);
33 static _XBT_INLINE int
34 gras_dd_is_r_null(char **r_ptr, long int length);
36 static _XBT_INLINE void
37 gras_dd_send_int(gras_socket_t sock,int i) {
40 int_type = gras_datadesc_by_name("int");
44 DEBUG1("send_int(%d)",i);
45 gras_trp_chunk_send(sock, (char*)&i, int_type->size[GRAS_THISARCH]);
48 static _XBT_INLINE void
49 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 gras_trp_chunk_recv(sock, (char*)i, int_type->size[r_arch]);
58 if (r_arch != GRAS_THISARCH)
59 gras_dd_convert_elm(int_type,1,r_arch, i,i);
61 void *ptr = xbt_malloc(int_type->size[r_arch]);
63 gras_trp_chunk_recv(sock, (char*)ptr, int_type->size[r_arch]);
64 if (r_arch != GRAS_THISARCH)
65 gras_dd_convert_elm(int_type,1,r_arch, ptr,i);
68 DEBUG1("recv_int(%d)",*i);
72 * Note: here we suppose that the remote NULL is a sequence
73 * of 'length' bytes set to 0.
74 * FIXME: Check in configure?
76 static _XBT_INLINE int
77 gras_dd_is_r_null(char **r_ptr, long int length) {
80 for (i=0; i<length; i++) {
81 if ( ((unsigned char*)r_ptr) [i]) {
89 static _XBT_INLINE xbt_error_t
90 gras_dd_alloc_ref(xbt_dict_t refs,
93 long int r_len, /* pointer_type->size[r_arch] */
98 xbt_assert1(size>0,"Cannot allocate %ld bytes!", size);
99 l_data = xbt_malloc((size_t)size);
102 DEBUG5("alloc_ref: l_data=%p, &l_data=%p; r_ref=%p; *r_ref=%p, r_len=%ld",
103 (void*)l_data,(void*)&l_data,
104 (void*)r_ref, (void*)(r_ref?*r_ref:NULL), r_len);
105 if (detect_cycle && r_ref && !gras_dd_is_r_null( r_ref, r_len)) {
106 void *ptr = xbt_malloc(sizeof(void *));
108 CRITICAL0("Check for cycles");
109 memcpy(ptr,l_ref, sizeof(void *));
111 DEBUG2("Insert l_ref=%p under r_ref=%p",*(void**)ptr, *(void**)r_ref);
114 xbt_dict_set_ext(refs,(const char *) r_ref, r_len, ptr, free);
122 * Copy the data pointed by src and described by type
123 * to a new location, and store a pointer to it in dst.
126 xbt_error_t gras_datadesc_cpy(gras_datadesc_type_t type,
133 *** Direct use functions
137 gras_datadesc_send_rec(gras_socket_t sock,
140 gras_datadesc_type_t type,
146 gras_datadesc_type_t sub_type; /* type on which we recurse */
148 VERB2("Send a %s (%s)",
149 type->name, gras_datadesc_cat_names[type->category_code]);
152 type->send(type,state,data);
155 switch (type->category_code) {
156 case e_gras_datadesc_type_cat_scalar:
157 gras_trp_chunk_send(sock, data, type->size[GRAS_THISARCH]);
160 case e_gras_datadesc_type_cat_struct: {
161 gras_dd_cat_struct_t struct_data;
162 gras_dd_cat_field_t field;
165 struct_data = type->category.struct_data;
166 xbt_assert1(struct_data.closed,
167 "Please call gras_datadesc_declare_struct_close on %s before sending it",
169 VERB1(">> Send all fields of the structure %s",type->name);
170 xbt_dynar_foreach(struct_data.fields, cpt, field) {
172 field_data += field->offset[GRAS_THISARCH];
174 sub_type = field->type;
177 field->send(type,state,field_data);
179 VERB1("Send field %s",field->name);
180 gras_datadesc_send_rec(sock,state,refs,sub_type, field_data,
181 detect_cycle || sub_type->cycle);
184 VERB1("<< Sent all fields of the structure %s", type->name);
189 case e_gras_datadesc_type_cat_union: {
190 gras_dd_cat_union_t union_data;
191 gras_dd_cat_field_t field=NULL;
194 union_data = type->category.union_data;
196 xbt_assert1(union_data.closed,
197 "Please call gras_datadesc_declare_union_close on %s before sending it",
199 /* retrieve the field number */
200 field_num = union_data.selector(type, state, data);
202 xbt_assert1(field_num > 0,
203 "union field selector of %s gave a negative value",
206 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
207 "union field selector of %s returned %d but there is only %lu fields",
208 type->name, field_num, xbt_dynar_length(union_data.fields));
210 /* Send the field number */
211 gras_dd_send_int(sock, field_num);
213 /* Send the content */
214 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
215 sub_type = field->type;
218 field->send(type,state,data);
220 gras_datadesc_send_rec(sock,state,refs, sub_type, data,
221 detect_cycle || sub_type->cycle);
226 case e_gras_datadesc_type_cat_ref: {
227 gras_dd_cat_ref_t ref_data;
228 void **ref=(void**)data;
229 int reference_is_to_send;
231 ref_data = type->category.ref_data;
233 /* Detect the referenced type and send it to peer if needed */
234 sub_type = ref_data.type;
235 if (sub_type == NULL) {
236 sub_type = (*ref_data.selector)(type,state,data);
237 gras_dd_send_int(sock, sub_type->code);
240 /* Send the actual value of the pointer for cycle handling */
242 pointer_type = gras_datadesc_by_name("data pointer");
243 xbt_assert(pointer_type);
246 gras_trp_chunk_send(sock, (char*)data,
247 pointer_type->size[GRAS_THISARCH]);
249 /* Send the pointed data only if not already sent */
250 if (*(void**)data == NULL) {
251 VERB0("Not sending NULL referenced data");
255 reference_is_to_send = 0;
258 /* return ignored. Just checking whether it's known or not */
259 xbt_dict_get_ext(refs,(char*)ref, sizeof(void*));
261 reference_is_to_send = 1;
263 if (e.category == mismatch_error) {
264 reference_is_to_send = 1;
271 if (reference_is_to_send) {
272 VERB1("Sending data referenced at %p", (void*)*ref);
274 xbt_dict_set_ext(refs, (char*)ref, sizeof(void*), ref, NULL);
275 gras_datadesc_send_rec(sock,state,refs, sub_type, *ref,
276 detect_cycle || sub_type->cycle);
279 VERB1("Not sending data referenced at %p (already done)", (void*)*ref);
285 case e_gras_datadesc_type_cat_array: {
286 gras_dd_cat_array_t array_data;
291 array_data = type->category.array_data;
293 /* determine and send the element count */
294 count = array_data.fixed_size;
296 count = array_data.dynamic_size(type,state,data);
297 xbt_assert1(count >=0,
298 "Invalid (negative) array size for type %s",type->name);
299 gras_dd_send_int(sock, count);
302 /* send the content */
303 sub_type = array_data.type;
304 elm_size = sub_type->aligned_size[GRAS_THISARCH];
305 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
306 VERB1("Array of %ld scalars, send it in one shot",count);
307 gras_trp_chunk_send(sock, data,
308 sub_type->aligned_size[GRAS_THISARCH] * count);
309 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
310 sub_type->category.array_data.fixed_size > 0 &&
311 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
313 VERB1("Array of %ld fixed array of scalars, send it in one shot",count);
314 gras_trp_chunk_send(sock, data,
315 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
316 * count * sub_type->category.array_data.fixed_size);
319 for (cpt=0; cpt<count; cpt++) {
320 gras_datadesc_send_rec(sock,state,refs, sub_type, ptr,
321 detect_cycle || sub_type->cycle);
329 xbt_assert0(0, "Invalid type");
334 * gras_datadesc_send:
336 * Copy the data pointed by src and described by type to the socket
339 void gras_datadesc_send(gras_socket_t sock,
340 gras_datadesc_type_t type,
345 xbt_dict_t refs; /* all references already sent */
347 xbt_assert0(type,"called with NULL type descriptor");
349 refs = xbt_dict_new();
350 state = gras_cbps_new();
353 gras_datadesc_send_rec(sock,state,refs,type,(char*)src, type->cycle);
355 xbt_dict_free(&refs);
356 gras_cbps_free(&state);
363 * gras_datadesc_recv_rec:
365 * Do the data reception job recursively.
367 * subsize used only to deal with vicious case of reference to dynamic array.
368 * This size is needed at the reference reception level (to allocate enough
369 * space) and at the array reception level (to fill enough room).
371 * Having this size passed as an argument of the recursive function is a crude
372 * hack, but I was told that working code is sometimes better than neat one ;)
375 gras_datadesc_recv_rec(gras_socket_t sock,
378 gras_datadesc_type_t type,
387 gras_datadesc_type_t sub_type;
390 VERB2("Recv a %s @%p", type->name, (void*)l_data);
393 switch (type->category_code) {
394 case e_gras_datadesc_type_cat_scalar:
395 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
396 gras_trp_chunk_recv(sock, (char*)l_data, type->size[r_arch]);
397 if (r_arch != GRAS_THISARCH)
398 gras_dd_convert_elm(type,1,r_arch, l_data,l_data);
400 void *ptr = xbt_malloc(type->size[r_arch]);
402 gras_trp_chunk_recv(sock, (char*)ptr, type->size[r_arch]);
403 if (r_arch != GRAS_THISARCH)
404 gras_dd_convert_elm(type,1,r_arch, ptr,l_data);
409 case e_gras_datadesc_type_cat_struct: {
410 gras_dd_cat_struct_t struct_data;
411 gras_dd_cat_field_t field;
413 struct_data = type->category.struct_data;
415 xbt_assert1(struct_data.closed,
416 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
418 VERB1(">> Receive all fields of the structure %s",type->name);
419 xbt_dynar_foreach(struct_data.fields, cpt, field) {
420 char *field_data = l_data + field->offset[GRAS_THISARCH];
422 sub_type = field->type;
424 gras_datadesc_recv_rec(sock,state,refs, sub_type,
427 detect_cycle || sub_type->cycle);
430 field->recv(type,state,(void*)l_data);
433 VERB1("<< Received all fields of the structure %s", type->name);
438 case e_gras_datadesc_type_cat_union: {
439 gras_dd_cat_union_t union_data;
440 gras_dd_cat_field_t field=NULL;
443 union_data = type->category.union_data;
445 xbt_assert1(union_data.closed,
446 "Please call gras_datadesc_declare_union_close on %s before receiving it",
448 /* retrieve the field number */
449 gras_dd_recv_int(sock, r_arch, &field_num);
451 THROW1(mismatch_error,0,
452 "Received union field for %s is negative", type->name);
453 if (field_num < xbt_dynar_length(union_data.fields))
454 THROW3(mismatch_error,0,
455 "Received union field for %s is said to be #%d but there is only %lu fields",
456 type->name, field_num, xbt_dynar_length(union_data.fields));
458 /* Recv the content */
459 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
460 sub_type = field->type;
462 gras_datadesc_recv_rec(sock,state,refs, sub_type,
465 detect_cycle || sub_type->cycle);
467 field->recv(type,state,l_data);
472 case e_gras_datadesc_type_cat_ref: {
475 gras_dd_cat_ref_t ref_data;
476 int reference_is_to_recv = 0;
478 ref_data = type->category.ref_data;
480 /* Get the referenced type locally or from peer */
481 sub_type = ref_data.type;
482 if (sub_type == NULL) {
484 gras_dd_recv_int(sock, r_arch, &ref_code);
485 sub_type = gras_datadesc_by_id(ref_code);
488 /* Get the actual value of the pointer for cycle handling */
490 pointer_type = gras_datadesc_by_name("data pointer");
491 xbt_assert(pointer_type);
494 r_ref = xbt_malloc(pointer_type->size[r_arch]);
496 gras_trp_chunk_recv(sock, (char*)r_ref,
497 pointer_type->size[r_arch]);
499 /* Receive the pointed data only if not already sent */
500 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
501 VERB1("Not receiving data remotely referenced @%p since it's NULL",
503 *(void**)l_data = NULL;
508 reference_is_to_recv = 0;
511 l_ref = xbt_dict_get_ext(refs, (char*)r_ref, pointer_type->size[r_arch]);
513 reference_is_to_recv = 1;
515 if (e.category == mismatch_error) {
516 reference_is_to_recv = 1;
522 if (reference_is_to_recv) {
524 void *l_referenced=NULL;
526 VERB2("Receiving a ref to '%s', remotely @%p",
527 sub_type->name, *(void**)r_ref);
528 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
529 /* Damn. Reference to a dynamic array. Allocating the space for it
530 is more complicated */
531 gras_dd_cat_array_t array_data = sub_type->category.array_data;
532 gras_datadesc_type_t subsub_type;
534 subsubcount = array_data.fixed_size;
535 if (subsubcount == 0)
536 gras_dd_recv_int(sock, r_arch, &subsubcount);
538 subsub_type = array_data.type;
541 gras_dd_alloc_ref(refs,
542 subsub_type->size[GRAS_THISARCH] * subsubcount,
543 r_ref,pointer_type->size[r_arch],
544 (char**)&l_referenced,
547 gras_dd_alloc_ref(refs,sub_type->size[GRAS_THISARCH],
548 r_ref,pointer_type->size[r_arch],
549 (char**)&l_referenced,
553 gras_datadesc_recv_rec(sock,state,refs, sub_type,
554 r_arch,r_ref,pointer_type->size[r_arch],
555 (char*)l_referenced, subsubcount,
556 detect_cycle || sub_type->cycle);
558 *(void**)l_data=l_referenced;
559 VERB3("'%s' remotely referenced at %p locally at %p",
560 sub_type->name, *(void**)r_ref, l_referenced);
563 VERB2("NOT receiving data remotely referenced @%p (already done, @%p here)",
564 *(void**)r_ref, *(void**)l_ref);
566 *(void**)l_data=*l_ref;
573 case e_gras_datadesc_type_cat_array: {
574 gras_dd_cat_array_t array_data;
579 array_data = type->category.array_data;
580 /* determine element count locally, or from caller, or from peer */
581 count = array_data.fixed_size;
585 gras_dd_recv_int(sock, r_arch, &count);
587 THROW1(mismatch_error,0,
588 "Invalid (=0) array size for type %s",type->name);
590 /* receive the content */
591 sub_type = array_data.type;
592 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
593 VERB1("Array of %d scalars, get it in one shoot", count);
594 if (sub_type->aligned_size[GRAS_THISARCH] >=
595 sub_type->aligned_size[r_arch]) {
596 gras_trp_chunk_recv(sock, (char*)l_data,
597 sub_type->aligned_size[r_arch] * count);
598 if (r_arch != GRAS_THISARCH)
599 gras_dd_convert_elm(sub_type,count,r_arch, l_data,l_data);
601 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
603 gras_trp_chunk_recv(sock, (char*)ptr,
604 sub_type->size[r_arch] * count);
605 if (r_arch != GRAS_THISARCH)
606 gras_dd_convert_elm(sub_type,count,r_arch, ptr,l_data);
609 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
610 sub_type->category.array_data.fixed_size > 0 &&
611 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
612 gras_datadesc_type_t subsub_type;
613 array_data = sub_type->category.array_data;
614 subsub_type = array_data.type;
616 VERB1("Array of %d fixed array of scalars, get it in one shot",count);
617 if (subsub_type->aligned_size[GRAS_THISARCH] >=
618 subsub_type->aligned_size[r_arch]) {
619 gras_trp_chunk_recv(sock, (char*)l_data,
620 subsub_type->aligned_size[r_arch] * count *
621 array_data.fixed_size);
622 if (r_arch != GRAS_THISARCH)
623 gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, l_data,l_data);
625 ptr = xbt_malloc(subsub_type->aligned_size[r_arch] * count*array_data.fixed_size);
627 gras_trp_chunk_recv(sock, (char*)ptr,
628 subsub_type->size[r_arch] * count*array_data.fixed_size);
629 if (r_arch != GRAS_THISARCH)
630 gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, ptr,l_data);
636 /* not scalar content, get it recursively (may contain pointers) */
637 elm_size = sub_type->aligned_size[GRAS_THISARCH];
638 VERB2("Receive a %d-long array of %s",count, sub_type->name);
641 for (cpt=0; cpt<count; cpt++) {
642 gras_datadesc_recv_rec(sock,state,refs, sub_type,
643 r_arch, NULL, 0, ptr,-1,
644 detect_cycle || sub_type->cycle);
653 xbt_assert0(0, "Invalid type");
657 type->recv(type,state,l_data);
662 * gras_datadesc_recv:
664 * Get an instance of the datatype described by @type from the @socket,
665 * and store a pointer to it in @dst
669 gras_datadesc_recv(gras_socket_t sock,
670 gras_datadesc_type_t type,
675 gras_cbps_t state; /* callback persistent state */
676 xbt_dict_t refs; /* all references already sent */
678 refs = xbt_dict_new();
679 state = gras_cbps_new();
681 xbt_assert0(type,"called with NULL type descriptor");
683 gras_datadesc_recv_rec(sock, state, refs, type,
688 xbt_dict_free(&refs);
689 gras_cbps_free(&state);
697 *** IDL compiling functions
700 #define gras_datadesc_send_rec foo /* Just to make sure the copypast was ok */
701 #define gras_datadesc_send foo /* Just to make sure the copypast was ok */
702 #define gras_datadesc_recv_rec foo /* Just to make sure the copypast was ok */
703 #define gras_datadesc_recv foo /* Just to make sure the copypast was ok */
706 gras_datadesc_gen_send_rec(gras_socket_t sock,
709 gras_datadesc_type_t type,
715 gras_datadesc_type_t sub_type; /* type on which we recurse */
717 printf(" VERB2(\"Send a %s (%s)\");\n",
718 type->name, gras_datadesc_cat_names[type->category_code]);
720 xbt_assert0(!type->send, "Callbacks not implemented in IDL compiler");
722 switch (type->category_code) {
723 case e_gras_datadesc_type_cat_scalar:
724 printf(" TRYOLD(gras_trp_chunk_send(sock, data, %lu));\n",type->size[GRAS_THISARCH]);
727 case e_gras_datadesc_type_cat_struct: {
728 gras_dd_cat_struct_t struct_data;
729 gras_dd_cat_field_t field;
732 struct_data = type->category.struct_data;
733 xbt_assert1(struct_data.closed,
734 "Please call gras_datadesc_declare_struct_close on %s before sending it",
736 printf(" VERB1(\">> Send all fields of the structure %s\");\n",type->name);
737 xbt_dynar_foreach(struct_data.fields, cpt, field) {
739 field_data += field->offset[GRAS_THISARCH];
741 sub_type = field->type;
743 xbt_assert0(!field->send, "Callbacks not implemented in IDL compiler");
745 printf(" VERB1(\"Send field %s\");\n",field->name);
746 printf(" data += %lu;\n",field->offset[GRAS_THISARCH]);
747 TRYOLD(gras_datadesc_gen_send_rec(sock,state,refs,sub_type, field_data,
748 detect_cycle || sub_type->cycle));
749 printf(" data -= %lu;\n",field->offset[GRAS_THISARCH]);
751 xbt_assert0(!field->recv, "Callbacks not implemented in IDL compiler");
753 printf(" VERB1(\"<< Sent all fields of the structure %s\"", type->name);
758 case e_gras_datadesc_type_cat_union: {
759 gras_dd_cat_union_t union_data;
760 gras_dd_cat_field_t field=NULL;
763 union_data = type->category.union_data;
765 xbt_assert1(union_data.closed,
766 "Please call gras_datadesc_declare_union_close on %s before sending it",
768 /* retrieve the field number */
769 printf(" field_num = union_data.selector(state, data);\n");
771 printf(" xbt_assert0(field_num > 0,\n");
772 printf(" \"union field selector of %s gave a negative value\");\n",type->name);
774 printf(" xbt_assert3(field_num < xbt_dynar_length(union_data.fields),\n");
775 printf(" \"union field selector of %s returned %%d but there is only %lu fields\",field_num);\n",
776 type->name, xbt_dynar_length(union_data.fields));
778 /* Send the field number */
779 printf("TRYOLD(gras_dd_send_int(sock, field_num));\n");
781 /* Send the content */
782 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
783 sub_type = field->type;
786 field->send(state,data);
788 TRYOLD(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, data,
789 detect_cycle || sub_type->cycle));
794 case e_gras_datadesc_type_cat_ref: {
795 gras_dd_cat_ref_t ref_data;
797 void **ref=(void**)data;
800 ref_data = type->category.ref_data;
802 /* Detect the referenced type and send it to peer if needed */
803 sub_type = ref_data.type;
804 if (sub_type == NULL) {
805 sub_type = (*ref_data.selector)(state,data);
806 TRYOLD(gras_dd_send_int(sock, sub_type->code));
809 /* Send the actual value of the pointer for cycle handling */
811 pointer_type = gras_datadesc_by_name("data pointer");
812 xbt_assert(pointer_type);
815 TRYOLD(gras_trp_chunk_send(sock, (char*)data,
816 pointer_type->size[GRAS_THISARCH]));
818 /* Send the pointed data only if not already sent */
819 if (*(void**)data == NULL) {
820 VERB0("Not sending NULL referenced data");
823 errcode = detect_cycle
824 ? xbt_dict_get_ext(refs,(char*)ref, sizeof(void*), &dummy)
826 if (errcode == mismatch_error) {
827 VERB1("Sending data referenced at %p", (void*)*ref);
829 xbt_dict_set_ext(refs, (char*)ref, sizeof(void*), ref, NULL);
830 TRYOLD(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, *ref,
831 detect_cycle || sub_type->cycle));
833 } else if (errcode == no_error) {
834 VERB1("Not sending data referenced at %p (already done)", (void*)*ref);
842 case e_gras_datadesc_type_cat_array: {
843 gras_dd_cat_array_t array_data;
848 array_data = type->category.array_data;
850 /* determine and send the element count */
851 count = array_data.fixed_size;
853 count = array_data.dynamic_size(state,data);
854 xbt_assert1(count >=0,
855 "Invalid (negative) array size for type %s",type->name);
856 TRYOLD(gras_dd_send_int(sock, count));
859 /* send the content */
860 sub_type = array_data.type;
861 elm_size = sub_type->aligned_size[GRAS_THISARCH];
862 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
863 VERB1("Array of %ld scalars, send it in one shot",count);
864 TRYOLD(gras_trp_chunk_send(sock, data,
865 sub_type->aligned_size[GRAS_THISARCH] * count));
866 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
867 sub_type->category.array_data.fixed_size > 0 &&
868 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
870 VERB1("Array of %ld fixed array of scalars, send it in one shot",count);
871 TRYOLD(gras_trp_chunk_send(sock, data,
872 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
873 * count * sub_type->category.array_data.fixed_size));
876 for (cpt=0; cpt<count; cpt++) {
877 TRYOLD(gras_datadesc_gen_send_rec(sock,state,refs, sub_type, ptr,
878 detect_cycle || sub_type->cycle));
886 xbt_assert0(0, "Invalid type");
893 * gras_datadesc_gen_send:
895 * Copy the data pointed by src and described by type to the socket
898 xbt_error_t gras_datadesc_gen_send(gras_socket_t sock,
899 gras_datadesc_type_t type,
904 xbt_dict_t refs; /* all references already sent */
906 refs = xbt_dict_new();
907 state = gras_cbps_new();
909 printf("xbt_error_t gras_%s_send(gras_socket_t sock,void *dst){\n",
911 errcode = gras_datadesc_gen_send_rec(sock,state,refs,type,(char*)src,
912 detect_cycle || sub_type->cycle);
915 xbt_dict_free(&refs);
916 gras_cbps_free(&state);
922 * gras_datadesc_gen_recv_rec:
924 * Do the data reception job recursively.
926 * subsize used only to deal with vicious case of reference to dynamic array.
927 * This size is needed at the reference reception level (to allocate enough
928 * space) and at the array reception level (to fill enough room).
930 * Having this size passed as an argument of the recursive function is a crude
931 * hack, but I was told that working code is sometimes better than neat one ;)
934 gras_datadesc_gen_recv_rec(gras_socket_t sock,
937 gras_datadesc_type_t type,
947 gras_datadesc_type_t sub_type;
949 VERB2("Recv a %s @%p", type->name, (void*)l_data);
952 switch (type->category_code) {
953 case e_gras_datadesc_type_cat_scalar:
954 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
955 TRYOLD(gras_trp_chunk_recv(sock, (char*)l_data, type->size[r_arch]));
956 if (r_arch != GRAS_THISARCH)
957 TRYOLD(gras_dd_convert_elm(type,1,r_arch, l_data,l_data));
959 void *ptr = xbt_malloc(type->size[r_arch]);
961 TRYOLD(gras_trp_chunk_recv(sock, (char*)ptr, type->size[r_arch]));
962 if (r_arch != GRAS_THISARCH)
963 TRYOLD(gras_dd_convert_elm(type,1,r_arch, ptr,l_data));
968 case e_gras_datadesc_type_cat_struct: {
969 gras_dd_cat_struct_t struct_data;
970 gras_dd_cat_field_t field;
972 struct_data = type->category.struct_data;
974 xbt_assert1(struct_data.closed,
975 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
977 VERB1(">> Receive all fields of the structure %s",type->name);
978 xbt_dynar_foreach(struct_data.fields, cpt, field) {
979 char *field_data = l_data + field->offset[GRAS_THISARCH];
981 sub_type = field->type;
983 TRYOLD(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
986 detect_cycle || sub_type->cycle));
988 field->recv(type,state,data);
991 VERB1("<< Received all fields of the structure %s", type->name);
996 case e_gras_datadesc_type_cat_union: {
997 gras_dd_cat_union_t union_data;
998 gras_dd_cat_field_t field=NULL;
1001 union_data = type->category.union_data;
1003 xbt_assert1(union_data.closed,
1004 "Please call gras_datadesc_declare_union_close on %s before receiving it",
1006 /* retrieve the field number */
1007 TRYOLD(gras_dd_recv_int(sock, r_arch, &field_num));
1009 RAISE1(mismatch_error,
1010 "Received union field for %s is negative", type->name);
1011 if (field_num < xbt_dynar_length(union_data.fields))
1012 RAISE3(mismatch_error,
1013 "Received union field for %s is %d but there is only %lu fields",
1014 type->name, field_num, xbt_dynar_length(union_data.fields));
1016 /* Recv the content */
1017 field = xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
1018 sub_type = field->type;
1020 TRYOLD(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
1023 detect_cycle || sub_type->cycle));
1025 field->recv(type,state,data);
1030 case e_gras_datadesc_type_cat_ref: {
1031 char **r_ref = NULL;
1032 char **l_ref = NULL;
1033 gras_dd_cat_ref_t ref_data;
1035 ref_data = type->category.ref_data;
1037 /* Get the referenced type locally or from peer */
1038 sub_type = ref_data.type;
1039 if (sub_type == NULL) {
1041 TRYOLD(gras_dd_recv_int(sock, r_arch, &ref_code));
1042 TRYOLD(gras_datadesc_by_id(ref_code, &sub_type));
1045 /* Get the actual value of the pointer for cycle handling */
1046 if (!pointer_type) {
1047 pointer_type = gras_datadesc_by_name("data pointer");
1048 xbt_assert(pointer_type);
1051 r_ref = xbt_malloc(pointer_type->size[r_arch]);
1053 TRYOLD(gras_trp_chunk_recv(sock, (char*)r_ref,
1054 pointer_type->size[r_arch]));
1056 /* Receive the pointed data only if not already sent */
1057 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
1058 VERB1("Not receiving data remotely referenced @%p since it's NULL",
1060 *(void**)l_data = NULL;
1065 errcode = detect_cycle
1066 ? xbt_dict_get_ext(refs,
1067 (char*)r_ref, pointer_type->size[r_arch],
1071 if (errcode == mismatch_error) {
1072 int subsubcount = 0;
1073 void *l_referenced=NULL;
1075 VERB2("Receiving a ref to '%s', remotely @%p",
1076 sub_type->name, *(void**)r_ref);
1077 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
1078 /* Damn. Reference to a dynamic array. Allocating the size for it
1079 is more complicated */
1080 gras_dd_cat_array_t array_data = sub_type->category.array_data;
1081 gras_datadesc_type_t subsub_type;
1083 subsubcount = array_data.fixed_size;
1084 if (subsubcount == 0)
1085 TRYOLD(gras_dd_recv_int(sock, r_arch, &subsubcount));
1087 subsub_type = array_data.type;
1090 TRYOLD(gras_dd_alloc_ref(refs,
1091 subsub_type->size[GRAS_THISARCH] * subsubcount,
1092 r_ref,pointer_type->size[r_arch],
1093 (char**)&l_referenced,
1096 TRYOLD(gras_dd_alloc_ref(refs,sub_type->size[GRAS_THISARCH],
1097 r_ref,pointer_type->size[r_arch],
1098 (char**)&l_referenced,
1102 TRYOLD(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
1103 r_arch,r_ref,pointer_type->size[r_arch],
1104 (char*)l_referenced, subsubcount,
1105 detect_cycle || sub_type->cycle));
1107 *(void**)l_data=l_referenced;
1108 VERB3("'%s' remotely referenced at %p locally at %p",
1109 sub_type->name, *(void**)r_ref, l_referenced);
1111 } else if (errcode == no_error) {
1112 VERB2("NOT receiving data remotely referenced @%p (already done, @%p here)",
1113 *(void**)r_ref, *(void**)l_ref);
1115 *(void**)l_data=*l_ref;
1124 case e_gras_datadesc_type_cat_array: {
1125 gras_dd_cat_array_t array_data;
1130 array_data = type->category.array_data;
1131 /* determine element count locally, or from caller, or from peer */
1132 count = array_data.fixed_size;
1136 TRYOLD(gras_dd_recv_int(sock, r_arch, &count));
1138 RAISE1(mismatch_error,
1139 "Invalid (=0) array size for type %s",type->name);
1141 /* receive the content */
1142 sub_type = array_data.type;
1143 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
1144 VERB1("Array of %d scalars, get it in one shoot", count);
1145 if (sub_type->aligned_size[GRAS_THISARCH] >=
1146 sub_type->aligned_size[r_arch]) {
1147 TRYOLD(gras_trp_chunk_recv(sock, (char*)l_data,
1148 sub_type->aligned_size[r_arch] * count));
1149 if (r_arch != GRAS_THISARCH)
1150 TRYOLD(gras_dd_convert_elm(sub_type,count,r_arch, l_data,l_data));
1152 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
1154 TRYOLD(gras_trp_chunk_recv(sock, (char*)ptr,
1155 sub_type->size[r_arch] * count));
1156 if (r_arch != GRAS_THISARCH)
1157 TRYOLD(gras_dd_convert_elm(sub_type,count,r_arch, ptr,l_data));
1160 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
1161 sub_type->category.array_data.fixed_size > 0 &&
1162 sub_type->category.array_data.type->category_code == e_gras_datadesc_type_cat_scalar) {
1163 gras_datadesc_type_t subsub_type;
1164 array_data = sub_type->category.array_data;
1165 subsub_type = array_data.type;
1167 VERB1("Array of %d fixed array of scalars, get it in one shot",count);
1168 if (subsub_type->aligned_size[GRAS_THISARCH] >=
1169 subsub_type->aligned_size[r_arch]) {
1170 TRYOLD(gras_trp_chunk_recv(sock, (char*)l_data,
1171 subsub_type->aligned_size[r_arch] * count *
1172 array_data.fixed_size));
1173 if (r_arch != GRAS_THISARCH)
1174 TRYOLD(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, l_data,l_data));
1176 ptr = xbt_malloc(subsub_type->aligned_size[r_arch] * count*array_data.fixed_size);
1178 TRYOLD(gras_trp_chunk_recv(sock, (char*)ptr,
1179 subsub_type->size[r_arch] * count*array_data.fixed_size));
1180 if (r_arch != GRAS_THISARCH)
1181 TRYOLD(gras_dd_convert_elm(subsub_type,count*array_data.fixed_size,r_arch, ptr,l_data));
1187 /* not scalar content, get it recursively (may contain pointers) */
1188 elm_size = sub_type->aligned_size[GRAS_THISARCH];
1189 VERB2("Receive a %d-long array of %s",count, sub_type->name);
1192 for (cpt=0; cpt<count; cpt++) {
1193 TRYOLD(gras_datadesc_gen_recv_rec(sock,state,refs, sub_type,
1194 r_arch, NULL, 0, ptr,-1,
1195 detect_cycle || sub_type->cycle));
1204 xbt_assert0(0, "Invalid type");
1208 type->recv(type,state,l_data);
1214 * gras_datadesc_gen_recv:
1216 * Get an instance of the datatype described by @type from the @socket,
1217 * and store a pointer to it in @dst
1221 gras_datadesc_gen_recv(gras_socket_t sock,
1222 gras_datadesc_type_t type,
1226 xbt_error_t errcode;
1227 gras_cbps_t state; /* callback persistent state */
1228 xbt_dict_t refs; /* all references already sent */
1230 refs = xbt_dict_new();
1231 state = gras_cbps_new();
1233 printf("xbt_error_t gras_%s_recv(gras_socket_t sock,void *dst){\n",
1236 errcode = gras_datadesc_gen_recv_rec(sock, state, refs, type,
1242 xbt_dict_free(&refs);
1243 gras_cbps_free(&state);