Logo AND Algorithmique Numérique Distribuée

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