Logo AND Algorithmique Numérique Distribuée

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