Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[Data description]
authormquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 21 Apr 2004 18:44:57 +0000 (18:44 +0000)
committermquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 21 Apr 2004 18:44:57 +0000 (18:44 +0000)
   - register init/exit functions within gras module mecanism
   - send/receive function.
   Convertion is not implemented, but short-cutted if not needed.
   struct/array elements are sent one by one (instead of block-wise), but
     nobody really cares (yet). Get a prototype before optimizing.
   - tests (using a file socket) for DD send/receive on:
     - base types: int, float
     - array: fixed size, string (ie ref to dynamic string)
     - structure: homogeneous, heterogeneous
     - chained list, graph with cycle
   Believe it or not, valgrind is not too unhappy with the results. The
    cycle happily segfaults, but the others are ok. And I'm sick of pointers
    for now.
 [Transport]
   [File plugin]
     - Bugfix when using a filename explicitely (instead of '-')

git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@82 48e7efb5-ca39-0410-a469-dd3cf9ba447f

21 files changed:
UNIMPLEMENTED [new file with mode: 0644]
changelog [new file with mode: 0644]
configure
cruft/doc/tmpl/comm_socks.sgml
include/datadesc.h
include/error.h
src/gras/DataDesc/cbps.c
src/gras/DataDesc/datadesc.c
src/gras/DataDesc/datadesc_interface.h
src/gras/DataDesc/datadesc_private.h
src/gras/DataDesc/ddt_create.c
src/gras/DataDesc/ddt_declare.c
src/gras/DataDesc/ddt_remote.c
src/gras/DataDesc/ddt_use.c
src/gras/Makefile.am
src/gras/Transport/transport_plugin_file.c
src/xbt/module.c
src/xbt/set.c
testsuite/Makefile.am
testsuite/gras/datadesc_usage.c [new file with mode: 0644]
testsuite/xbt/dynar_string.c

diff --git a/UNIMPLEMENTED b/UNIMPLEMENTED
new file mode 100644 (file)
index 0000000..6561e1d
--- /dev/null
@@ -0,0 +1,26 @@
+- gras_dd_convert_elm                    
+  gras_datadesc_cpy
+
+- callback en reception ??
+
+- Virer cat ignored
+
+gras_ddt_new_ignored : Pas portable (taille) => virer cat?
+
+gras_ddt_new_parse
+gras_ddt_new_from_nws
+
+
+
+gras_trp_select [SG]
+
+gras_trp_sg_socket_client
+gras_trp_sg_socket_server
+gras_trp_sg_socket_close
+gras_trp_sg_select
+gras_trp_sg_bloc_send
+gras_trp_sg_bloc_recv
+gras_trp_sg_flush
+
+tcp->incoming_socks
+sock specific tcp (buffsize) inutile
diff --git a/changelog b/changelog
new file mode 100644 (file)
index 0000000..a0910cf
--- /dev/null
+++ b/changelog
@@ -0,0 +1,42 @@
+2004-04-19 Martin Quinson  <martin.quinson@tuxfamily.org>
+ [Data description]
+   - register init/exit functions within gras module mecanism   
+   - send/receive function. 
+   Convertion is not implemented, but short-cutted if not needed.
+   struct/array elements are sent one by one (instead of block-wise), but
+     nobody really cares (yet). Get a prototype before optimizing.
+   - tests (using a file socket) for DD send/receive on:
+     - base types: int, float
+     - array: fixed size, string (ie ref to dynamic string)
+     - structure: homogeneous, heterogeneous
+     - chained list, graph with cycle
+   Believe it or not, valgrind is not too unhappy with the results. The
+    cycle happily segfaults, but the others are ok. And I'm sick of pointers
+    for now.
+ [Transport]
+   [File plugin] 
+     - Bugfix when using a filename explicitely (instead of '-')
+   [SG plugin]   
+     - Porting to new standards.
+   [SG select]   
+     - Porting to new standards.
+
+2004-04-09 Martin Quinson  <martin.quinson@tuxfamily.org>
+ [Transport plugins]
+   - factorize more code between RL and SG in socket creation
+   - Complete the implementation and tests of:
+     o TCP
+     o file (only in RL, and mainly for debugging)
+     
+     I lost 3 days to design a portable address resolver, and then decided
+       that the prototype mainly have to run on my box.
+     Addressing portability too early may be like optimizing too early :-/
+ [Tests]
+   - use gras_init in the Tests instead of the crappy parse_log_opt 
+     (the latter function is removed)
+ [Conditional execution]
+   - New functions: gras_if_RL/gras_if_SG (basic support for this)
+ [Code reorganisation]
+  - Get rid of libgrasutils.a since it makes more trouble than it solves.
+    Build examples against the RL library, since there is no way to disable
+    its creation for now.
index bfd4563..c5892ff 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 1.5 .
+# From configure.ac Revision: 1.6 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59 for GRAS 0.0.040304.
 #
index e918bf5..6bc7b7d 100644 (file)
@@ -21,10 +21,10 @@ Open/close sockets, and get info on peer.
 
 @host: 
 @Param2: 
-@bufSize: 
 @dst: 
 @Returns: 
 <!-- # Unused Parameters # -->
+@bufSize: 
 @sock: 
 
 
@@ -34,9 +34,10 @@ Open/close sockets, and get info on peer.
 </para>
 
 @Param1: 
-@bufSize: 
 @dst: 
 @Returns: 
+<!-- # Unused Parameters # -->
+@bufSize: 
 
 
 <!-- ##### FUNCTION gras_socket_close ##### -->
index a8cfa40..f50c9c4 100644 (file)
@@ -45,6 +45,12 @@ typedef struct s_gras_datadesc_type gras_datadesc_type_t;
  ***********************************************/
 long int gras_datadesc_get_id_from_name(const char *name);
 
+gras_error_t gras_datadesc_by_name(const char *name,
+                                  gras_datadesc_type_t **type);
+gras_error_t gras_datadesc_by_id  (long int code,
+                                  gras_datadesc_type_t **type);
+#define gras_datadesc_by_code(a,b) gras_datadesc_by_id(a,b)
+
 /*********************************************
  **** DataDesc callback persistent states ****
  *********************************************/
@@ -170,6 +176,11 @@ gras_datadesc_declare_array_cb(const char                      *name,
                               gras_datadesc_type_cb_void_t     post,
                               long int                        *code);
 
+/*******************************
+ **** About data convertion ****
+ *******************************/
+int gras_arch_selfid(void); /* ID of this arch */
+
 /****************************
  **** Parse C statements ****
  ****************************/
