Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
1fb1b00b72d3a974f5460f5f220130a41b6f9748
[simgrid.git] / src / gras / gs / message.c
1 /* gs_message.c */
2
3 #include "gs/gs_private.h"
4
5 /*
6  * Sequences
7  */
8 static
9 struct s_gs_sequence *
10 _gs_sequence_alloc(void) {
11         struct s_gs_sequence            *p_sequence             = NULL;
12         p_sequence = malloc(sizeof(struct s_gs_sequence));
13         return p_sequence;
14 }
15
16 static
17 struct s_gs_sequence *
18 _gs_sequence_new(void) {
19         struct s_gs_sequence            *p_sequence             = NULL;
20
21         p_sequence = _gs_sequence_alloc();
22
23         p_sequence->message = NULL;
24         p_sequence->code    =   -1;
25         p_sequence->next    = NULL;
26
27         return p_sequence;
28 }
29
30 /*
31  * Messages
32  */
33 static
34 struct s_gs_message *
35 _gs_message_alloc(void) {
36         struct s_gs_message *p_message = NULL;
37
38         p_message = malloc(sizeof(struct s_gs_message));
39
40         return p_message;
41 }
42
43 struct s_gs_message *
44 gs_message_new(struct s_gs_type_bag     *p_bag,
45                struct s_gs_connection   *p_connection,
46                const char               *name) {
47
48         struct s_gs_type_bag_ops        *bag_ops        = p_bag->bag_ops;
49         struct s_gs_message             *p_message      = NULL;
50
51         p_message        = _gs_message_alloc();
52
53         p_message->code  = -1;
54         p_message->name  = strdup(name);
55
56         p_message->first = NULL;
57         p_message->last  = NULL;
58
59         bag_ops->store_message(p_bag, p_connection, p_message);
60
61         return p_message;
62 }
63
64
65 void
66 gs_message_append_new_sequence(struct s_gs_message      *p_message,
67                                struct s_gs_type         *p_type) {
68
69         struct s_gs_sequence *p_sequence = NULL;
70
71         p_sequence = _gs_sequence_new();
72
73         p_sequence->message = p_message;
74         p_sequence->code    = p_type->code;
75         p_sequence->next    = NULL;
76
77         if (p_message->first) {
78                 p_message->last ->next = p_sequence;
79         } else {
80                 p_message->first       = p_sequence;
81         }
82
83         p_message->last = p_sequence;
84 }
85
86
87 /*
88  * Send/receive
89  */
90 static
91 struct s_gs_message_instance *
92 _gs_message_instance_alloc(void) {
93         struct s_gs_message_instance *p_message_instance = NULL;
94         p_message_instance = malloc(sizeof (struct s_gs_message_instance));
95         return p_message_instance;
96 }
97
98 static
99 struct s_gs_message_instance *
100 _gs_message_instance_new(void) {
101         struct s_gs_message_instance *p_message_instance = NULL;
102
103         p_message_instance = _gs_message_instance_alloc();
104
105         p_message_instance->p_message           = NULL;
106         p_message_instance->current             = NULL;
107         p_message_instance->p_bag               = NULL;
108         p_message_instance->p_connection        = NULL;
109
110         return p_message_instance;
111 }
112
113 /* Send */
114 static
115 void
116 _gs_message_send_type(struct s_gs_type_bag       *p_bag,
117                       struct s_gs_connection     *p_cnx,
118                       void                       *vars,
119                       gras_dict_t               **p_refs,
120                       struct s_gs_type           *p_type,
121                       void                       *data);
122
123 static
124 struct s_gs_type *
125 _sg_message_send_get_type_by_code(struct s_gs_type_bag   *p_bag,
126                                   struct s_gs_connection *p_cnx,
127                                   void                   *vars,
128                                   int                     code) {
129         struct s_gs_type_bag_ops        *bops   = p_bag->bag_ops;
130         struct s_gs_type                *p_type = NULL;
131
132         p_type = bops->get_type_by_code(p_bag, NULL, code);
133
134         if (!bops->check_type_mark(p_bag, p_cnx, p_type->name)) {
135                 struct s_gs_type        *p_type_type = NULL;
136                 gras_dict_t             *_refs       = NULL;
137
138                 p_type_type = bops->get_type_by_name(p_bag, NULL, "_s_gs_type");
139                 if (!p_type_type)
140                         GS_FAILURE("_s_gs_type default type missing");
141
142                 bops->mark_type(p_bag, p_cnx, p_type->name);
143
144                 fprintf(stderr, "sending type with code = %d\n", code);
145                 gs_vars_enter(vars);
146                 _gs_message_send_type(p_bag, p_cnx, vars, &_refs, p_type_type, p_type);
147                 gs_vars_leave(vars);
148                 fprintf(stderr, "type with code = %d, name = %s sent\n", code, p_type->name);
149         } else {
150                 fprintf(stderr, "no need to send type with code = %d, name = %s\n", code, p_type->name);
151         }
152
153         return p_type;
154 }
155
156 static
157 void
158 _gs_message_send_type(struct s_gs_type_bag       *p_bag,
159                       struct s_gs_connection     *p_cnx,
160                       void                       *vars,
161                       gras_dict_t               **p_refs,
162                       struct s_gs_type           *p_type,
163                       void                       *data) {
164
165         struct s_gs_type_bag_ops        *bops = p_bag->bag_ops;
166         struct s_gs_connection_ops      *cops = p_cnx->connection_ops;
167
168         if (p_type->category_code > 1)
169                 fprintf(stderr, "\n");
170         fprintf(stderr, "sending a %s\n", p_type->name);
171
172         switch (p_type->category_code) {
173
174         case e_gs_type_cat_elemental:
175                 {
176                         if (p_type->before_callback) {
177                                 p_type->before_callback(vars, p_type, data);
178                         }
179
180                         cops->write (p_cnx, data, p_type->size);
181                 }
182                 break;
183
184         case e_gs_type_cat_struct   :
185                 {
186                         struct s_gs_cat_struct *p_struct  = NULL;
187
188                         if (p_type->before_callback) {
189                                 p_type->before_callback(vars, p_type, data);
190                         }
191
192                         p_struct = p_type->category.struct_data;
193
194                         {
195                                 int nb_fields = 0;
196                                 int i         = 0;
197
198                                 nb_fields = p_struct->nb_fields;
199
200                                 while (i < nb_fields) {
201                                         struct s_gs_cat_struct_field    *p_field        = NULL;
202                                         struct s_gs_type                *p_field_type   = NULL;
203                                         void                            *ref            = NULL;
204
205                                         p_field         = p_struct->field_array[i];
206                                         p_field_type    = _sg_message_send_get_type_by_code(p_bag, p_cnx, vars, p_field->code);
207                                         ref             = ((char *)data) + p_field->offset;
208
209                                         if (p_field->before_callback) {
210                                                 p_field->before_callback(vars, p_field_type, ref);
211                                         }
212
213                                         _gs_message_send_type(p_bag,
214                                                               p_cnx,
215                                                               vars,
216                                                               p_refs,
217                                                               p_field_type,
218                                                               ref);
219
220                                         if (p_field->after_callback) {
221                                                 p_field->after_callback(vars, p_field_type, ref);
222                                         }
223
224                                         i++;
225                                 }
226                         }
227
228                         if (p_type->after_callback) {
229                                 p_type->after_callback(vars, p_type, data);
230                         }
231                 }
232                 break;
233
234         case e_gs_type_cat_union   :
235                 {
236                         struct s_gs_cat_union *p_union  = NULL;
237
238                         p_union = p_type->category.union_data;
239
240                         {
241                                 int                              field_num      = 0;
242                                 struct s_gs_cat_union_field     *p_field        = NULL;
243                                 struct s_gs_type                *p_field_type   = NULL;
244
245                                 field_num = p_union->callback(vars, p_type, data);
246
247                                 if ((field_num < 0) || (field_num >= p_union->nb_fields))
248                                         GS_FAILURE("invalid field index");
249
250                                 _gs_message_send_type(p_bag,
251                                                       p_cnx,
252                                                       vars,
253                                                       p_refs,
254                                                       bops->get_type_by_name(p_bag, NULL, "signed int"),
255                                                       &field_num);
256
257                                 p_field         = p_union->field_array[field_num];
258                                 p_field_type    = _sg_message_send_get_type_by_code(p_bag, p_cnx, vars, p_field->code);
259
260                                 if (p_field->before_callback) {
261                                         p_field->before_callback(vars, p_field_type, data);
262                                 }
263
264                                 _gs_message_send_type(p_bag,
265                                                       p_cnx,
266                                                       vars,
267                                                       p_refs,
268                                                       p_field_type,
269                                                       data);
270
271                                 if (p_field->after_callback) {
272                                         p_field->after_callback(vars, p_field_type, data);
273                                 }
274                         }
275
276                         if (p_type->after_callback) {
277                                 p_type->after_callback(vars, p_type, data);
278                         }
279                 }
280                 break;
281
282         case e_gs_type_cat_ref      :
283                 {
284                         void                    *dummy          = NULL;
285                         void                    **p_ref         = (void **)data;
286                         struct s_gs_cat_ref     *p_ref_data     = NULL;
287                         int                      code           = 0;
288
289                         p_ref_data = p_type->category.ref_data;
290
291                         if (p_ref_data->callback) {
292                                 code = p_ref_data->callback(vars, p_type, data);
293                         }
294
295                         if (p_ref_data->code >= 0) {
296                                 code = p_ref_data->code;
297                         } else {
298                                 _gs_message_send_type(p_bag,
299                                                       p_cnx,
300                                                       vars,
301                                                       p_refs,
302                                                       bops->get_type_by_name(p_bag, NULL, "signed int"),
303                                                       &code);
304                         }
305
306                         cops->write (p_cnx, data, p_type->size);
307
308                         if (*p_ref && !(gras_dict_retrieve_ext(*p_refs, (char *)p_ref, sizeof(void *), &dummy), dummy)) {
309                                 struct s_gs_type        *p_ref_type     = NULL;
310
311                                 fprintf(stderr, "sending data referenced at %p\n", *p_ref);
312                                 gras_dict_insert_ext(*p_refs, (char *)p_ref, sizeof(void *), p_ref, NULL);
313
314                                 p_ref_type = _sg_message_send_get_type_by_code(p_bag, p_cnx, vars, code);
315
316                                 _gs_message_send_type(p_bag,
317                                                       p_cnx,
318                                                       vars,
319                                                       p_refs,
320                                                       p_ref_type,
321                                                       *p_ref);
322
323                         } else {
324                                 /**/
325                                 fprintf(stderr, "not sending data referenced at %p\n", *p_ref);
326                         }
327
328                         if (p_type->after_callback) {
329                                 p_type->after_callback(vars, p_type, data);
330                         }
331                 }
332                 break;
333
334         case e_gs_type_cat_array    :
335                 {
336                         struct s_gs_cat_array *p_array        = NULL;
337                         long int               count          =    0;
338                         struct s_gs_type      *p_element_type = NULL;
339                         long int               element_size   =    0;
340                         char                  *ptr            = data;
341
342                         p_array = p_type->category.array_data;
343                         count   = p_array->element_count;
344
345                         if (count < 0) {
346                                 count = p_array->callback(vars, p_type, data);
347                                 if (count < 0)
348                                         GS_FAILURE("invalid array element count");
349                         } else if (p_array->callback) {
350                                 (void)p_array->callback(vars, p_type, data);
351                         }
352
353                         _gs_message_send_type(p_bag,
354                                               p_cnx,
355                                               vars,
356                                               p_refs,
357                                               bops->get_type_by_name(p_bag, NULL, "signed long int"),
358                                               &count);
359
360                         p_element_type  = _sg_message_send_get_type_by_code(p_bag, p_cnx, vars, p_array->code);
361                         element_size    = p_element_type->aligned_size;
362
363                         if (count == 0)
364                                 goto empty_array;
365
366                         while (count --) {
367                                 _gs_message_send_type(p_bag,
368                                                       p_cnx,
369                                                       vars,
370                                                       p_refs,
371                                                       p_element_type,
372                                                       ptr);
373
374                                 ptr += element_size;
375                         }
376
377                 empty_array:
378                         if (p_type->after_callback) {
379                                 p_type->after_callback(vars, p_type, data);
380                         }
381                 }
382                 break;
383
384
385        case e_gs_type_cat_ignored    :
386                 {
387                         if (p_type->before_callback) {
388                                 p_type->before_callback(vars, p_type, data);
389                         }
390                 }
391                 break;
392
393          default:
394                 GS_FAILURE("invalid type");
395         }
396 }
397
398 struct s_gs_message_instance *
399 gs_message_init_send_by_ref(struct s_gs_type_bag        *p_bag,
400                             struct s_gs_connection      *p_cnx,
401                             struct s_gs_message         *p_message) {
402         struct s_gs_type_bag_ops        *bops                   = p_bag->bag_ops;
403         struct s_gs_message_instance    *p_message_instance     = NULL;
404         void                            *vars                   = NULL;
405
406         vars = gs_vars_alloc();
407
408         if (!bops->check_message_mark(p_bag, p_cnx, p_message->name)) {
409                 struct s_gs_type        *p_message_type = NULL;
410                 gras_dict_t             *_refs          = NULL;
411                 struct s_gs_type        *signed_int     = NULL;
412
413                 signed_int = bops->get_type_by_name(p_bag, NULL, "signed int");
414                 p_message_type = bops->get_type_by_name(p_bag, NULL, "_s_gs_message");
415
416                 if (!p_message_type)
417                         GS_FAILURE("_s_gs_message default type missing");
418
419                 bops->mark_message(p_bag, p_cnx, p_message->name);
420
421                 _gs_message_send_type(p_bag, p_cnx, vars, &_refs, signed_int,     &p_message->code);
422                 _gs_message_send_type(p_bag, p_cnx, vars, &_refs, p_message_type,  p_message);
423         } else {
424                 gras_dict_t             *_refs          = NULL;
425                 struct s_gs_type        *signed_int     = NULL;
426
427                 _gs_message_send_type(p_bag, p_cnx, vars, &_refs, signed_int, &p_message->code);
428         }
429
430         gs_vars_free(vars);
431
432         p_message_instance      = _gs_message_instance_new();
433
434         p_message_instance->p_message           = p_message;
435         p_message_instance->current             = p_message->first;
436         p_message_instance->p_bag               = p_bag;
437         p_message_instance->p_connection        = p_cnx;
438
439
440         return p_message_instance;
441 }
442
443 struct s_gs_message_instance *
444 gs_message_init_send_by_name(struct s_gs_type_bag       *p_bag,
445                              struct s_gs_connection     *p_connection,
446                              const char                 *name) {
447         struct s_gs_type_bag_ops        *bag_ops                = p_bag->bag_ops;
448         struct s_gs_message             *p_message              = NULL;
449         struct s_gs_message_instance    *p_message_instance     = NULL;
450
451         p_message               = bag_ops->get_message_by_name(p_bag, NULL, name);
452         p_message_instance      = gs_message_init_send_by_ref(p_bag, p_connection, p_message);
453
454         return p_message_instance;
455 }
456
457 struct s_gs_message_instance *
458 gs_message_init_send_by_code(struct s_gs_type_bag       *p_bag,
459                              struct s_gs_connection     *p_connection,
460                              int                        code) {
461         struct s_gs_type_bag_ops        *bag_ops                = p_bag->bag_ops;
462         struct s_gs_message             *p_message              = NULL;
463         struct s_gs_message_instance    *p_message_instance     = NULL;
464
465         p_message               = bag_ops->get_message_by_code(p_bag, NULL, code);
466         p_message_instance      = gs_message_init_send_by_ref(p_bag, p_connection, p_message);
467
468         return p_message_instance;
469 }
470
471 void
472 gs_message_send_next_sequence_ext(void                         *vars,
473                                   struct s_gs_message_instance *p_message_instance,
474                                   void                         *data) {
475         struct s_gs_type_bag            *p_bag          = p_message_instance->p_bag;
476         struct s_gs_connection          *p_cnx          = p_message_instance->p_connection;
477         struct s_gs_sequence            *p_sequence     = NULL;
478         struct s_gs_type                *p_type         = NULL;
479         gras_dict_t                     *refs           = NULL;
480
481         p_sequence = p_message_instance->current;
482         if (!p_sequence)
483                 GS_FAILURE("message type has no more sequences");
484
485         p_type = _sg_message_send_get_type_by_code(p_bag, p_cnx, vars, p_sequence->code);
486         _gs_message_send_type(p_message_instance->p_bag,
487                               p_message_instance->p_connection,
488                               vars,
489                               &refs,
490                               p_type,
491                               data);
492         gras_dict_free(&refs);
493         p_message_instance->current = p_sequence->next;
494 }
495
496 void
497 gs_message_send_next_sequence(struct s_gs_message_instance *p_message_instance,
498                               void                         *data) {
499         void *vars = NULL;
500
501         vars = gs_vars_alloc();
502         gs_message_send_next_sequence_ext(vars, p_message_instance, data);
503         gs_vars_free(vars);
504 }
505
506
507 /* recv */
508
509
510 /*
511  * Note: here we suppose that the remote NULL is a sequence of 'length' bytes set to 0.
512  */
513 static
514 int
515 _gs_is_null(void        **p_ptr,
516             long int      length) {
517         int i;
518
519         for (i = 0; i < length; i++) {
520                 if (((unsigned char *)p_ptr)[i]) {
521                         return 0;
522                 }
523         }
524
525         return 1;
526 }
527
528
529 static
530 void
531 _gs_alloc_ref(gras_dict_t       **p_refs,
532               long int            size,
533               void              **p_old_ref,
534               long int            length,
535               void              **p_new_ref) {
536         void *new_ref = NULL;
537
538         new_ref = malloc((size_t)size);
539         *p_new_ref      = new_ref;
540
541         if (p_old_ref && !_gs_is_null(p_old_ref, length)) {
542                 p_old_ref       = gs_memdup(p_old_ref, (size_t)length);
543                 p_new_ref       = gs_memdup(&new_ref, sizeof(void *));
544
545                 gras_dict_insert_ext(*p_refs,(char *) p_old_ref, length, p_new_ref, NULL);
546         }
547 }
548
549 static
550 void
551 _gs_convert_elemental(void              *local,
552                       struct s_gs_type  *p_local_type,
553                       void              *remote,
554                       struct s_gs_type  *p_remote_type) {
555         struct s_gs_cat_elemental *p_local_elemental  = p_local_type->category.elemental_data;
556         struct s_gs_cat_elemental *p_remote_elemental = p_remote_type->category.elemental_data;
557
558         (void)local;
559         (void)remote;
560
561         if (p_local_elemental->encoding == p_remote_elemental->encoding) {
562                 if (p_local_type->size != p_remote_type->size) {
563                         GS_FAILURE("size conversion unimplemented");
564                 }
565         } else {
566                 GS_FAILURE("encoding conversion unimplemented");
567         }
568 }
569
570 static
571 void
572 _gs_message_receive_type(struct s_gs_type_bag    *p_bag,
573                          struct s_gs_connection  *p_cnx,
574                          gras_dict_t            **p_refs,
575                          struct s_gs_type        *p_type,
576                          void                   **p_old_data,
577                          long int                 old_data_length,
578                          void                   **p_new_data);
579
580 static
581 struct s_gs_type *
582 _sg_message_receive_get_type_by_code(struct s_gs_type_bag       *p_bag,
583                                      struct s_gs_connection     *p_cnx,
584                                      int                         code) {
585         struct s_gs_type_bag_ops        *bops   = p_bag->bag_ops;
586         struct s_gs_type                *p_type = NULL;
587
588         p_type = bops->get_type_by_code(p_bag, p_cnx, code);
589
590         if (!p_type) {
591                 struct s_gs_type        *p_type_type = NULL;
592                 gras_dict_t             *_refs       = NULL;
593
594                 p_type_type = bops->get_type_by_name(p_bag, p_cnx, "_s_gs_type");
595                 if (!p_type_type)
596                         GS_FAILURE("_s_gs_type default type missing");
597
598                 fprintf(stderr, "need type with code = %d\n", code);
599                 _gs_message_receive_type(p_bag, p_cnx, &_refs, p_type_type, NULL, 0, (void **)&p_type);
600                 fprintf(stderr, "got type with code = %d, name = %s\n", code, p_type->name);
601
602                 bops->store_incoming_type(p_bag, p_cnx, p_type);
603         } else {
604                 fprintf(stderr, "already seen type with code = %d, name = %s\n", code, p_type->name);
605         }
606         
607
608         return p_type;
609 }
610
611 static
612 void
613 _gs_message_receive_type(struct s_gs_type_bag    *p_bag,
614                          struct s_gs_connection  *p_cnx,
615                          gras_dict_t            **p_refs,
616                          struct s_gs_type        *p_remote_type,
617                          void                   **p_old_ptr,
618                          long int                 old_ptr_length,
619                          void                   **p_new_ptr) {
620         struct s_gs_type_bag_ops        *bops           = p_bag->bag_ops;
621         struct s_gs_connection_ops      *cops           = p_cnx->connection_ops;
622         struct s_gs_type                *p_local_type   = NULL;
623         void                            *new_data       = *p_new_ptr;
624
625         p_local_type = bops->get_type_by_name(p_bag, NULL, p_remote_type->name);
626         if (p_local_type->category_code > 1)
627                 fprintf(stderr, "\n");
628         fprintf(stderr, "receiving a %s\n", p_local_type->name);
629
630         switch (p_remote_type->category_code) {
631
632         case e_gs_type_cat_elemental:
633                 {
634                         if (!new_data) {
635                                 _gs_alloc_ref(p_refs, p_local_type->size, p_old_ptr, old_ptr_length, p_new_ptr);
636                                 new_data = *p_new_ptr;
637                         }
638
639                         if (p_remote_type->size <= p_local_type->size) {
640                                 cops->read (p_cnx, new_data, p_remote_type->size);
641                                 _gs_convert_elemental(new_data, p_local_type, new_data, p_remote_type);
642                         } else {
643                                 void *ptr = NULL;
644
645                                 ptr = malloc((size_t)p_remote_type->size);
646                                 cops->read (p_cnx, ptr, p_remote_type->size);
647                                 _gs_convert_elemental(new_data, p_local_type, ptr, p_remote_type);
648                                 free(ptr);
649                         }
650                 }
651                 break;
652
653         case e_gs_type_cat_struct   :
654                 {
655                         struct s_gs_cat_struct *p_struct  = NULL;
656
657                         p_struct = p_remote_type->category.struct_data;
658
659                         if (!new_data) {
660                                 _gs_alloc_ref(p_refs, p_local_type->size, p_old_ptr, old_ptr_length, p_new_ptr);
661                                 new_data = *p_new_ptr;
662                         }
663
664                         {
665                                 int nb_fields = 0;
666                                 int i         = 0;
667
668                                 nb_fields = p_struct->nb_fields;
669
670                                 while (i < nb_fields) {
671                                         struct s_gs_cat_struct_field    *p_field        = NULL;
672                                         struct s_gs_type                *p_field_type   = NULL;
673                                         void                            *ref            = NULL;
674
675                                         p_field         = p_struct->field_array[i];
676                                         p_field_type    = _sg_message_receive_get_type_by_code(p_bag, p_cnx, p_field->code);
677                                         ref             = ((char *)new_data) + p_field->offset;
678
679                                         _gs_message_receive_type(p_bag,
680                                                                  p_cnx,
681                                                                  p_refs,
682                                                                  p_field_type,
683                                                                  NULL,
684                                                                  0,
685                                                                  &ref);
686                                         i++;
687                                 }
688                         }
689                 }
690                 break;
691
692         case e_gs_type_cat_union   :
693                 {
694                         struct s_gs_cat_union *p_union  = NULL;
695
696                         p_union = p_remote_type->category.union_data;
697
698                         if (!new_data) {
699                                 _gs_alloc_ref(p_refs, p_local_type->size, p_old_ptr, old_ptr_length, p_new_ptr);
700                                 new_data = *p_new_ptr;
701                         }
702
703                         {
704                                 int                              field_num      = 0;
705                                 struct s_gs_cat_union_field     *p_field        = NULL;
706                                 struct s_gs_type                *p_field_type   = NULL;
707
708                                 {
709                                         int *p_field_num = &field_num;
710
711                                         _gs_message_receive_type(p_bag,
712                                                                  p_cnx,
713                                                                  p_refs,
714                                                                  bops->get_type_by_name(p_bag, p_cnx, "signed int"),
715                                                                  NULL,
716                                                                  0,
717                                                                  (void**)&p_field_num);
718                                 }
719
720                                 p_field         = p_union->field_array[field_num];
721                                 p_field_type    = _sg_message_receive_get_type_by_code(p_bag, p_cnx, p_field->code);
722
723                                 _gs_message_receive_type(p_bag,
724                                                          p_cnx,
725                                                          p_refs,
726                                                          p_field_type,
727                                                          NULL,
728                                                          0,
729                                                          &new_data);
730                         }
731                 }
732                 break;
733
734         case e_gs_type_cat_ref      :
735                 {
736                         void                    **p_old_ref     = NULL;
737                         void                    **p_new_ref     = NULL;
738                         struct s_gs_cat_ref      *p_ref_data    = NULL;
739                         int                       code          = 0;
740
741                         p_ref_data      = p_remote_type->category.ref_data;
742                         code            = p_ref_data->code;
743
744                         if (code < 0) {
745                                 int *p_code = &code;
746
747                                 _gs_message_receive_type(p_bag,
748                                                          p_cnx,
749                                                          p_refs,
750                                                          bops->get_type_by_name(p_bag, p_cnx, "signed int"),
751                                                          NULL,
752                                                          0,
753                                                          (void**)&p_code);
754                         }
755
756                         p_old_ref = malloc((size_t)p_remote_type->size);
757                         cops->read (p_cnx, p_old_ref, p_remote_type->size);
758
759                         if (!new_data) {
760                                 _gs_alloc_ref(p_refs, p_local_type->size, p_old_ptr, old_ptr_length, p_new_ptr);
761                                 new_data = *p_new_ptr;
762                         }
763
764                         if (!_gs_is_null(p_old_ref, p_remote_type->size)) {
765                                 if (!(gras_dict_retrieve_ext(*p_refs, (char *)p_old_ref, p_remote_type->size, (void **)&p_new_ref), p_new_ref)) {
766                                         void             *new_ref       = NULL;
767                                         struct s_gs_type *p_ref_type    = NULL;
768
769                                         fprintf(stderr, "receiving data referenced at %p\n", *(void **)p_old_ref);
770                                         p_ref_type = _sg_message_receive_get_type_by_code(p_bag, p_cnx, code);
771
772                                         _gs_message_receive_type(p_bag,
773                                                                  p_cnx,
774                                                                  p_refs,
775                                                                  p_ref_type,
776                                                                  p_old_ref,
777                                                                  p_remote_type->size,
778                                                                  &new_ref);
779
780                                         *(void **)new_data      = new_ref;
781                                 } else {
782                                         fprintf(stderr, "not receiving data referenced at %p\n", *(void **)p_old_ref);
783                                         *(void **)new_data      = *p_new_ref;
784                                 }
785                         } else {
786                                 fprintf(stderr, "not receiving data referenced at %p\n", *(void **)p_old_ref);
787                                 *(void **)new_data      = NULL;
788                         }
789                 }
790                 break;
791
792         case e_gs_type_cat_array    :
793                 {
794                         struct s_gs_cat_array *p_array        = NULL;
795                         long int               count          =    0;
796                         struct s_gs_type      *p_element_type = NULL;
797                         struct s_gs_type      *p_local_element_type =   NULL;
798                         long int               element_size   =    0;
799                         char                  *ptr            = NULL;
800
801                         p_array = p_remote_type->category.array_data;
802
803                         {
804                                 long int *p_count = &count;
805
806                                 _gs_message_receive_type(p_bag,
807                                                          p_cnx,
808                                                          p_refs,
809                                                          bops->get_type_by_name(p_bag, p_cnx, "signed long int"),
810                                                          NULL,
811                                                          0,
812                                                          (void**)&p_count);
813                         }
814
815                         p_element_type          = _sg_message_receive_get_type_by_code(p_bag, p_cnx, p_array->code);
816                         p_local_element_type    = bops->get_type_by_name(p_bag, NULL, p_element_type->name);
817                         element_size            = p_local_element_type->aligned_size;
818
819                         if (!new_data) {
820                                 _gs_alloc_ref(p_refs, count*element_size, p_old_ptr, old_ptr_length, p_new_ptr);
821                                 new_data = *p_new_ptr;
822                         }
823
824                         ptr = new_data;
825
826                         if (!count)
827                                 return;
828
829                         while (count --) {
830                                 _gs_message_receive_type(p_bag,
831                                                          p_cnx,
832                                                          p_refs,
833                                                          p_element_type,
834                                                          NULL,
835                                                          0,
836                                                          (void**)&ptr);
837
838                                 ptr += element_size;
839                         }
840                 }
841                 break;
842
843         case e_gs_type_cat_ignored:
844                 {
845                         struct s_gs_cat_ignored *p_ignored        =     NULL;
846
847                         if (!new_data) {
848                                 _gs_alloc_ref(p_refs, p_local_type->size, p_old_ptr, old_ptr_length, p_new_ptr);
849                                 new_data = *p_new_ptr;
850                         }
851
852                         p_ignored = p_local_type->category.ignored_data;
853
854                         if (p_ignored->default_value) {
855                                 memcpy(new_data, p_ignored->default_value, (size_t)p_local_type->size);
856                         }
857                 }
858                 break;
859
860
861         default:
862                 GS_FAILURE("invalid type");
863         }
864 }
865
866 struct s_gs_message_instance *
867 gs_message_init_receive(struct s_gs_type_bag    *p_bag,
868                         struct s_gs_connection  *p_cnx) {
869
870         struct s_gs_type_bag_ops        *bops                   = p_bag->bag_ops;
871         struct s_gs_message_instance    *p_message_instance     = NULL;
872         int                             *p_code                 = NULL;
873         struct s_gs_message             *p_message              = NULL;
874
875         {
876                 gras_dict_t             *_refs          = NULL;
877                 struct s_gs_type        *signed_int     = NULL;
878
879                 signed_int = bops->get_type_by_name(p_bag, p_cnx, "signed int");
880                 _gs_message_receive_type(p_bag, p_cnx, &_refs, signed_int, NULL, 0, (void**)&p_code);
881
882                 p_message = bops->get_message_by_code(p_bag, p_cnx, *p_code);
883
884                 if (!p_message) {
885                         struct s_gs_type        *p_message_type = NULL;
886                         p_message_type = bops->get_type_by_name(p_bag, p_cnx, "_s_gs_message");
887
888                         if (!p_message_type)
889                                 GS_FAILURE("_s_gs_message default type missing");
890
891                         _gs_message_receive_type(p_bag, p_cnx, &_refs, p_message_type, NULL, 0, (void **)&p_message);
892
893                         bops->store_incoming_message(p_bag, p_cnx, p_message);
894                 }
895         }
896
897         p_message_instance      = _gs_message_instance_new();
898
899         p_message_instance->p_message           = p_message;
900         p_message_instance->current             = p_message->first;
901         p_message_instance->p_bag               = p_bag;
902         p_message_instance->p_connection        = p_cnx;
903
904         return p_message_instance;
905 }
906
907 void *
908 gs_message_receive_next_sequence(struct s_gs_message_instance *p_message_instance) {
909         struct s_gs_type_bag            *p_bag          = p_message_instance->p_bag;
910         struct s_gs_connection          *p_cnx          = p_message_instance->p_connection;
911         struct s_gs_sequence            *p_sequence     = NULL;
912         struct s_gs_type                *p_remote_type  = NULL;
913         gras_dict_t                     *refs           = NULL;
914         void                            *data           = NULL;
915
916         p_sequence = p_message_instance->current;
917         if (!p_sequence)
918                 GS_FAILURE("message type has no more sequences");
919
920         p_remote_type = _sg_message_receive_get_type_by_code(p_bag, p_cnx, p_sequence->code);
921         _gs_message_receive_type(p_bag,
922                                  p_cnx,
923                                  &refs,
924                                  p_remote_type,
925                                  NULL,
926                                  0,
927                                  &data);
928
929         gras_dict_free(&refs);
930
931         p_message_instance->current = p_sequence->next;
932
933         return data;
934 }
935