Logo AND Algorithmique Numérique Distribuée

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