index 58c89ad..49b91bc 100644 (file)
@@ -52,11 +52,19 @@ typedef enum {
 
 /*@observer@*/ const char *gras_error_name(gras_error_t errcode);
 
-#define TRY(a) if ((errcode=a) != no_error) return errcode
+#define TRY(a) do {                                     \
+  if ((errcode=a) != no_error) {                        \
+     fprintf (stderr, "%s:%d: '%s' error raising...\n", \
+            __FILE__,__LINE__,                         \
+             gras_error_name(errcode));                 \
+     return errcode;                                    \
+  } } while (0)
+   
 #define TRYCATCH(a,b) if ((errcode=a) != no_error && errcode !=b) return errcode
 #define TRYFAIL(a) do {                                        \
   if ((errcode=a) != no_error) {                               \
-     fprintf(stderr,"Got '%s' error !\n",                      \
+     fprintf(stderr,"%s:%d: Got '%s' error !\n",               \
+            __FILE__,__LINE__,                                \
              gras_error_name(errcode));                        \
      fflush(stdout);                                           \
      abort();                                                  \
index 02e320e..1c801fc 100644 (file)
@@ -19,15 +19,42 @@ struct s_gras_dd_cbps {
   gras_dict_t  *space;
   gras_dynar_t *stack;
   gras_dynar_t *globals;
-
 };
 
+gras_error_t
+gras_dd_cbps_new(gras_dd_cbps_t **dst) {
+  gras_error_t errcode;
+  gras_dd_cbps_t *res;
+
+  if (!(res=malloc(sizeof(gras_dd_cbps_t))))
+    RAISE_MALLOC;
+
+  TRY(gras_dict_new(&(res->space)));
+  /* FIXME:leaking on content of dynars*/
+  TRY(gras_dynar_new(&(res->stack), sizeof(gras_dynar_t*), NULL));
+  TRY(gras_dynar_new(&(res->globals), sizeof(char*), NULL));
+
+  *dst = res;
+  return no_error;
+}
+
+void
+gras_dd_cbps_free(gras_dd_cbps_t **state) {
+
+  gras_dict_free ( &( (*state)->space   ) );
+  gras_dynar_free(    (*state)->stack     );
+  gras_dynar_free(    (*state)->globals   );
+
+  free(*state);
+  *state = NULL;
+}
+
 /**
  * gras_dd_cbps_push:
  *
- * Declare a new element in the PS, and give it a value. If an element of that name already exists, 
- * it becomes masked by the one given here, and will be seable again only after a pop to remove th
- * value this push adds.
+ * Declare a new element in the PS, and give it a value. If an element of that
+ * name already exists, it is masked by the one given here, and will b
+ * seeable again only after a pop to remove the value this push adds.
  */
 void
 gras_dd_cbps_push(gras_dd_cbps_t        *ps,
@@ -60,8 +87,9 @@ gras_dd_cbps_push(gras_dd_cbps_t        *ps,
 /**
  * gras_dd_cbps_pop:
  *
- * Retrieve an element from the PS, and remove it from the PS. If it's not present in the current block,
- * it will fail (with abort) and not search in upper blocks since this denotes a programmation error.
+ * Retrieve an element from the PS, and remove it from the PS. If it's not
+ * present in the current block, it will fail (with abort) and not search
+ * in upper blocks since this denotes a programmation error.
  */
 void *
 gras_dd_cbps_pop (gras_dd_cbps_t        *ps, 
@@ -112,11 +140,14 @@ gras_dd_cbps_pop (gras_dd_cbps_t        *ps,
 /**
  * gras_dd_cbps_set:
  *
- * Change the value of an element in the PS.  If it's not present in the current block, look in the upper ones.
- * If it's not present in any of them, look in the globals (FIXME: which no function of this API allows to set). 
+ * Change the value of an element in the PS.  
+ * If it's not present in the current block, look in the upper ones.
+ * If it's not present in any of them, look in the globals
+ *   (FIXME: which no function of this API allows to set). 
  * If not present there neither, the code may segfault (Oli?).
  *
- * Once a reference to an element of that name is found somewhere in the PS, its value is changed.
+ * Once a reference to an element of that name is found somewhere in the PS,
+ *   its value is changed.
  */
 void
 gras_dd_cbps_set (gras_dd_cbps_t        *ps,
@@ -149,9 +180,11 @@ gras_dd_cbps_set (gras_dd_cbps_t        *ps,
 /**
  * gras_dd_cbps_get:
  *
- * Get the value of an element in the PS without modifying it.
+ * Get the value of an element in the PS without modifying it. 
+ * (note that you get the content of the data struct and not a copy to it)
  * If it's not present in the current block, look in the upper ones.
- * If it's not present in any of them, look in the globals (FIXME: which no function of this API allows to set). 
+ * If it's not present in any of them, look in the globals
+ *   (FIXME: which no function of this API allows to set). 
  * If not present there neither, the code may segfault (Oli?).
  */
 void *
@@ -180,11 +213,13 @@ gras_dd_cbps_get (gras_dd_cbps_t        *ps,
  *
  * Begins a new block. 
  *
- * Blocks are usefull to remove a whole set of declarations you don't even know
+ * Blocks are usefull to remove a whole set of declarations you don't even know
  *
- * For example, they constitute a very elegent solution to recursive data structures. 
- * push/pop may be used in some cases for that, but if your recursive data struct contains 
- * other structs needing themselves callbacks, you have to use block_{begin,end} to do the trick.
+ * E.g., they constitute an elegent solution to recursive data structures. 
+ *
+ * push/pop may be used in some cases for that, but if your recursive data 
+ * struct contains other structs needing themselves callbacks, you have to
+ * use block_{begin,end} to do the trick.
  */
 
 void
@@ -211,7 +246,6 @@ gras_dd_cbps_block_end(gras_dd_cbps_t *ps) {
   gras_dynar_pop(ps->stack, &p_dynar);
   
   gras_dynar_foreach(p_dynar, cursor, name) {
-    /*  inline the code of  _gs_vars_pop(p_vars, name), which was used only once */
 
     gras_dynar_t            *p_dynar_elm    = NULL;
     gras_dd_cbps_elm_t      *p_elm          = NULL;
@@ -227,7 +261,7 @@ gras_dd_cbps_block_end(gras_dd_cbps_t *ps) {
     free(p_elm);
     free(name);
   }
-                                                                                
+  
   gras_dynar_free_container(p_dynar);
 }
 
index 984df70..1154629 100644 (file)
@@ -28,7 +28,9 @@ _strlen_cb(void                       *vars,
 /**
  * gras_datadesc_init:
  *
- * Initialize the datadesc module
+ * Initialize the datadesc module.
+ * FIXME: We assume that when neither signed nor unsigned is given, 
+ *    that means signed. To be checked by configure.
  **/
 void
 gras_datadesc_init(void) {
@@ -36,88 +38,129 @@ gras_datadesc_init(void) {
   gras_datadesc_type_t *ddt; /* What to add */
   gras_datadesc_type_t *elm; /* element of ddt when needed */
 
+  /* only initialize once */
+  if (gras_datadesc_set_local != NULL)
+    return;
+
   VERB0("Initializing DataDesc");
 
   TRYFAIL(gras_set_new(&gras_datadesc_set_local));
 
   TRYFAIL(gras_ddt_new_scalar("signed char", 
-                             gras_ddt_scalar_char, e_gras_dd_scalar_encoding_sint, 
+                             gras_ddt_scalar_char, 
+                             e_gras_dd_scalar_encoding_sint, 
+                             NULL, &ddt));
+  TRYFAIL(gras_ddt_new_scalar("char", 
+                             gras_ddt_scalar_char, 
+                             e_gras_dd_scalar_encoding_sint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
   TRYFAIL(gras_ddt_new_scalar("unsigned char", 
-                             gras_ddt_scalar_char, e_gras_dd_scalar_encoding_uint, 
+                             gras_ddt_scalar_char, 
+                             e_gras_dd_scalar_encoding_uint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
 
   TRYFAIL(gras_ddt_new_scalar("signed short int", 
-                             gras_ddt_scalar_short, e_gras_dd_scalar_encoding_sint, 
+                             gras_ddt_scalar_short, 
+                             e_gras_dd_scalar_encoding_sint, 
+                             NULL, &ddt));
+  TRYFAIL(gras_ddt_register(ddt));
+  TRYFAIL(gras_ddt_new_scalar("short int", 
+                             gras_ddt_scalar_short, 
+                             e_gras_dd_scalar_encoding_sint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
-
   TRYFAIL(gras_ddt_new_scalar("unsigned short int", 
-                             gras_ddt_scalar_short, e_gras_dd_scalar_encoding_uint, 
+                             gras_ddt_scalar_short, 
+                             e_gras_dd_scalar_encoding_uint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
 
   TRYFAIL(gras_ddt_new_scalar("signed int", 
-                             gras_ddt_scalar_int, e_gras_dd_scalar_encoding_sint, 
+                             gras_ddt_scalar_int, 
+                             e_gras_dd_scalar_encoding_sint, 
+                             NULL, &ddt));
+  TRYFAIL(gras_ddt_register(ddt));
+  TRYFAIL(gras_ddt_new_scalar("int", 
+                             gras_ddt_scalar_int, 
+                             e_gras_dd_scalar_encoding_sint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
-
   TRYFAIL(gras_ddt_new_scalar("unsigned int", 
-                             gras_ddt_scalar_int, e_gras_dd_scalar_encoding_uint, 
+                             gras_ddt_scalar_int, 
+                             e_gras_dd_scalar_encoding_uint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
 
   TRYFAIL(gras_ddt_new_scalar("signed long int", 
-                             gras_ddt_scalar_long, e_gras_dd_scalar_encoding_sint, 
+                             gras_ddt_scalar_long, 
+                             e_gras_dd_scalar_encoding_sint, 
+                             NULL, &ddt));
+  TRYFAIL(gras_ddt_register(ddt));
+  TRYFAIL(gras_ddt_new_scalar("long int", 
+                             gras_ddt_scalar_long, 
+                             e_gras_dd_scalar_encoding_sint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
-
   TRYFAIL(gras_ddt_new_scalar("unsigned long int", 
-                             gras_ddt_scalar_long, e_gras_dd_scalar_encoding_uint, 
+                             gras_ddt_scalar_long, 
+                             e_gras_dd_scalar_encoding_uint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
 
   TRYFAIL(gras_ddt_new_scalar("signed long long int", 
-                             gras_ddt_scalar_long_long, e_gras_dd_scalar_encoding_sint, 
+                             gras_ddt_scalar_long_long, 
+                             e_gras_dd_scalar_encoding_sint, 
+                             NULL, &ddt));
+  TRYFAIL(gras_ddt_register(ddt));
+  TRYFAIL(gras_ddt_new_scalar("long long int", 
+                             gras_ddt_scalar_long_long, 
+                             e_gras_dd_scalar_encoding_sint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
-
   TRYFAIL(gras_ddt_new_scalar("unsigned long long int", 
-                             gras_ddt_scalar_long_long, e_gras_dd_scalar_encoding_uint, 
+                             gras_ddt_scalar_long_long, 
+                             e_gras_dd_scalar_encoding_uint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
 
   TRYFAIL(gras_ddt_new_scalar("data pointer", 
-                             gras_ddt_scalar_pdata, e_gras_dd_scalar_encoding_uint, 
+                             gras_ddt_scalar_pdata, 
+                             e_gras_dd_scalar_encoding_uint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
-
   TRYFAIL(gras_ddt_new_scalar("function pointer", 
-                             gras_ddt_scalar_pfunc, e_gras_dd_scalar_encoding_uint, 
+                             gras_ddt_scalar_pfunc, 
+                             e_gras_dd_scalar_encoding_uint, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
 
   TRYFAIL(gras_ddt_new_scalar("float", 
-                             gras_ddt_scalar_float, e_gras_dd_scalar_encoding_float, 
+                             gras_ddt_scalar_float, 
+                             e_gras_dd_scalar_encoding_float, 
                              NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
   TRYFAIL(gras_ddt_new_scalar("double", 
-                             gras_ddt_scalar_float, e_gras_dd_scalar_encoding_float, 
+                             gras_ddt_scalar_float, 
+                             e_gras_dd_scalar_encoding_float, 
                              NULL,&ddt));
   TRYFAIL(gras_ddt_register(ddt));
 
-  TRYFAIL(gras_ddt_get_by_name("unsigned char",&elm));
-  TRYFAIL(gras_ddt_new_array("string", elm, 0, _strlen_cb, NULL, &ddt));
+  TRYFAIL(gras_datadesc_by_name("char",&elm));
+  TRYFAIL(gras_ddt_new_array("char array", elm, -1, _strlen_cb, NULL, &ddt));
+  TRYFAIL(gras_ddt_register(ddt));
+
+  elm=ddt;
+  TRYFAIL(gras_ddt_new_ref("string", elm, NULL, NULL, &ddt));
   TRYFAIL(gras_ddt_register(ddt));
 }
 
@@ -130,9 +173,7 @@ void
 gras_datadesc_exit(void) {
   VERB0("Exiting DataDesc");
   gras_set_free(&gras_datadesc_set_local);
+  gras_datadesc_set_local = NULL;
 }
 
 
-/***
- *** BOOTSTRAPING FUNCTIONS: known within GRAS only
- ***/
index 85fb1d7..2c81d88 100644 (file)
@@ -13,8 +13,6 @@
 #ifndef GRAS_DATADESC_INTERFACE_H
 #define GRAS_DATADESC_INTERFACE_H
 
-#include "gras_private.h"
-
 void gras_datadesc_init(void);
 void gras_datadesc_exit(void);
 
@@ -35,7 +33,8 @@ gras_datadesc_send(gras_socket_t *sock, gras_datadesc_type_t *type, void *src);
 
 /* Receive (and convert) stuff */
 gras_error_t
-gras_datadesc_recv(gras_socket_t *sock, gras_datadesc_type_t *type, void **dst);
+gras_datadesc_recv(gras_socket_t *sock, gras_datadesc_type_t *type, 
+                  int r_arch, void **dst);
 
 
 /* -- */
index be6971f..8eef386 100644 (file)
@@ -69,14 +69,14 @@ extern const gras_arch_sizes_t gras_arch_sizes[gras_arch_count];
 typedef enum e_gras_datadesc_type_category {
         e_gras_datadesc_type_cat_undefined = 0,
 
-        e_gras_datadesc_type_cat_scalar,
-        e_gras_datadesc_type_cat_struct,
-        e_gras_datadesc_type_cat_union,
-        e_gras_datadesc_type_cat_ref,       /* ref to an uniq element */
-        e_gras_datadesc_type_cat_array,
-        e_gras_datadesc_type_cat_ignored,
-
-        e_gras_datadesc_type_cat_invalid
+        e_gras_datadesc_type_cat_scalar = 1,
+        e_gras_datadesc_type_cat_struct = 2,
+        e_gras_datadesc_type_cat_union = 3,
+        e_gras_datadesc_type_cat_ref = 4,       /* ref to an uniq element */
+        e_gras_datadesc_type_cat_array = 5,
+        e_gras_datadesc_type_cat_ignored = 6,
+
+        e_gras_datadesc_type_cat_invalid = 7
 } gras_datadesc_type_category_t;
 
 
@@ -134,7 +134,7 @@ typedef struct s_gras_dd_cat_struct {
  * Specific fields of a union
  */
 typedef struct s_gras_dd_cat_union {
-  gras_datadesc_type_cb_int_t field_count;
+  gras_datadesc_type_cb_int_t selector;
   gras_dynar_t *fields; /* elm type = gras_dd_cat_field_t */
 } gras_dd_cat_union_t;
 
@@ -147,7 +147,7 @@ typedef struct s_gras_dd_cat_ref {
   int                          code;
 
   /* callback used to return the referenced type number  */
-  gras_datadesc_type_cb_int_t   discriminant;
+  gras_datadesc_type_cb_int_t   selector;
 } gras_dd_cat_ref_t;
 
 
@@ -284,5 +284,20 @@ gras_ddt_new_from_nws(const char           *name,
                      size_t                howmany,
                      gras_datadesc_type_t **dst);
 
+/****************************************************
+ * Callback persistant state constructor/destructor *
+ ****************************************************/
+gras_error_t
+gras_dd_cbps_new(gras_dd_cbps_t **dst);
+void
+gras_dd_cbps_free(gras_dd_cbps_t **state);
+
+/***************
+ * Convertions *
+ ***************/
+gras_error_t
+gras_dd_convert_elm(gras_datadesc_type_t *type,
+                   int r_arch, 
+                   void *src, void *dst);
 
 #endif /* GRAS_DATADESC_PRIVATE_H */
index 626b98c..1d871ce 100644 (file)
@@ -22,6 +22,9 @@ gras_ddt_new(const char            *name,
 
   memset(res, 0, sizeof(res));
   res->name = strdup(name);
+  res->name_len = strlen(name);
+  res->pre = NULL;
+  res->post = NULL;
   
   *dst=res;
   return no_error;
@@ -175,7 +178,7 @@ gras_ddt_new_struct_append(gras_datadesc_type_t            *struct_type,
   field->pre    = pre;
   field->post   = post;
   
-  TRY(gras_dynar_push(struct_type->category.struct_data.fields, field));
+  TRY(gras_dynar_push(struct_type->category.struct_data.fields, &field));
 
   for (arch=0; arch<gras_arch_count; arch ++) {
     struct_type->size[arch]            = field->offset[arch] + field_type->size[arch];
@@ -193,7 +196,7 @@ gras_ddt_new_struct_append(gras_datadesc_type_t            *struct_type,
  */
 gras_error_t 
 gras_ddt_new_union(const char                      *name,
-                  gras_datadesc_type_cb_int_t      field_count,
+                  gras_datadesc_type_cb_int_t      selector,
                   gras_datadesc_type_cb_void_t     post,
                   gras_datadesc_type_t           **dst) {
 
@@ -201,7 +204,7 @@ gras_ddt_new_union(const char                      *name,
   gras_datadesc_type_t *res;
   int arch;
 
-  gras_assert0(field_count,
+  gras_assert0(selector,
               "Attempt to creat an union without field_count function");
 
   TRY(gras_ddt_new(name,dst));
@@ -216,7 +219,7 @@ gras_ddt_new_union(const char                      *name,
   TRY(gras_dynar_new(&(res->category.union_data.fields),
                     sizeof(gras_dd_cat_field_t*),
                     &gras_dd_cat_field_free));
-  res->category.union_data.field_count = field_count;
+  res->category.union_data.selector = selector;
   res->pre                     = NULL;
   res->post                    = post;
 
@@ -254,7 +257,7 @@ gras_ddt_new_union_append(gras_datadesc_type_t            *union_type,
   field->pre    = pre;
   field->post   = post;
   
-  TRY(gras_dynar_push(union_type->category.union_data.fields, field));
+  TRY(gras_dynar_push(union_type->category.union_data.fields, &field));
 
   for (arch=0; arch<gras_arch_count; arch ++) {
     union_type->size[arch]        = max(union_type->size[arch], field_type->size[arch]);
@@ -273,31 +276,33 @@ gras_ddt_new_union_append(gras_datadesc_type_t            *union_type,
 gras_error_t 
 gras_ddt_new_ref(const char                      *name,
                 gras_datadesc_type_t            *referenced_type,
-                gras_datadesc_type_cb_int_t      discriminant,
+                gras_datadesc_type_cb_int_t      selector,
                 gras_datadesc_type_cb_void_t     post,
                 gras_datadesc_type_t           **dst) {
 
   gras_error_t errcode;
   gras_datadesc_type_t *res;
+  gras_datadesc_type_t *pointer_type;
   int arch;
 
-  gras_assert0(discriminant || referenced_type,
-              "Attempt to create a generic reference without discriminant");
+  gras_assert0(selector || referenced_type,
+              "Attempt to create a generic reference without selector");
 
   TRY(gras_ddt_new(name,dst));
   res=*dst;
 
-  /* FIXME: Size from bootstraping */
+  TRY(gras_datadesc_by_name("data pointer", &pointer_type));
+      
   for (arch=0; arch<gras_arch_count; arch ++) {
-    res->size[arch]                    = 0;
-    res->alignment[arch]               = 0;
-    res->aligned_size[arch]            = 0;
+    res->size[arch]                    = pointer_type->size[arch];
+    res->alignment[arch]               = pointer_type->alignment[arch];
+    res->aligned_size[arch]            = pointer_type->aligned_size[arch];
   }
 
   res->category_code           = e_gras_datadesc_type_cat_ref;
 
   res->category.ref_data.code         = referenced_type ? referenced_type->code : -1;
-  res->category.ref_data.discriminant = discriminant;
+  res->category.ref_data.selector = selector;
   res->pre                     = NULL;
   res->post                    = post;
 
index 2572e57..4001167 100644 (file)
@@ -34,10 +34,8 @@ gras_datadesc_declare_struct_add_name_cb(long int    struct_code,
   gras_datadesc_type_t *struct_type;
   gras_datadesc_type_t *field_type;
   
-  TRY(gras_set_get_by_id(gras_datadesc_set_local,struct_code,
-                        (gras_set_elm_t**)struct_type));
-  TRY(gras_set_get_by_name(gras_datadesc_set_local,field_type_name,
-                        (gras_set_elm_t**)field_type));
+  TRY(gras_datadesc_by_id(struct_code,&struct_type));
+  TRY(gras_datadesc_by_name(field_type_name,&field_type));
 
   TRY(gras_ddt_new_struct_append(struct_type,
                                 field_name,  field_type,
@@ -55,10 +53,8 @@ gras_datadesc_declare_struct_add_code_cb(long int    struct_code,
   gras_datadesc_type_t *struct_type;
   gras_datadesc_type_t *field_type;
   
-  TRY(gras_set_get_by_id(gras_datadesc_set_local,struct_code,
-                        (gras_set_elm_t**)struct_type));
-  TRY(gras_set_get_by_id(gras_datadesc_set_local,field_code,
-                        (gras_set_elm_t**)field_type));
+  TRY(gras_datadesc_by_id(struct_code,&struct_type));
+  TRY(gras_datadesc_by_id(field_code, &field_type));
 
   TRY(gras_ddt_new_struct_append(struct_type,
                                 field_name,  field_type,
@@ -90,10 +86,8 @@ gras_datadesc_declare_union_add_name_cb(long int                      union_code
   gras_datadesc_type_t *union_type;
   gras_datadesc_type_t *field_type;
   
-  TRY(gras_set_get_by_id(gras_datadesc_set_local,union_code,
-                        (gras_set_elm_t**)union_type));
-  TRY(gras_set_get_by_name(gras_datadesc_set_local,field_type_name,
-                        (gras_set_elm_t**)field_type));
+  TRY(gras_datadesc_by_id  (union_code,      &union_type));
+  TRY(gras_datadesc_by_name(field_type_name, &field_type));
 
   TRY(gras_ddt_new_union_append(union_type,
                                field_name,  field_type,
@@ -111,10 +105,8 @@ gras_datadesc_declare_union_add_code_cb(long int                      union_code
   gras_datadesc_type_t *union_type;
   gras_datadesc_type_t *field_type;
   
-  TRY(gras_set_get_by_id(gras_datadesc_set_local,union_code,
-                        (gras_set_elm_t**)union_type));
-  TRY(gras_set_get_by_id(gras_datadesc_set_local,field_code,
-                        (gras_set_elm_t**)field_type));
+  TRY(gras_datadesc_by_id(union_code, &union_type));
+  TRY(gras_datadesc_by_id(field_code, &field_type));
 
   TRY(gras_ddt_new_union_append(union_type,
                                field_name,  field_type,
index 6d45998..b3c72cb 100644 (file)
@@ -45,21 +45,51 @@ gras_error_t gras_ddt_register(gras_datadesc_type_t *type) {
 }
 
 /**
- * gras_ddt_get_by_name:
+ * gras_datadesc_by_name:
  *
  * Retrieve a type from its name
  */
-gras_error_t gras_ddt_get_by_name(const char            *name,
-                                 gras_datadesc_type_t **type) {
-  return gras_set_get_by_name(gras_datadesc_set_local,name,(gras_set_elm_t**)type);
+gras_error_t gras_datadesc_by_name(const char            *name,
+                                  gras_datadesc_type_t **type) {
+  return gras_set_get_by_name(gras_datadesc_set_local,
+                             name,(gras_set_elm_t**)type);
 }
 
 /**
- * gras_ddt_get_by_code:
+ * gras_datadesc_by_id:
  *
- * Retrieve a type from its name
+ * Retrieve a type from its code
+ */
+gras_error_t gras_datadesc_by_id(long int               code,
+                                gras_datadesc_type_t **type) {
+  return gras_set_get_by_id(gras_datadesc_set_local,
+                           code,(gras_set_elm_t**)type);
+}
+
+/**
+ * gras_dd_convert_elm:
+ *
+ * Convert the element described by @type comming from architecture @r_arch.
+ * The data to be converted is stored in @src, and is to be stored in @dst.
+ * Both pointers may be the same location if no resizing is needed.
+ */
+gras_error_t
+gras_dd_convert_elm(gras_datadesc_type_t *type,
+                   int r_arch, 
+                   void *src, void *dst) {
+
+  if (r_arch != GRAS_THISARCH) 
+    RAISE_UNIMPLEMENTED;
+
+  return no_error;
+}
+
+/**
+ * gras_arch_selfid:
+ *
+ * returns the ID of the architecture the process is running on
  */
-gras_error_t gras_ddt_get_by_code(int                    code,
-                                 gras_datadesc_type_t **type) {
-  return gras_set_get_by_id(gras_datadesc_set_local,code,(gras_set_elm_t**)type);
+int
+gras_arch_selfid(void) {
+  return GRAS_THISARCH;
 }
index f4f6c34..ebad127 100644 (file)
 
 #include "DataDesc/datadesc_private.h"
 
-//GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(use,DataDesc);
+GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(use,DataDesc);
+
+static const char *gras_datadesc_cat_names[9] = { 
+  "undefined", 
+  "scalar", "struct", "union", "ref", "array", "ignored",
+  "invalid"};
+
+static gras_datadesc_type_t *int_type = NULL;
+static gras_datadesc_type_t *pointer_type = NULL;    
+static gras_error_t gras_dd_send_int(gras_socket_t *sock,             int  i);
+static gras_error_t gras_dd_recv_int(gras_socket_t *sock, int r_arch, int *i);
+
+static gras_error_t
+gras_dd_alloc_ref(gras_dict_t *refs,  long int     size,
+                 char       **r_ref, long int     r_len,
+                 char       **l_ref);
+static int 
+gras_dd_is_r_null(char **r_ptr, long int length);
+
+static gras_error_t 
+gras_datadesc_send_rec(gras_socket_t        *sock,
+                      gras_dd_cbps_t       *state,
+                      gras_dict_t          *refs,
+                      gras_datadesc_type_t *type, 
+                      char                 *data);
+static gras_error_t
+gras_datadesc_recv_rec(gras_socket_t        *sock, 
+                      gras_dd_cbps_t       *state,
+                      gras_dict_t          *refs,
+                      gras_datadesc_type_t *type,
+                      int                   r_arch,
+                      char                **r_data,
+                      long int              r_lgr,
+                      char                **dst);
+
+
+static gras_error_t
+gras_dd_send_int(gras_socket_t *sock,int i) {
+  gras_error_t errcode;
+
+  if (!int_type) 
+    TRY(gras_datadesc_by_name("int", &int_type));
+  
+  DEBUG1("send_int(%d)",i);
+  return gras_trp_chunk_send(sock, (char*)&i, int_type->size[GRAS_THISARCH]);
+}
+
+static gras_error_t
+gras_dd_recv_int(gras_socket_t *sock, int r_arch, int *i) {
+  gras_error_t errcode;
+
+  if (!int_type) 
+    TRY(gras_datadesc_by_name("int", &int_type));
+
+  if (int_type->size[GRAS_THISARCH] >= int_type->size[r_arch]) {
+    TRY(gras_trp_chunk_recv(sock, (char*)i, int_type->size[r_arch]));
+    TRY(gras_dd_convert_elm(int_type,r_arch, i,i));
+  } else {
+    void *ptr = NULL;
+    ptr = malloc((size_t)int_type->size[r_arch]);
+    TRY(gras_trp_chunk_recv(sock, (char*)ptr, int_type->size[r_arch]));
+    TRY(gras_dd_convert_elm(int_type,r_arch, ptr,i));
+    free(ptr);
+  }
+  DEBUG1("recv_int(%d)",*i);
+
+  return no_error;
+}
+
+/*
+ * Note: here we suppose that the remote NULL is a sequence 
+ *       of 'length' bytes set to 0.
+ * FIXME: Check in configure?
+ */
+static int 
+gras_dd_is_r_null(char **r_ptr, long int length) {
+  int i;
+
+  for (i=0; i<length; i++) {
+    if ( ((unsigned char*)r_ptr) [i]) {
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+static gras_error_t
+gras_dd_alloc_ref(gras_dict_t *refs,
+                 long int     size,
+                 char       **r_ref,
+                 long int     r_len, /* pointer_type->size[r_arch] */
+                 char       **l_ref) {
+  char *l_data = NULL;
+  gras_error_t errcode;
+
+  gras_assert1(size>0,"Cannot allocate %d bytes!", size);
+  if (! (l_data = malloc((size_t)size)) )
+    RAISE_MALLOC;
+
+  *l_ref = l_data;
+  DEBUG2("l_data=%p, &l_data=%p",l_data,&l_data);
+
+  DEBUG3("alloc_ref: r_ref=%p; *r_ref=%p, r_len=%d",
+        r_ref, r_ref?*r_ref:NULL, r_len);
+  if (r_ref && !gras_dd_is_r_null( r_ref, r_len)) {
+    void *ptr = malloc(sizeof(void *));
+    if (!ptr)
+      RAISE_MALLOC;
+    //    memcpy(ptr,&l_data, sizeof(void *));
+    memcpy(ptr,l_ref, sizeof(void *));
+
+    DEBUG2("Insert %p under %p",*(void**)ptr, *(void**)r_ref);
+    /* FIXME: Leaking on the ptr. Do I really need to copy it? */
+    TRY(gras_dict_insert_ext(refs,(const char *) r_ref, r_len, ptr, NULL));
+  }
+  return no_error;
+}
 
 /**
  * gras_datadesc_get_id_from_name:
@@ -23,7 +140,7 @@ gras_datadesc_get_id_from_name(const char *name) {
   gras_error_t errcode;
   gras_datadesc_type_t *type;
 
-  errcode = gras_ddt_get_by_name(name,&type);
+  errcode = gras_datadesc_by_name(name,&type);
   if (errcode != no_error)
     return -1;
   return type->code;
@@ -48,14 +165,20 @@ int gras_datadesc_type_cmp(const gras_datadesc_type_t *d1,
   if (!d1 && !d2) return 0;
   if ( d1 && !d2) return -1;
 
-  if (d1->size          != d2->size     )     return d1->size          > d2->size         ? 1 : -1;
-  if (d1->alignment     != d2->alignment)     return d1->alignment     > d2->alignment    ? 1 : -1;
-  if (d1->aligned_size  != d2->aligned_size)  return d1->aligned_size  > d2->aligned_size ? 1 : -1;
+  if      (d1->size          != d2->size     )     
+    return d1->size          >  d2->size         ? 1 : -1;
+  if      (d1->alignment     != d2->alignment)     
+    return d1->alignment     >  d2->alignment    ? 1 : -1;
+  if      (d1->aligned_size  != d2->aligned_size)  
+    return d1->aligned_size  >  d2->aligned_size ? 1 : -1;
 
-  if (d1->category_code != d2->category_code) return d1->category_code > d2->category_code ? 1 : -1;
+  if      (d1->category_code != d2->category_code) 
+    return d1->category_code >  d2->category_code ? 1 : -1;
 
-  if (d1->pre           != d2->pre)           return d1->pre           > d2->pre ? 1 : -1;
-  if (d1->post          != d2->post)          return d1->post          > d2->post ? 1 : -1;
+  if      (d1->pre          != d2->pre)           
+    return d1->pre          >  d2->pre ? 1 : -1;
+  if      (d1->post         != d2->post)
+    return d1->post          > d2->post ? 1 : -1;
 
   switch (d1->category_code) {
   case e_gras_datadesc_type_cat_scalar:
@@ -73,8 +196,8 @@ int gras_datadesc_type_cmp(const gras_datadesc_type_t *d1,
     gras_dynar_foreach(d1->category.struct_data.fields, cpt, field1) {
       
       gras_dynar_get(d2->category.struct_data.fields, cpt, field2);
-      gras_ddt_get_by_code(field1->code,&field_desc_1); /* FIXME: errcode ignored */
-      gras_ddt_get_by_code(field2->code,&field_desc_2);
+      gras_datadesc_by_id(field1->code,&field_desc_1); /* FIXME: errcode ignored */
+      gras_datadesc_by_id(field2->code,&field_desc_2);
       ret = gras_datadesc_type_cmp(field_desc_1,field_desc_2);
       if (ret)
        return ret;
@@ -83,8 +206,8 @@ int gras_datadesc_type_cmp(const gras_datadesc_type_t *d1,
     break;
     
   case e_gras_datadesc_type_cat_union:
-    if (d1->category.union_data.field_count != d2->category.union_data.field_count
-      return d1->category.union_data.field_count > d2->category.union_data.field_count ? 1 : -1;
+    if (d1->category.union_data.selector != d2->category.union_data.selector
+      return d1->category.union_data.selector > d2->category.union_data.selector ? 1 : -1;
     
     if (gras_dynar_length(d1->category.union_data.fields) != 
        gras_dynar_length(d2->category.union_data.fields))
@@ -95,8 +218,8 @@ int gras_datadesc_type_cmp(const gras_datadesc_type_t *d1,
     gras_dynar_foreach(d1->category.union_data.fields, cpt, field1) {
       
       gras_dynar_get(d2->category.union_data.fields, cpt, field2);
-      gras_ddt_get_by_code(field1->code,&field_desc_1); /* FIXME: errcode ignored */
-      gras_ddt_get_by_code(field2->code,&field_desc_2);
+      gras_datadesc_by_id(field1->code,&field_desc_1); /* FIXME: errcode ignored */
+      gras_datadesc_by_id(field2->code,&field_desc_2);
       ret = gras_datadesc_type_cmp(field_desc_1,field_desc_2);
       if (ret)
        return ret;
@@ -106,8 +229,8 @@ int gras_datadesc_type_cmp(const gras_datadesc_type_t *d1,
     
     
   case e_gras_datadesc_type_cat_ref:
-    if (d1->category.ref_data.discriminant != d2->category.ref_data.discriminant
-      return d1->category.ref_data.discriminant > d2->category.ref_data.discriminant ? 1 : -1;
+    if (d1->category.ref_data.selector != d2->category.ref_data.selector
+      return d1->category.ref_data.selector > d2->category.ref_data.selector ? 1 : -1;
     
     if (d1->category.ref_data.code != d2->category.ref_data.code) 
       return d1->category.ref_data.code > d2->category.ref_data.code ? 1 : -1;
@@ -138,31 +261,439 @@ int gras_datadesc_type_cmp(const gras_datadesc_type_t *d1,
 /**
  * gras_datadesc_cpy:
  *
- * Copy the data pointed by src and described by type to a new location, and store a pointer to it in dst.
+ * Copy the data pointed by src and described by type 
+ * to a new location, and store a pointer to it in dst.
  *
  */
-gras_error_t gras_datadesc_cpy(gras_datadesc_type_t *type, void *src, void **dst) {
+gras_error_t gras_datadesc_cpy(gras_datadesc_type_t *type, 
+                              void *src, 
+                              void **dst) {
   RAISE_UNIMPLEMENTED;
 }
 
+static gras_error_t 
+gras_datadesc_send_rec(gras_socket_t        *sock,
+                      gras_dd_cbps_t       *state,
+                      gras_dict_t          *refs,
+                      gras_datadesc_type_t *type, 
+                      char                 *data) {
+
+  gras_error_t          errcode;
+  int                   cpt;
+  gras_datadesc_type_t *sub_type; /* type on which we recurse */
+  
+  VERB2("Send a %s (%s)", 
+       type->name, gras_datadesc_cat_names[type->category_code]);
+
+  if (type->pre) {
+    type->pre(state,type,data);
+  }
+
+  switch (type->category_code) {
+  case e_gras_datadesc_type_cat_scalar:
+    TRY(gras_trp_chunk_send(sock, data, type->size[GRAS_THISARCH]));
+    break;
+
+  case e_gras_datadesc_type_cat_struct: {
+    gras_dd_cat_struct_t  struct_data;
+    gras_dd_cat_field_t  *field;
+    char                 *field_data;
+
+    struct_data = type->category.struct_data;
+    VERB1(">> Send all fields of the structure %s",type->name);
+    gras_dynar_foreach(struct_data.fields, cpt, field) {
+      field_data = data;
+      field_data += field->offset[GRAS_THISARCH];
+      
+      TRY(gras_datadesc_by_id(field->code, &sub_type));
+      
+      if (field->pre)
+       field->pre(state,sub_type,field_data);
+      
+      TRY(gras_datadesc_send_rec(sock,state,refs,sub_type, field_data));
+      
+      if (field->post)
+       field->post(state,sub_type,field_data);
+    }
+    VERB1("<< Sent all fields of the structure %s", type->name);
+    
+    break;
+  }
+
+  case e_gras_datadesc_type_cat_union: {
+    gras_dd_cat_union_t    union_data;
+    gras_dd_cat_field_t   *field;
+    int                    field_num;
+    
+    union_data = type->category.union_data;
+    
+    /* retrieve the field number */
+    field_num = union_data.selector(state, type, data);
+    
+    gras_assert1(field_num > 0,
+                "union field selector of %s gave a negative value", 
+                type->name);
+    
+    gras_assert3(field_num < gras_dynar_length(union_data.fields),
+        "union field selector of %s returned %d but there is only %d fields", 
+                type->name, field_num, gras_dynar_length(union_data.fields));
+
+    /* Send the field number */
+    TRY(gras_dd_send_int(sock, field_num));
+    
+    /* Send the content */
+    gras_dynar_get(union_data.fields, field_num, field);
+    TRY(gras_datadesc_by_id(field->code, &sub_type));
+    
+    if (field->pre)
+      field->pre(state,sub_type,data);
+    
+    TRY(gras_datadesc_send_rec(sock,state,refs, sub_type, data));
+      
+    if (field->post)
+      field->post(state,sub_type,data);
+    
+    break;
+  }
+    
+  case e_gras_datadesc_type_cat_ref: {
+    gras_dd_cat_ref_t      ref_data;
+    int                    ref_code;
+
+    void                 **ref=(void**)data;
+    void *dummy;
+    
+    ref_data = type->category.ref_data;
+    
+    /* Detect the referenced type and send it to peer if needed */
+    ref_code = ref_data.code;
+    if (ref_code < 0) {
+      ref_code = ref_data.selector(state,type,data);
+      TRY(gras_dd_send_int(sock, ref_code));
+    }
+    
+    /* Send the actual value of the pointer for cycle handling */
+    if (!pointer_type)
+      TRY(gras_datadesc_by_name("data pointer", &pointer_type));
+    TRY(gras_trp_chunk_send(sock, (char*)data,
+                           pointer_type->size[GRAS_THISARCH]));
+    
+    /* Send the pointed data only if not already sent */
+    if (*(void**)data == NULL) {
+      VERB0("Not sending NULL referenced data");
+      break;
+    }
+    errcode = gras_dict_retrieve_ext(refs,(char*)ref, sizeof(void*), &dummy);
+    if (errcode == mismatch_error) {
+      VERB1("Sending data referenced at %p", *ref);
+      TRY(gras_dict_insert_ext(refs, (char*)ref, sizeof(void*), ref, NULL));
+      TRY(gras_datadesc_by_id(ref_code, &sub_type));
+      TRY(gras_datadesc_send_rec(sock,state,refs, sub_type, *ref));
+      
+    } else if (errcode == no_error) {
+      VERB1("Not sending data referenced at %p (already done)", *ref);
+    } else {
+      return errcode;
+    }
+    
+    break;
+  }
+
+  case e_gras_datadesc_type_cat_array: {
+    gras_dd_cat_array_t    array_data;
+    long int               count;
+    char                  *ptr=data;
+    long int               elm_size;
+    
+    array_data = type->category.array_data;
+    
+    /* determine and send the element count */
+    count = array_data.fixed_size;
+    if (count <= 0) {
+      count = array_data.dynamic_size(state,type,data);
+      gras_assert1(count >=0,
+                  "Invalid (negative) array size for type %s",type->name);
+      TRY(gras_dd_send_int(sock, count));
+    }
+    
+    /* send the content */
+    TRY(gras_datadesc_by_id(array_data.code, &sub_type));
+    elm_size = sub_type->aligned_size[GRAS_THISARCH];
+    for (cpt=0; cpt<count; cpt++) {
+      TRY(gras_datadesc_send_rec(sock,state,refs, sub_type, ptr));
+      ptr += elm_size;
+    }
+    break;
+  }
+
+  default:
+    gras_assert0(0, "Invalid type");
+  }
+
+  if (type->post) {
+    type->post(state,type,data);
+  }
+
+  return no_error;
+}
+
 /**
  * gras_datadesc_send:
  *
  * Copy the data pointed by src and described by type to the socket
  *
  */
-gras_error_t gras_datadesc_send(gras_socket_t *sock, gras_datadesc_type_t *type, void *src) {
+gras_error_t gras_datadesc_send(gras_socket_t *sock, 
+                               gras_datadesc_type_t *type, 
+                               void *src) {
 
-  RAISE_UNIMPLEMENTED;
+  gras_error_t errcode;
+  gras_dd_cbps_t *state = NULL;
+  gras_dict_t    *refs; /* all references already sent */
+  TRY(gras_dict_new(&refs));
+  TRY(gras_dd_cbps_new(&state));
+
+  errcode = gras_datadesc_send_rec(sock,state,refs,type,(char*)src);
+
+  gras_dict_free(&refs);
+  gras_dd_cbps_free(&state);
+
+  return errcode;
+}
+
+/**
+ * gras_datadesc_recv_rec:
+ *
+ * Do the data reception job recursively.
+ */
+gras_error_t
+gras_datadesc_recv_rec(gras_socket_t        *sock, 
+                      gras_dd_cbps_t       *state,
+                      gras_dict_t          *refs,
+                      gras_datadesc_type_t *type,
+                      int                   r_arch,
+                      char                **r_data,
+                      long int              r_lgr,
+                      char                **dst) {
+
+  gras_error_t          errcode;
+  char                 *l_data = *dst; /* dereference to avoid typo */
+  int                   cpt;
+  gras_datadesc_type_t *sub_type;
+
+  VERB1("Recv a %s", type->name);
+
+  switch (type->category_code) {
+  case e_gras_datadesc_type_cat_scalar:
+    if (!l_data) {
+      TRY(gras_dd_alloc_ref(refs,type->size[GRAS_THISARCH],r_data,r_lgr, dst));
+      l_data = *dst;
+    } 
+    
+    if (type->size[GRAS_THISARCH] >= type->size[r_arch]) {
+      TRY(gras_trp_chunk_recv(sock, (char*)l_data, type->size[r_arch]));
+      TRY(gras_dd_convert_elm(type,r_arch, l_data,l_data));
+    } else {
+      void *ptr = NULL;
+      ptr = malloc((size_t)type->size[r_arch]);
+      TRY(gras_trp_chunk_recv(sock, (char*)ptr, type->size[r_arch]));
+      TRY(gras_dd_convert_elm(type,r_arch, ptr,l_data));
+      free(ptr);
+    }
+    break;
+
+  case e_gras_datadesc_type_cat_struct: {
+    gras_dd_cat_struct_t   struct_data;
+    gras_dd_cat_field_t   *field;
+
+    struct_data = type->category.struct_data;
+
+    if (!l_data) {
+      TRY(gras_dd_alloc_ref(refs,type->size[GRAS_THISARCH],r_data,r_lgr, dst));
+      l_data = *dst;
+    } 
+
+    VERB1(">> Receive all fields of the structure %s",type->name);
+    gras_dynar_foreach(struct_data.fields, cpt, field) {
+      char                 *field_data = l_data + field->offset[GRAS_THISARCH];
+
+      TRY(gras_datadesc_by_id(field->code, &sub_type));
+
+      TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
+                                r_arch,NULL,0,
+                                &field_data));
+    }
+    VERB1("<< Received all fields of the structure %s", type->name);
+    
+    break;
+  }
+
+  case e_gras_datadesc_type_cat_union: {
+    gras_dd_cat_union_t    union_data;
+    gras_dd_cat_field_t   *field;
+    int                    field_num;
+
+    union_data = type->category.union_data;
+
+    if (!l_data) {
+      TRY(gras_dd_alloc_ref(refs,type->size[GRAS_THISARCH],r_data,r_lgr, dst));
+      l_data = *dst;
+    } 
+
+    /* retrieve the field number */
+    TRY(gras_dd_recv_int(sock, r_arch, &field_num));
+    if (field_num < 0)
+      RAISE1(mismatch_error,
+            "Received union field for %s is negative", type->name);
+    if (field_num < gras_dynar_length(union_data.fields)) 
+      RAISE3(mismatch_error,
+            "Received union field for %s is %d but there is only %d fields", 
+            type->name, field_num, gras_dynar_length(union_data.fields));
+    
+    /* Recv the content */
+    gras_dynar_get(union_data.fields, field_num, field);
+    TRY(gras_datadesc_by_id(field->code, &sub_type));
+    
+    TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
+                              r_arch,NULL,0,
+                              dst));
+    break;
+  }
+
+  case e_gras_datadesc_type_cat_ref: {
+    char             **r_ref = NULL;
+    char             **l_ref = NULL;
+    gras_dd_cat_ref_t  ref_data;
+    int                ref_code;
+    
+    ref_data = type->category.ref_data;
+
+    /* Get the referenced type locally or from peer */
+    ref_code = ref_data.code;
+    if (ref_code < 0) 
+      TRY(gras_dd_recv_int(sock, r_arch, &ref_code));
+
+    /* Get the actual value of the pointer for cycle handling */
+    if (!pointer_type)
+      TRY(gras_datadesc_by_name("data pointer", &pointer_type));
+
+    if (! (r_ref = malloc((size_t)pointer_type->size[r_arch])) )
+      RAISE_MALLOC;
+    TRY(gras_trp_chunk_recv(sock, (char*)r_ref,
+                           pointer_type->size[r_arch]));
+
+    if (!l_data) {
+      TRY(gras_dd_alloc_ref(refs,type->size[GRAS_THISARCH],r_data,r_lgr, dst));
+      l_data = *dst;
+    } 
+
+    /* Receive the pointed data only if not already sent */
+    if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
+      VERB1("Not receiving data remotely referenced at %p since it's NULL",
+           *(void **)r_ref);
+      *(void**)l_data = NULL;
+      break;
+    }
+    errcode = gras_dict_retrieve_ext(refs,
+                                    (char*)r_ref, pointer_type->size[r_arch],
+                                    (void**)&l_ref);
+
+
+    if (errcode == mismatch_error) {
+      void *l_referenced=NULL;
+      VERB1("Receiving data remotely referenced at %p", *(void**)r_ref);
+
+      TRY(gras_datadesc_by_id(ref_code, &sub_type));
+      //      DEBUG2("l_ref= %p; &l_ref=%p",l_referenced,&l_referenced);
+      TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
+                                r_arch,r_ref,pointer_type->size[r_arch],
+                                (char**)&l_referenced));
+      *(void**)l_data=l_referenced;
+      
+    } else if (errcode == no_error) {
+      VERB1("NOT receiving data remotely referenced at %p (already done). ",
+           *(void**)r_ref);
+
+      VERB2("l_ref=%p; *l_ref=%p", l_ref,*l_ref);
+
+      *(void**)l_data=*l_ref;
+
+    } else {
+      return errcode;
+    }
+    VERB1("*l_data=%p",*(void**)l_data);
+    break;
+  }
+
+  case e_gras_datadesc_type_cat_array: {
+    gras_dd_cat_array_t    array_data;
+    int       count;
+    char     *ptr;
+    long int  elm_size;
+
+    array_data = type->category.array_data;
+    /* determine element count locally or from peer */
+    count = array_data.fixed_size;
+    if (count <= 0)
+      TRY(gras_dd_recv_int(sock, r_arch, &count));
+    if (count < 0)
+      RAISE1(mismatch_error,
+            "Invalid (negative) array size for type %s",type->name);
+
+    /* receive the content */
+    TRY(gras_datadesc_by_id(array_data.code, &sub_type));
+    elm_size = sub_type->aligned_size[GRAS_THISARCH];
+    
+    if (!l_data) {
+      TRY(gras_dd_alloc_ref(refs,elm_size*count,r_data,r_lgr, dst));
+      l_data = *dst;
+    } 
+
+    ptr = l_data;
+    for (cpt=0; cpt<count; cpt++) {
+      TRY(gras_datadesc_recv_rec(sock,state,refs, sub_type,
+                                r_arch, NULL, 0, &ptr));
+      ptr += elm_size;
+    }
+    break;
+  }
+        
+  default:
+    gras_assert0(0, "Invalid type");
+  }
+  
+  return no_error;
 }
 
 /**
  * gras_datadesc_recv:
  *
- * Get an instance of the datatype described by @type from the @socket, and store a pointer to it in @dst
+ * Get an instance of the datatype described by @type from the @socket, 
+ * and store a pointer to it in @dst
  *
  */
 gras_error_t
-gras_datadesc_recv(gras_socket_t *sock, gras_datadesc_type_t *type, void **dst) {
-  RAISE_UNIMPLEMENTED;
+gras_datadesc_recv(gras_socket_t *sock, 
+                  gras_datadesc_type_t *type, 
+                  int r_arch,
+                  void **dst) {
+
+  gras_error_t errcode;
+  gras_dd_cbps_t *state = NULL; /* callback persistent state */
+  gras_dict_t    *refs;         /* all references already sent */
+
+  TRY(gras_dict_new(&refs));
+  TRY(gras_dd_cbps_new(&state));
+  if (*dst) 
+    VERB0("'*dst' not NULL in datadesc_recv. Data to be copied there without malloc");
+
+  errcode = gras_datadesc_recv_rec(sock, state, refs, type, 
+                                  r_arch, NULL, 0,
+                                  (char **) dst);
+
+  gras_dict_free(&refs);
+  gras_dd_cbps_free(&state);
+
+  return errcode;
 }
index 27ed9ed..edc7ff4 100644 (file)
@@ -34,7 +34,8 @@ COMMON_S=\
   DataDesc/ddt_create.c          DataDesc/ddt_declare.c \
   DataDesc/ddt_remote.c          DataDesc/ddt_use.c     \
   DataDesc/cbps.c                DataDesc/datadesc.c    \
-  DataDesc/datadesc_interface.h  DataDesc/datadesc_private.h
+  DataDesc/datadesc_interface.h  DataDesc/datadesc_private.h 
+
 
 #  DataDesc/datadesc.c                               \
 #  DataDesc/tools.c                                  \
index 74774ae..bb3a4c3 100644 (file)
@@ -105,13 +105,8 @@ gras_socket_client_from_file(const char*path,
   TRY(gras_trp_plugin_get_by_name("file",&trp));
   (*dst)->plugin=trp;
 
-  DEBUG3("in=%c out=%c accept=%c",
-       (*dst)->incoming?'y':'n', 
-       (*dst)->outgoing?'y':'n',
-       (*dst)->accepting?'y':'n');
-
   if (strcmp("-", path)) {
-    (*dst)->sd = open(path, O_RDONLY );
+    (*dst)->sd = open(path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP );
     
     if ( (*dst)->sd < 0) {
       RAISE2(system_error,
@@ -122,11 +117,12 @@ gras_socket_client_from_file(const char*path,
     (*dst)->sd = 1; /* stdout */
   }
 
-  DEBUG4("sd=%d in=%c out=%c accept=%c",
-       (*dst)->sd,
-       (*dst)->incoming?'y':'n', 
-       (*dst)->outgoing?'y':'n',
-       (*dst)->accepting?'y':'n');
+  DEBUG5("sock_client_from_file(%s): sd=%d in=%c out=%c accept=%c",
+        path,
+        (*dst)->sd,
+        (*dst)->incoming?'y':'n', 
+        (*dst)->outgoing?'y':'n',
+        (*dst)->accepting?'y':'n');
   /* register socket */
   errcode = gras_dynar_push(_gras_trp_sockets,dst);
   if (errcode != no_error) {
@@ -161,7 +157,7 @@ gras_socket_server_from_file(const char*path,
 
 
   if (strcmp("-", path)) {
-    (*dst)->sd = open(path, O_WRONLY );
+    (*dst)->sd = open(path, O_RDONLY );
 
     if ( (*dst)->sd < 0) {
       RAISE2(system_error,
@@ -200,14 +196,14 @@ void gras_trp_file_close(gras_socket_t *sock){
   } else if (sock->sd == 1) {
     DEBUG0("Do not close stdout");
   } else {
-    DEBUG1("close file connection %d\n", sock->sd);
+    DEBUG1("close file connection %d", sock->sd);
 
     /* forget about the socket */
     FD_CLR(sock->sd, &(specific->incoming_socks));
 
     /* close the socket */
     if(close(sock->sd) < 0) {
-      WARNING2("error while closing file %d: %s\n", 
+      WARNING2("error while closing file %d: %s", 
               sock->sd, strerror(errno));
     }
   }
@@ -228,8 +224,8 @@ gras_trp_file_chunk_send(gras_socket_t *sock,
   while (size) {
     int status = 0;
     
+    DEBUG3("write(%d, %p, %ld);", sock->sd, data, (size_t)size);
     status = write(sock->sd, data, (size_t)size);
-    DEBUG3("write(%d, %p, %ld);\n", sock->sd, data, size);
     
     if (status == -1) {
       RAISE4(system_error,"write(%d,%p,%d) failed: %s",
@@ -265,7 +261,7 @@ gras_trp_file_chunk_recv(gras_socket_t *sock,
     int status = 0;
     
     status = read(sock->sd, data, (size_t)size);
-    DEBUG3("read(%d, %p, %ld);\n", sock->sd, data, size);
+    DEBUG3("read(%d, %p, %ld);", sock->sd, data, size);
     
     if (status == -1) {
       RAISE4(system_error,"read(%d,%p,%d) failed: %s",
index 65638c8..290488e 100644 (file)
@@ -58,17 +58,17 @@ gras_init_defaultlog(int argc,char **argv, const char *defaultlog) {
    
   /** init other submodules */
   gras_trp_init();
+  gras_datadesc_init();
 }
 
 /**
  * gras_exit:
- * @argc:
- * @argv:
  *
  * Finalize the gras mecanisms.
  */
 void 
 gras_exit(){
   gras_trp_exit();
+  gras_datadesc_exit();
   gras_log_exit();
 }
index d452b1a..94280a1 100644 (file)
@@ -94,7 +94,7 @@ gras_error_t gras_set_add    (gras_set_t     *set,
   elm->ID = gras_dynar_length( set->dynar );
   TRY(gras_dict_insert_ext(set->dict, elm->name, elm->name_len, elm, free_func));
   TRY(gras_dynar_set(set->dynar, elm->ID, &elm));
-  DEBUG2("Insertion of key %s (id %d)", elm->name, elm->ID);
+  DEBUG2("Insertion of key '%s' (id %d)", elm->name, elm->ID);
 
   return no_error;
 }
@@ -146,10 +146,14 @@ gras_error_t gras_set_get_by_name_ext(gras_set_t     *set,
 gras_error_t gras_set_get_by_id      (gras_set_t     *set,
                                      int             id,
                                      /* OUT */gras_set_elm_t **dst) {
+  DEBUG2("Lookup type of id %d (of %d)", 
+        id, gras_dynar_length(set->dynar));
   if (id < gras_dynar_length(set->dynar) &&
       id >= 0) {
     gras_dynar_get(set->dynar,id,dst);
-    
+    DEBUG3("Lookup type of id %d (of %d): %s", 
+          id, gras_dynar_length(set->dynar), (*dst)->name);
+  
   } else {
     DEBUG1("Cannot get ID %d: out of bound", id);
     return mismatch_error;
index 606e2a9..edd33a8 100644 (file)
@@ -17,7 +17,8 @@ core_tests =                                  \
 
 RL_tests =                                    \
        trp_tcp_client   trp_tcp_server       \
-       trp_file_client  trp_file_server
+       trp_file_client  trp_file_server      \
+       datadesc_usage
 #      gs_example_send gs_example_receive
 
 SG_tests =
@@ -53,6 +54,8 @@ trp_tcp_server_LDADD=     $(LDADD_RL)
 trp_file_client_LDADD=    $(LDADD_RL)
 trp_file_server_LDADD=    $(LDADD_RL)
 
+datadesc_usage_LDADD=     $(LDADD_RL)
+
 #gs_example_send_LDADD=    $(LDADD_UTILS)
 #gs_example_receive_LDADD= $(LDADD_UTILS)
 
diff --git a/testsuite/gras/datadesc_usage.c b/testsuite/gras/datadesc_usage.c
new file mode 100644 (file)
index 0000000..2a6507b
--- /dev/null
@@ -0,0 +1,400 @@
+/* $Id$ */
+
+/* datadesc: test of data description (using file transport).               */
+
+/* Authors: Martin Quinson                                                  */
+/* Copyright (C) 2004 the OURAGAN project.                                  */
+
+/* This program is free software; you can redistribute it and/or modify it
+   under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <stdio.h>
+#include <gras.h>
+
+#include "../DataDesc/datadesc_interface.h"
+GRAS_LOG_NEW_DEFAULT_CATEGORY(test);
+
+gras_error_t
+write_read(gras_datadesc_type_t *type,void *src, void *dst);
+
+gras_error_t
+write_read(gras_datadesc_type_t *type,void *src, void *dst) {
+  gras_error_t errcode;
+  gras_socket_t *sock;
+   
+  /* write */
+  TRY(gras_socket_client_from_file("datadesc_usage.out",&sock));
+  TRY(gras_datadesc_send(sock, type, src));
+  gras_socket_close(&sock);
+   
+  /* read */
+  TRY(gras_socket_server_from_file("datadesc_usage.out",&sock));
+  TRY(gras_datadesc_recv(sock, type, gras_arch_selfid(), dst));
+  gras_socket_close(&sock);
+  
+  return no_error;
+}
+
+gras_error_t test_int(void);
+gras_error_t test_float(void);
+gras_error_t test_array(void);
+gras_error_t test_intref(void);
+gras_error_t test_string(void);
+
+gras_error_t test_homostruct(void);
+gras_error_t test_hetestruct(void);
+gras_error_t test_nestedstruct(void);
+gras_error_t test_chain_list(void);
+gras_error_t test_graph(void);
+
+gras_error_t test_int(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *type;
+  int i=5,*j=NULL;
+  
+  INFO0("==== Test on integer ====");
+  TRY(gras_datadesc_by_name("int", &type));
+  TRY(write_read(type, (void*)&i,(void**) &j));
+  gras_assert(i == *j);
+  free(j);
+  return no_error;
+}
+gras_error_t test_float(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *type;
+  float i=5.0,*j=NULL;
+  
+  INFO0("==== Test on float ====");
+  TRY(gras_datadesc_by_name("float", &type));
+  TRY(write_read(type, (void*)&i,(void**) &j));
+  gras_assert(i == *j);
+  free(j);
+  return no_error;
+}
+
+#define SIZE 5
+typedef int array[SIZE];
+gras_error_t test_array(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *int_type;
+  gras_datadesc_type_t *my_type;
+  
+  array i,*j;
+  long int code;
+  int cpt;
+
+  INFO0("==== Test on fixed array ====");
+  for (cpt=0; cpt<SIZE; cpt++) {
+    i[cpt] = rand();
+  }
+  j=NULL;
+
+  TRY(gras_datadesc_by_name("int", &int_type));
+  TRY(gras_datadesc_declare_array("fixed array of int", int_type, 5, &code));
+  TRY(gras_datadesc_by_code(code,&my_type));
+
+  TRY(write_read(my_type, (void*)&i,(void**) &j));
+  for (cpt=0; cpt<SIZE; cpt++)
+    gras_assert(i[cpt] == (*j)[cpt]);
+  free(j);
+  return no_error;
+}
+gras_error_t test_intref(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *int_type;
+  gras_datadesc_type_t *my_type;
+  int *i,**j=NULL;
+  long int code;
+  
+  if (! (i=malloc(sizeof(int))) )
+    RAISE_MALLOC;
+  *i=45;
+  INFO1("==== Test on a reference to an integer (%p) ====",i);
+
+  TRY(gras_datadesc_by_name("int", &int_type));
+  TRY(gras_datadesc_declare_ref("int*",int_type,&code));
+  TRY(gras_datadesc_by_code(code,&my_type));
+
+  TRY(write_read(my_type, (void*)&i,(void**) &j));
+  gras_assert(*i == **j);
+  free(j);
+  return no_error;
+}
+
+/***
+ *** string (dynamic array)
+ ***/ 
+typedef char *string;
+gras_error_t test_string(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *type;
+  string i=strdup("Some data");
+  string *j=NULL;
+  
+  INFO0("==== Test on string (dynamic array) ====");
+  TRY(gras_datadesc_by_name("string", &type));
+  TRY(write_read(type, (void*)&i,(void**) &j));
+  gras_assert(!strcmp(i,*j));
+  free(*j);
+  return no_error;
+}
+
+
+/***
+ *** homogeneous struct
+ ***/ 
+typedef struct {
+  int a,b,c,d;
+} homostruct;
+gras_error_t test_homostruct(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *my_type;
+  long int my_code;
+  homostruct *i, *j; 
+
+  INFO0("==== Test on homogeneous structure ====");
+  /* create descriptor */
+  TRY(gras_datadesc_declare_struct("homostruct",&my_code));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"a","int"));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"b","int"));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"c","int"));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"d","int"));
+  TRY(gras_datadesc_by_code(my_code, &my_type));
+
+  /* init a value, exchange it and check its validity*/
+  if (! (i=malloc(sizeof(homostruct))) )
+    RAISE_MALLOC;
+  i->a = rand();  i->b = rand();
+  i->c = rand();  i->d = rand();
+  j = NULL;
+
+  TRY(write_read(my_type, (void*)i, (void**)&j));
+  gras_assert(i->a == j->a);
+  gras_assert(i->b == j->b);
+  gras_assert(i->c == j->c);
+  gras_assert(i->d == j->d);
+
+  free(i);
+  free(j);
+  return no_error;
+}
+
+/***
+ *** heterogeneous struct
+ ***/ 
+typedef struct {
+  unsigned char c1;
+  unsigned long int l1;
+  unsigned char c2;
+  unsigned long int l2;
+} hetestruct;
+gras_error_t test_hetestruct(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *my_type;
+  long int my_code;
+  hetestruct *i, *j; 
+
+  INFO0("==== Test on heterogeneous structure ====");
+  /* create descriptor */
+  TRY(gras_datadesc_declare_struct("hetestruct",&my_code));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"c1","unsigned char"));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"l1","unsigned long int"));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"c2","unsigned char"));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"l2","unsigned long int"));
+  TRY(gras_datadesc_by_code(my_code, &my_type));
+
+  /* init a value, exchange it and check its validity*/
+  if (! (i=malloc(sizeof(hetestruct))) )
+    RAISE_MALLOC;
+  i->c1 = 's'; i->l1 = 123455;
+  i->c2 = 'e'; i->l2 = 774531;
+  j = NULL;
+
+  TRY(write_read(my_type, (void*)i, (void**)&j));
+  gras_assert(i->c1 == j->c1);
+  gras_assert(i->c2 == j->c2);
+  gras_assert(i->l1 == j->l1);
+  gras_assert(i->l2 == j->l2);
+
+  free(i);
+  free(j);
+  return no_error;
+}
+
+/***
+ *** nested struct
+ ***/ 
+typedef struct {
+  hetestruct hete;
+  homostruct homo;
+} nestedstruct;
+gras_error_t test_nestedstruct(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *my_type;
+  long int my_code;
+  nestedstruct *i, *j; 
+
+  INFO0("==== Test on nested structures ====");
+  /* create descriptor */
+  TRY(gras_datadesc_declare_struct("nestedstruct",&my_code));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"hete","hetestruct"));
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"homo","homostruct"));
+  TRY(gras_datadesc_by_code(my_code, &my_type));
+
+  /* init a value, exchange it and check its validity*/
+  if (! (i=malloc(sizeof(nestedstruct))) )
+    RAISE_MALLOC;
+  i->homo.a = rand();  i->homo.b = rand();
+  i->homo.c = rand();  i->homo.d = rand();
+  i->hete.c1 = 's'; i->hete.l1 = 123455;
+  i->hete.c2 = 'e'; i->hete.l2 = 774531;
+  j = NULL;
+
+  TRY(write_read(my_type, (void*)i, (void**)&j));
+  gras_assert(i->homo.a == j->homo.a);
+  gras_assert(i->homo.b == j->homo.b);
+  gras_assert(i->homo.c == j->homo.c);
+  gras_assert(i->homo.d == j->homo.d);
+  gras_assert(i->hete.c1 == j->hete.c1);
+  gras_assert(i->hete.c2 == j->hete.c2);
+  gras_assert(i->hete.l1 == j->hete.l1);
+  gras_assert(i->hete.l2 == j->hete.l2);
+
+  free(i);
+  free(j);
+  return no_error;
+}
+
+/***
+ *** chained list
+ ***/ 
+typedef struct s_chained_list chained_list_t;
+struct s_chained_list {
+  int          v;
+  chained_list_t *l;
+};
+chained_list_t *cons(int v, chained_list_t *l);
+void list_free(chained_list_t *l);
+int list_eq(chained_list_t*i,chained_list_t*j);
+chained_list_t * cons(int v, chained_list_t *l) {
+  chained_list_t *nl = malloc(sizeof (chained_list_t));
+  
+  nl->v = v;
+  nl->l = l;
+  
+  return nl;
+}
+void list_free(chained_list_t*l) {
+  if (l) {
+    list_free(l->l);
+    free(l);
+  }
+}
+int list_eq(chained_list_t*i,chained_list_t*j) {
+  if (!i || !j) return i == j;
+  if (i->v != j->v)
+    return 0;
+  return list_eq(i->l, j->l); 
+}
+gras_error_t test_chain_list(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *my_type,*ref_my_type;
+  long int my_code;
+  long int ref_my_code;
+  chained_list_t *i, *j; 
+
+  INFO0("==== Test on chained list ====");
+  /* create descriptor */
+  TRY(gras_datadesc_declare_struct("chained_list_t",&my_code));
+  TRY(gras_datadesc_by_code(my_code, &my_type));
+
+  TRY(gras_datadesc_declare_ref("chained_list_t*",my_type,&ref_my_code));
+
+  TRY(gras_datadesc_declare_struct_add_name(my_code,"v","int"));
+  TRY(gras_datadesc_declare_struct_add_code(my_code,"l",ref_my_code));
+
+  TRY(gras_datadesc_by_code(ref_my_code, &ref_my_type));
+      
+  /* init a value, exchange it and check its validity*/
+  i = cons( rand(), cons( rand() , cons( rand(), NULL)));
+  j = NULL;
+
+  TRY(write_read(my_type, (void*)i, (void**)&j));
+  gras_assert(list_eq(i,j));
+
+  list_free(i);
+  list_free(j);
+  return no_error;
+}
+/***
+ *** graph
+ ***/
+gras_error_t test_graph(void) {
+  gras_error_t errcode;
+  gras_datadesc_type_t *my_type;
+  chained_list_t *i, *j; 
+
+  INFO0("==== Test on graph (cyclique chained list) ====");
+  TRY(gras_datadesc_by_name("chained_list_t*", &my_type));
+      
+  /* init a value, exchange it and check its validity*/
+  i = cons( rand(), cons( rand() , cons( rand(), NULL)));
+  i->l->l->l = i->l;
+  j = NULL;
+
+  TRY(write_read(my_type, (void*)&i, (void**)&j));
+  INFO1("j=%p"         ,j);
+  INFO1("j->l=%p"      ,j->l);
+  INFO1("j->l->l=%p"   ,j->l->l);
+  INFO1("j->l->l->l=%p",j->l->l->l);
+  gras_assert4(j->l->l->l == j->l,
+              "Received list is not cyclic. j->l=%p != j->l->l->l=%p\n"
+              "j=%p; &j=%p",
+              j->l,j->l->l->l, 
+              j ,&j);
+  i->l->l->l = NULL;
+  j->l->l->l = NULL;
+  gras_assert(list_eq(i,j));
+
+  list_free(i);
+  list_free(j);
+  return no_error;
+}
+
+/**** PBIO *****/
+typedef struct { /* structure presented in the IEEE article */
+  int Cnstatv;
+  double Cstatev[12];
+  int Cnprops;
+  double Cprops[110];
+  int Cndi[4], Cnshr, Cnpt;
+  double Cdtime, Ctime[2];
+  int Cntens;
+  double Cdfgrd0[3][373], Cdfgrd1[3][3], Cstress[106], Cddsdde[106][106];
+} KSdata1;
+
+int main(int argc,char *argv[]) {
+  gras_error_t errcode;
+
+  gras_init_defaultlog(argc,argv,
+                      "DataDesc.thresh=verbose"
+                      " test.thresh=debug"
+                      //                      " set.thresh=debug"
+                      );
+
+  /*
+  TRYFAIL(test_int());    
+  TRYFAIL(test_float());  
+  TRYFAIL(test_array());  
+  TRYFAIL(test_intref()); 
+  TRYFAIL(test_string()); 
+
+  TRYFAIL(test_homostruct());
+  TRYFAIL(test_hetestruct());
+  TRYFAIL(test_nestedstruct());
+  */
+  TRYFAIL(test_chain_list());
+  TRYFAIL(test_graph());
+
+  return 0;
+}
index 7c755d9..48522cb 100644 (file)
@@ -23,7 +23,7 @@ void free_string(void *d){
 int main(int argc,char *argv[]) {
    gras_dynar_t *d;
    gras_error_t errcode;
-   int cpt,i;
+   int cpt;
    char buf[1024];
    char *s1,*s2;
    
@@ -31,7 +31,7 @@ int main(int argc,char *argv[]) {
    
    fprintf(stderr,"==== Traverse the empty dynar\n");
    TRYFAIL(gras_dynar_new(&d,sizeof(char *),&free_string));
-   gras_dynar_foreach(d,cpt,i){
+   gras_dynar_foreach(d,cpt,s1){
      fprintf(stderr,
             "Damnit, there is something in the empty dynar\n");
      abort();
@@ -74,13 +74,22 @@ int main(int argc,char *argv[]) {
    gras_dynar_free(d);
 
 
-   fprintf(stderr,"==== Unshift/pop %d strings\n",NB_ELEM);
+   fprintf(stderr,"==== Unshift, traverse and pop %d strings\n",NB_ELEM);
    TRYFAIL(gras_dynar_new(&d,sizeof(char**),&free_string));
    for (cpt=0; cpt< NB_ELEM; cpt++) {
      sprintf(buf,"%d",cpt);
      s1=strdup(buf);
      TRYFAIL(gras_dynar_unshift(d,&s1));
    }
+   gras_dynar_foreach(d,cpt,s1) {
+     sprintf(buf,"%d",NB_ELEM - cpt -1);
+     if (strcmp(buf,s1)) {
+       fprintf(stderr,
+           "The retrieved value is not the same than the injected one (%s!=%s)\n",
+              buf,s1);
+       abort();
+     }
+   }
    for (cpt=0; cpt< NB_ELEM; cpt++) {
      sprintf(buf,"%d",cpt);
      gras_dynar_pop(d,&s2);