1 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
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">
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">
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">
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">
25 <!ENTITY overview SYSTEM "overview.sgml">
29 <title>Grid Reality And Simulation Reference Manual</title>
33 <title>GRAS overview</title>
38 <title>Communication facilities</title>
46 <title>Virtualization</title>
53 =head2 Sending (or receiving) dynamic sized arrays
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
62 =head1 Describing hosts
64 Before any GRAS communication, you have to do some initialization work. For
65 that, use the GRAS_EstablishHost() function.
67 GRAS_EstablishHost(char **addresses,
68 unsigned int addressesCount,
70 void (*initFunction)(void),
71 int (*exitFunction)(void),
72 unsigned int serveEvery,
73 GRAS_host_t *hostdescriptor);
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
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
86 =head1 Preparing to accept incomming messages
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.
94 GRAS_IncomingSocket(unsigned short startingPort,
95 unsigned short endingPort,
97 unsigned short *socketPort);
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.
104 =head1 Sending messages
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.
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.
113 In fact, an outgoing socket is nothing more than an address to remote socket
114 openned in listing mode.
117 GRAS_OutgoingSocket(char *host,
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.
125 GRAS_SendMessage(GRAS_Socket_t *sd,
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:
137 const DataDescriptor *description,
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>.
144 This function is blocking until the message is actually sent, and you must
145 free the data when you're done with it.
147 =head1 Receiving messages
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
155 =item default callback
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>).
164 typedef void (*GRAS_ListenerFunction)(GRAS_Socket_t *from,
170 GRAS_RegisterListener (int message,const char *name,
171 GRAS_ListenFunction listener);
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:
179 const DataDescriptor *description,
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.
185 =item Actually waiting for data
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.
196 GRAS_RecvMessage(GRAS_Socket_t *sd,
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:
207 const DataDescriptor **description,
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.
213 The C<data> fields are allocated by the GRAS_RecvMessage, and must be freed
216 =item one-way callback
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...
230 GRAS_RegisterOneWayListener (int message,const char *name,
231 GRAS_ListenerFunction listener);
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.
239 =head1 Handling computation
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>.
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).
250 GRAS_computation_if_RL(size) {
251 code to execute when running in RL;
253 code to execute when running in SG;
256 If running RL, this macro will be rewritten to
260 and if running SG, this macro will be rewritten to
262 if (<code to simulate the task>, 0)
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
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.
281 Make sure this proposal is more or less flawless. That's a RFC ;)
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.
290 In RL, it should pretty straightforward, since GRAS functions are more or
291 less wrappers to the NWS communication library.
293 In SG, it shouldn't be that difficult either ;)
302 <title>GRAS toolbox</title>
313 <title>GRAS implementation</title>