--- /dev/null
+- 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
--- /dev/null
+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.
#! /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.
#
@host:
@Param2:
-@bufSize:
@dst:
@Returns:
<!-- # Unused Parameters # -->
+@bufSize:
@sock:
</para>
@Param1:
-@bufSize:
@dst:
@Returns:
+<!-- # Unused Parameters # -->
+@bufSize:
<!-- ##### FUNCTION gras_socket_close ##### -->
***********************************************/
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 ****
*********************************************/
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 ****
****************************/
/*@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(); \
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 the
- * 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 be
+ * seeable again only after a pop to remove the value this push adds.
*/
void
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,
/**
* 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,
/**
* 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 *
*
* 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
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;
free(p_elm);
free(name);
}
-
+
gras_dynar_free_container(p_dynar);
}
/**
* 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) {
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));
}
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
- ***/
#ifndef GRAS_DATADESC_INTERFACE_H
#define GRAS_DATADESC_INTERFACE_H
-#include "gras_private.h"
-
void gras_datadesc_init(void);
void gras_datadesc_exit(void);
/* 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);
/* -- */
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;
* 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;
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;
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 */
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;
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];
*/
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) {
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));
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;
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]);
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;
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,
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,
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,
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,
}
/**
- * 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;
}
#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:
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;
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:
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;
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))
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;
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;
/**
* 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;
}
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 \
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,
(*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) {
if (strcmp("-", path)) {
- (*dst)->sd = open(path, O_WRONLY );
+ (*dst)->sd = open(path, O_RDONLY );
if ( (*dst)->sd < 0) {
RAISE2(system_error,
} 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));
}
}
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",
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",
/** 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();
}
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;
}
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;
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 =
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)
--- /dev/null
+/* $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;
+}
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;
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();
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);