Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
current state
[simgrid.git] / cruft / doc / gras-docs.sgml
1 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
2
3 <!ENTITY comm-socks SYSTEM "sgml/comm_socks.sgml">
4 <!ENTITY comm-datadesc SYSTEM "sgml/comm_datadesc.sgml">
5 <!ENTITY comm-messages SYSTEM "sgml/comm_messages.sgml">
6
7 <!ENTITY virtu-globals SYSTEM "sgml/virtu_globals.sgml">
8 <!ENTITY virtu-syscall SYSTEM "sgml/virtu_syscall.sgml">
9 <!ENTITY virtu-fs      SYSTEM "sgml/virtu_fs.sgml">
10
11
12 <!ENTITY tbx-err SYSTEM "sgml/tbx_err.sgml">
13 <!ENTITY tbx-log SYSTEM "sgml/tbx_log.sgml">
14 <!ENTITY tbx-dynar SYSTEM "sgml/tbx_dynar.sgml">
15 <!ENTITY tbx-dico SYSTEM "sgml/tbx_dico.sgml">
16 <!ENTITY tbx-set SYSTEM "sgml/tbx_set.sgml">
17 <!ENTITY tbx-cfg SYSTEM "sgml/tbx_cfg.sgml">
18
19 <!ENTITY gras-gras SYSTEM "sgml/gras.sgml">
20 <!ENTITY gras-gras-private SYSTEM "sgml/gras_private.sgml">
21 <!ENTITY gras-gras-rl SYSTEM "sgml/gras_rl.sgml">
22 <!ENTITY gras-gras-sg SYSTEM "sgml/gras_sg.sgml">
23
24 <!ENTITY overview SYSTEM "overview.sgml">
25 ]>
26 <book id="index">
27   <bookinfo>
28     <title>Grid Reality And Simulation Reference Manual</title>
29   </bookinfo>
30
31   <chapter>
32     <title>GRAS overview</title>
33     &overview;
34   </chapter>
35
36   <chapter>
37    <title>Communication facilities</title>
38     &comm-datadesc;
39     &comm-socks;
40     &comm-messages;
41   </chapter>
42   
43   <chapter>
44    <title>Virtualization</title>
45     &virtu-globals;
46     &virtu-syscall;
47 <!--    &virtu-fs;-->
48   </chapter>
49
50 <!--
51 =head2 Sending (or receiving) dynamic sized arrays
52
53 To overcome the impossibility to send structure having dynamic-sized array,
54 it is possible to send several times the same structures, the number of time
55 being given in the header. The idea here is to say that we want to send a
56 C<STORE_STATE> message containing not one C<struct state> to store, but for
57 example three different C<state>s. We will come back on this in the next
58 sections.
59
60 =head1 Describing hosts
61
62 Before any GRAS communication, you have to do some initialization work. For
63 that, use the GRAS_EstablishHost() function. 
64
65  GRAS_EstablishHost(char **addresses,
66                     unsigned int addressesCount,
67                     unsigned short port,
68                     void (*initFunction)(void),
69                     int (*exitFunction)(void),
70                     unsigned int serveEvery,
71                     GRAS_host_t *hostdescriptor);
72
73 It takes as argument the name (or IP) of the host on which you want to
74 establish this host (in RL, you may want to pass a list of all IP addresses
75 served by this host), the port on which it will listen by default, the init
76 and exit functions, how often (in millisecond) it will try to handle the
77 incoming requests and returns a descriptor to the newly created host
78 descriptor.
79
80 The init function is supposed to return to a userdata, which will be passed
81 to all functions, and which should contain the I<state> of your server, if
82 it's not state-less.
83
84 =head1 Preparing to accept incomming messages
85
86 To be able to accept any incomming messages, you have first to open a socket
87 in listening mode. For that, simply use the GRAS_IncomingSocket(). In RL,
88 GRAS try to bind() to the socket, and then accept(). In SG, it tries to lock
89 the given channel. Here is the prototype of this function.
90
91  int
92  GRAS_IncomingSocket(unsigned short startingPort,
93                      unsigned short endingPort,
94                      GRAS_Socket_t *sd,
95                      unsigned short *socketPort);
96                      
97 It tries to open an incoming socket on a port between C<startingPort> and
98 C<endingPort>, returns the created C<socket> and the C<socketPort> on which we
99 managed to create this socket. The return value of the function is true if we
100 managed to create it, and false if not.
101
102 =head1 Sending messages
103
104 Sending data is pretty simple. First, you have to create a outgoing socket,
105 and then use it as argument to the GRAS_SendMessage*() function.
106
107 GRAS_OutgoingSocket() can be used to build a new outgoing socket.
108 Alternatively, you can pass a reference to a Socket you know using
109 C<socketDescriptor> and C<socketDescriptorLength> in messages.
110
111 In fact, an outgoing socket is nothing more than an address to remote socket
112 openned in listing mode.
113
114  int 
115  GRAS_OutgoingSocket(char *host, 
116                      unsigned short port,
117                      GRAS_Socket_t *sd);
118
119 Once you have a reference to the peer with which you want to communicate,
120 sending messages is as easy as using the GRAS_SendMessage() function.
121
122  int
123  GRAS_SendMessage(GRAS_Socket_t *sd,
124                   double timeOut,
125                   MessageType message,
126                   int sequence_count ,
127                   ...);
128
129
130 C<GRAS_SendMessage> allows you to send a message with several sequence of
131 structures as payload. For each sequence, you have to pass three extra
132 arguments to the function. The prototype of those arguments would be:
133
134                   size_t howMany,
135                   const DataDescriptor *description,
136                   const void *data
137
138 This allows you to specify that the given sequence is a C<howMany>-long
139 array of structure described by C<description>, and stored at the memory
140 location pointed by C<data>.
141
142 This function is blocking until the message is actually sent, and you must
143 free the data when you're done with it.
144
145 =head1 Receiving messages
146
147 GRAS_IncomingSocket() prepared the host to receive messages, but did not
148 explain how to handle incoming messages. There is 3 kinds of handling to
149 incoming messages :
150
151 =over
152
153 =item default callback
154
155 you can register default callbacks to well known messages which will always
156 be handled the same way. This is for example used in the NWS memory server
157 to handle C<STORE_STATE> messages by actually writing the state on disk. For
158 that, use the function GRAS_RegisterListener() to register the function
159 C<listener> as listener to message type C<message> (which name to use in
160 debugging messages is C<name>).
161
162  typedef void (*GRAS_ListenerFunction)(GRAS_Socket_t *from,
163                                        void *userdata,
164                                        int sequence_count,
165                                        va_args va);
166
167  void
168  GRAS_RegisterListener (int message,const char *name,
169                         GRAS_ListenFunction listener);
170
171 The C<va> argument passed to the listener function is the pending of the
172 extra args passed to the GRAS_SendMessage function. That is to say that it
173 will contain C<sequence_count> sequence of data, each of them being
174 described by three arguments:
175
176                   size_t howMany,
177                   const DataDescriptor *description,
178                   const void *data
179
180 The data are allocated by GRAS for you when the message incomes, but must be
181 freed by you after use in the listener function.
182
183 =item Actually waiting for data
184
185 You can also ask to receive the next message of a given type. For example,
186 the sensor sending data to the memory using the C<STORE_STATE> message will
187 wait for an answer of the memory (which will use a C<STORED_STATE> to
188 indicate if the operation was successfull or not). For that, use the 
189 GRAS_RecvMessage() function. If the next message to be received is not of
190 the waited type, this message is queued until we get the message we expect,
191 and handled afterward.
192
193  int
194  GRAS_RecvMessage(GRAS_Socket_t *sd,
195                   double timeOut,
196                   MessageType message,
197                   int *sequence_count,
198                   ...);
199                   
200 Like always, sequence count is set to the number of sequences in the
201 message's payload, and the extra arguments should describe each sequence.
202 Their prototype will be:
203
204                   size_t *howMany,
205                   const DataDescriptor **description,
206                   const void **data
207
208 Note that there is a level of indirection more than in previous functions,
209 since their values will be set by the GRAS_RecvMessage() function.
210
211 The C<data> fields are allocated by the GRAS_RecvMessage, and must be freed
212 by user after use.
213
214 =item one-way callback
215
216 As you can see, calling GRAS_RecvMessage() is blocking for that host in that
217 sense that no other messages can be server until the expected message is
218 received. To avoid that problem, it is possible to declare I<one-way
219 callback>. As GRAS_RecvMessage(), this is to be used when you wait for the
220 answer of a peer, but when you don't want to block on this. The handling of
221 the message (or of the associated timeout) have to be moved to another
222 function, which will be passed as callback to the expected message. This
223 allows GRAS to handle other incoming messages before the answer to the
224 request comes and improve the reactivity of code. Sadly, this makes the code
225 quite difficult to read and maintain...
226
227  void
228  GRAS_RegisterOneWayListener (int message,const char *name,
229                               GRAS_ListenerFunction listener);
230
231 If you do several calls to this function for the same message, callbacks are
232 stacked, and their use will pop this stack. It is possible to use this
233 function to interceipt messages having a default callback.
234
235 =back
236
237 =head1 Handling computation
238
239 SG is a simulator, and you when you simulate a computationnal server, you
240 don't want to see him actually doing the computation, rather, you want to
241 see this work I<simulated>.
242
243 For that, use the GRAS_computation() macro. If running in RL, the provided
244 code will actually be done, and if running SG, a task of the provided
245 C<size> will be scheduled on the host (and the computation done will be the
246 one passed in the else branch).
247
248  GRAS_computation_if_RL(size) {
249    code to execute when running in RL;
250  } else {
251    code to execute when running in SG;
252  }
253  
254 If running RL, this macro will be rewritten to
255
256   if (1)
257   
258 and if running SG, this macro will be rewritten to 
259
260   if (<code to simulate the task>, 0) 
261
262 =head1 Conclusion
263
264 We belive that the sort of raw RPC we presented here permits to run the same
265 code both in RL and SG because GRAS will do the unpleasant job of moving
266 data from one namespace to another if needed, sending it over the network if
267 needed. 
268
269 GRAS Agents never really define the main function. The main function you
270 write in your code does only call to GRAS_EstablishHost(), which is in
271 charge of initializing the GRAS mecanism on the right hosts.
272
273 =head1 TODO
274
275 =over 
276
277 =item
278
279 Make sure this proposal is more or less flawless. That's a RFC ;)
280
281 We could go one step further on the main() problem, by using the SG scenario
282 files, and a way to actuate it in RL. 
283
284 =item
285
286 Implement this. 
287
288 In RL, it should pretty straightforward, since GRAS functions are more or
289 less wrappers to the NWS communication library. 
290
291 In SG, it shouldn't be that difficult either ;)
292
293 =item
294
295 Write examples.
296   </chapter>
297 -->
298
299   <chapter>
300    <title>GRAS toolbox</title>
301    &tbx-err;
302    &tbx-log;
303    &tbx-dynar;
304    &tbx-dico;
305    &tbx-set;
306    &tbx-cfg;
307   </chapter>
308
309 <!--
310   <chapter>
311     <title>GRAS implementation</title>
312     &gras-gras-private;
313     &gras-gras-rl;
314     &gras-gras-sg;
315   </chapter>
316 -->
317 </book>