Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
I'm such a looser (too)
[simgrid.git] / src / gras / Msg / rpc.c
1 /* $Id$ */
2
3 /* rpc - RPC implementation on top of GRAS messages                         */
4
5 /* Copyright (c) 2005 Martin Quinson. All rights reserved.                  */
6
7 /* This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. */
9
10 #include "gras/Msg/msg_private.h"
11                 
12 //XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_rpc,gras_msg,"RPCing");
13
14 xbt_set_t _gras_rpctype_set = NULL;
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_rpc,gras_msg,"RPC mecanism");
17
18
19 /** @brief declare a new versionned RPC type of the given name and payloads
20  *
21  * @param name: name as it should be used for logging messages (must be uniq)
22  * @param version: something like versionning symbol
23  * @param payload: datadescription of the payload
24  *
25  * Registers a new RPC message to the GRAS mechanism. RPC are constituted of a pair 
26  * of messages. 
27  */
28 void
29 gras_msgtype_declare_rpc(const char           *name,
30                          gras_datadesc_type_t  payload_request,
31                          gras_datadesc_type_t  payload_answer) {
32
33   gras_msgtype_declare_ext(name, 0, 
34                            e_gras_msg_kind_rpccall, 
35                            payload_request, payload_answer);
36
37 }
38
39 /** @brief declare a new versionned RPC type of the given name and payloads
40  *
41  * @param name: name as it should be used for logging messages (must be uniq)
42  * @param version: something like versionning symbol
43  * @param payload: datadescription of the payload
44  *
45  * Registers a new RPC message to the GRAS mechanism. RPC are constituted of a pair 
46  * of messages. 
47  *
48  * Use this version instead of gras_rpctype_declare when you change the
49  * semantic or syntax of a message and want your programs to be able to deal
50  * with both versions. Internally, each will be handled as an independent
51  * message type, so you can register differents for each of them.
52  */
53 void
54 gras_msgtype_declare_rpc_v(const char           *name,
55                            short int             version,
56                            gras_datadesc_type_t  payload_request,
57                            gras_datadesc_type_t  payload_answer) {
58
59   gras_msgtype_declare_ext(name, version, 
60                            e_gras_msg_kind_rpccall, 
61                            payload_request, payload_answer);
62
63 }
64
65 static unsigned long int last_msg_ID = 0;
66
67 static int msgfilter_rpcID(gras_msg_t msg, void* ctx) {
68   unsigned long int ID= *(unsigned long int*)ctx;
69   int res = msg->ID == ID && 
70     (msg->kind == e_gras_msg_kind_rpcanswer || msg->kind == e_gras_msg_kind_rpcerror);
71
72   DEBUG5("Filter a message of ID %lu, type '%s' and kind '%s'. Waiting for ID=%lu. %s",
73          msg->ID,msg->type->name,e_gras_msg_kind_names[msg->kind],ID,
74          res?"take it": "reject");
75   return res;
76 }
77
78 /** @brief Conduct a RPC call
79  *
80  */
81 void gras_msg_rpccall(gras_socket_t server,
82                       double timeOut,
83                       gras_msgtype_t msgtype,
84                       void *request, void *answer) {
85
86   unsigned long int msg_ID = last_msg_ID++;
87   s_gras_msg_t received;
88
89   DEBUG2("Send a RPC of type '%s' (ID=%lu)",msgtype->name,msg_ID);
90
91   gras_msg_send_ext(server, e_gras_msg_kind_rpccall, msg_ID, msgtype, request);
92   gras_msg_wait_ext(timeOut,
93                     msgtype, NULL, msgfilter_rpcID, &msg_ID,
94                     &received);
95   if (received.kind == e_gras_msg_kind_rpcerror) {
96     /* Damn. Got an exception. Extract it and revive it */
97     xbt_ex_t e;
98     VERB0("Raise a remote exception");
99     memcpy(&e,received.payl,received.payl_size);
100     free(received.payl);
101     memcpy((void*)&(__xbt_ex_ctx()->ctx_ex),&e,sizeof(xbt_ex_t));
102     DO_THROW(__xbt_ex_ctx()->ctx_ex);
103
104   }
105   memcpy(answer,received.payl,received.payl_size);
106   free(received.payl);
107 }
108
109
110 /** @brief Return the result of a RPC call
111  *
112  * It done before the actual return of the callback so that the callback can do
113  * some cleanups before leaving.
114  */
115
116 void gras_msg_rpcreturn(double timeOut,gras_msg_cb_ctx_t ctx,void *answer) {
117   gras_msg_send_ext(ctx->expeditor, e_gras_msg_kind_rpcanswer, ctx->ID, ctx->msgtype, answer);
118 }
119