Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
When answering a RPC, use the answer message type, not the request one. 'Some' RPC...
[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 payload_request: datatype of request
23  * @param payload_answer: datatype of answer
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_request: datatype of request
44  * @param payload_answer: datatype of answer
45  *
46  * Registers a new RPC message to the GRAS mechanism. RPC are constituted of a pair 
47  * of messages. 
48  *
49  * Use this version instead of gras_rpctype_declare when you change the
50  * semantic or syntax of a message and want your programs to be able to deal
51  * with both versions. Internally, each will be handled as an independent
52  * message type, so you can register differents for each of them.
53  */
54 void
55 gras_msgtype_declare_rpc_v(const char           *name,
56                            short int             version,
57                            gras_datadesc_type_t  payload_request,
58                            gras_datadesc_type_t  payload_answer) {
59
60   gras_msgtype_declare_ext(name, version, 
61                            e_gras_msg_kind_rpccall, 
62                            payload_request, payload_answer);
63
64 }
65
66 static unsigned long int last_msg_ID = 0;
67
68 static int msgfilter_rpcID(gras_msg_t msg, void* ctx) {
69   unsigned long int ID= *(unsigned long int*)ctx;
70   int res = msg->ID == ID && 
71     (msg->kind == e_gras_msg_kind_rpcanswer || msg->kind == e_gras_msg_kind_rpcerror);
72
73   DEBUG5("Filter a message of ID %lu, type '%s' and kind '%s'. Waiting for ID=%lu. %s",
74          msg->ID,msg->type->name,e_gras_msg_kind_names[msg->kind],ID,
75          res?"take it": "reject");
76   return res;
77 }
78
79 /** @brief Conduct a RPC call
80  *
81  */
82 void gras_msg_rpccall(gras_socket_t server,
83                       double timeOut,
84                       gras_msgtype_t msgtype,
85                       void *request, void *answer) {
86
87   unsigned long int msg_ID = last_msg_ID++;
88   s_gras_msg_t received;
89
90   DEBUG4("Send to %s:%d a RPC of type '%s' (ID=%lu)",
91          gras_socket_peer_name(server),
92          gras_socket_peer_port(server),
93          msgtype->name,msg_ID);
94
95   gras_msg_send_ext(server, e_gras_msg_kind_rpccall, msg_ID, msgtype, request);
96   gras_msg_wait_ext(timeOut,
97                     msgtype, NULL, msgfilter_rpcID, &msg_ID,
98                     &received);
99   if (received.kind == e_gras_msg_kind_rpcerror) {
100     /* Damn. Got an exception. Extract it and revive it */
101     xbt_ex_t e;
102     VERB0("Raise a remote exception");
103     memcpy(&e,received.payl,received.payl_size);
104     free(received.payl);
105     memcpy((void*)&(__xbt_ex_ctx()->ctx_ex),&e,sizeof(xbt_ex_t));
106     DO_THROW(__xbt_ex_ctx()->ctx_ex);
107
108   }
109   memcpy(answer,received.payl,received.payl_size);
110   free(received.payl);
111 }
112
113
114 /** @brief Return the result of a RPC call
115  *
116  * It done before the actual return of the callback so that the callback can do
117  * some cleanups before leaving.
118  */
119
120 void gras_msg_rpcreturn(double timeOut,gras_msg_cb_ctx_t ctx,void *answer) {
121   gras_msg_send_ext(ctx->expeditor, e_gras_msg_kind_rpcanswer, ctx->ID, ctx->msgtype, answer);
122 }
123