1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2007 FRESCOR consortium partners:
4 // Universidad de Cantabria, SPAIN
5 // University of York, UK
6 // Scuola Superiore Sant'Anna, ITALY
7 // Kaiserslautern University, GERMANY
8 // Univ. Politécnica Valencia, SPAIN
9 // Czech Technical University in Prague, CZECH REPUBLIC
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org for a link to partners' websites
18 // FRESCOR project (FP6/2005/IST/5-034026) is funded
19 // in part by the European Union Sixth Framework Programme
20 // The European Union is not liable of any use that may be
24 // based on previous work (FSF) done in the FIRST project
26 // Copyright (C) 2005 Mälardalen University, SWEDEN
27 // Scuola Superiore S.Anna, ITALY
28 // Universidad de Cantabria, SPAIN
29 // University of York, UK
31 // FSF API web pages: http://marte.unican.es/fsf/docs
32 // http://shark.sssup.it/contrib/first/docs/
34 // This file is part of FRSH API
36 // FRSH API is free software; you can redistribute it and/or modify
37 // it under the terms of the GNU General Public License as published by
38 // the Free Software Foundation; either version 2, or (at your option)
41 // FRSH API is distributed in the hope that it will be useful, but
42 // WITHOUT ANY WARRANTY; without even the implied warranty of
43 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 // General Public License for more details.
46 // You should have received a copy of the GNU General Public License
47 // distributed with FRSH API; see file COPYING. If not, write to the
48 // Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
51 // As a special exception, if you include this header file into source
52 // files to be compiled, this header file does not by itself cause
53 // the resulting executable to be covered by the GNU General Public
54 // License. This exception does not however invalidate any other
55 // reasons why the executable file might be covered by the GNU General
57 // -----------------------------------------------------------------------
59 //==============================================
60 // ******** ******* ******** ** **
61 // **///// /**////** **////// /** /**
62 // ** /** /** /** /** /**
63 // ******* /******* /********* /**********
64 // **//// /**///** ////////** /**//////**
65 // ** /** //** /** /** /**
66 // ** /** //** ******** /** /**
67 // // // // //////// // //
69 // FRSH(FRescor ScHeduler), pronounced "fresh"
70 //==============================================
71 #ifndef _FRSH_DISTRIBUTED_H_
72 #define _FRSH_DISTRIBUTED_H_
76 * @file frsh_distributed.h
80 #include "frsh_distributed_types.h"
81 #include "frsh_core_types.h"
86 * @defgroup distributed Distributed module
88 * This module defines the functions and typedefs for use in
89 * distributed applications.
91 * Each network is identified by its resource_id and FRSH hides its
92 * characteristics completely. The type of network is implied with
93 * its ID via a configuration table defined at compile time.
95 * FRSH uses the "message" as the atomic unit for every exchange.
96 * Queue sizes are measured in number of pending messages.
98 * FRSH provides a function to calculate the transmision time needed
99 * for a certain message size in a network as well as the maximum
100 * message size that can admit.
102 * Note also that package delivery guarantee is protocol dependent.
103 * For protocols in which the order is no guaranteed, the application
104 * needs to add extra info to detect possible package disorder.
106 * Summary of typical steps.
108 * 1. Map (internally in FRSH implementation)
109 * - node--> network_addresses
110 * - network --> resource_id's
111 * - unidirectional communication channel --> stream_id
112 * - other config --> protocol_info.
114 * 2. In a sending node:
115 * 2.1. Negotiates a "network contract" per communication channel
116 * that is used in the application. In the contract it is
118 * - frsh_resource_type = FRSH_RT_NETWORK.
119 * - frsh_resource_id = <network id #>
120 * - budget: Time needed to send the required data per period.
121 * (you can use frsh_netinfo_*() functions for this).
122 * - period: Period of sendings.
123 * - Queueing info: How will sends be queued at sendEndpoint.
124 * - Other protocol dependent function in protocol_contract_info.
125 * 2.2. Create a send_endpoint per any unidirectional stream that will
127 * resource_id --> the network through which the stream will
128 * flow (this is extra info needed for coherency
130 * destinator --> network_address of the destination.
131 * stream_id --> the unidirectional communication channel.
132 * 2.3. Bind the send_endpoint to the network contract negotiated
134 * 2.4. The (processor) sending vres invokes frsh_send_(a)sync() to
135 * send the data through the corresponding stream.
137 * 3. In a receiving node:
138 * 3.1. Create a receive_endpoint per any unidirectional stream
139 * that will be used in receiving.
140 * 3.2. The processor expecting a reception of message invokes
141 * frsh_receive_(a)sync() to read the incoming data.
143 * 4. When all comunication is finished and the channel is no longer
144 * needed the nodes will destroy the send and receive endpoints
145 * and the network contract will be canceled.
149 * frsh_distributed_init(void)
151 * This operation initializes all the installed networks and the structures
152 * that are necessary for the distributed module. Currently it is called by
153 * frsh_init so it is not necessary that the user calls it again.
156 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
159 int frsh_distributed_init(void);
161 //////////////////////////////////////////////////////////////////////
163 //////////////////////////////////////////////////////////////////////
166 * @defgroup distcontract Contract Info for Distributed Systems
167 * @ingroup distributed
169 * These functions help you calculate the needed budget for network
170 * contracts and also to include protocol dependent info in contract
177 * frsh_network_get_max_message_size()
179 * This operation gives the maximum number of bytes that can be sent
180 * at a time through the send function when using the network designated by
181 * 'resource_id' and sending it to 'destination'.
183 * If the application needs to send bigger messages it will have to
186 * Some protocols, like IP, are capable of sending large messages
187 * (and use fragmentation internally) but other protocols don't.
189 * @param[in] resource_id The network we want the tx time from.
190 * @param[in] destination The destination address
191 * @param[out] max_size The maximum number of bytes for each message
195 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
196 * FRSH_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
197 * FRSH_ERR_RESOURCE_ID_INVALID: if resource id does not represent
198 * a network accessible from the current processing node \n
199 * FRSH_ERR_BAD_ARGUMENT: if pointers are NULL or destination is
203 int frsh_network_get_max_message_size
204 (const frsh_resource_id_t resource_id,
205 const frsh_network_address_t destination,
209 * frsh_network_bytes_to_budget()
211 * This operation converts a number of bytes into a temporal budget for
212 * a specific network. Network overheads are not included here but are
213 * considered internally when negotiating a specific contract.
215 * @param[in] resource_id The network
216 * @param[in] nbytes Number of bytes
217 * @param[out] budget The network budget for nbytes
221 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
222 * FRSH_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
223 * FRSH_ERR_RESOURCE_ID_INVALID: if resource id does not represent
224 * a network accessible from the current processing node \n
225 * FRSH_ERR_BAD_ARGUMENT: if pointers are NULL or nbytes is less
229 int frsh_network_bytes_to_budget
230 (const frsh_resource_id_t resource_id,
232 frsh_rel_time_t *budget);
235 * frsh_network_budget_to_bytes()
237 * This operation converts a temporal budget into a number of bytes for
238 * a specific network. Network overheads are not included.
240 * @param[in] resource_id The network
241 * @param[in] budget The network budget for nbytes
242 * @param[out] nbytes Number of bytes
246 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
247 * FRSH_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
248 * FRSH_ERR_RESOURCE_ID_INVALID: if resource id does not represent
249 * a network accessible from the current processing node \n
250 * FRSH_ERR_BAD_ARGUMENT: if pointers are NULL or budget refers to
251 * an invalid time value \n
254 int frsh_network_budget_to_bytes
255 (const frsh_resource_id_t resource_id,
256 const frsh_rel_time_t *budget,
260 * frsh_network_get_min_effective_budget()
262 * This operation gets the minimum effective budget for a network. Each message
263 * consumes a contracted budget in "chunks" (i.e: packets) that we call
264 * minimum effective budget.
266 * A negotiated contract, for N bytes in a period T, means that there is a
267 * virtual resource that reserves for the user:
269 * Ceiling ((N bytes) / budget_to_bytes (min_effective_budget)) "CHUNKS"
271 * Note that if the user decides not to send these N bytes at once but, say,
272 * one byte at a time, it will consume one "CHUNK" at a time and the reserved
273 * budget will become exhausted before sending all the bytes.
275 * @param[in] resource_id The network
276 * @param[out] budget The network budget
280 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
281 * FRSH_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
282 * FRSH_ERR_RESOURCE_ID_INVALID: if resource id does not represent
283 * a network accessible from the current processing node \n
284 * FRSH_ERR_BAD_ARGUMENT: if pointers are NULL \n
287 int frsh_network_get_min_effective_budget
288 (const frsh_resource_id_t resource_id,
289 frsh_rel_time_t *budget);
292 * frsh_contract_set_queueing_info()
294 * This function adds queueing parameters that will be used in the
295 * sendEndpoint when the sendEndpoint is bound to the vres.
297 int frsh_contract_set_queueing_info(frsh_endpoint_queueing_info_t queueing_info,
298 frsh_contract_t *contract);
301 * frsh_contract_get_queueing_info()
303 * This function gets the queueing parameters that were specified in
304 * the network contract.
306 int frsh_contract_get_queueing_info(const frsh_contract_t *contract,
307 frsh_endpoint_queueing_info_t *queueing_info);
310 * frsh_contract_set_protocol_info
312 * We add protocol info to the contract
314 int frsh_contract_set_protocol_info(frsh_protocol_info_t protocol_info,
315 frsh_contract_t *contract);
318 * frsh_contract_get_protocol_info
320 * We get protocol info from the contract
322 int frsh_contract_get_protocol_info(frsh_contract_t *contract,
323 frsh_protocol_info_t *protocol_info);
326 * frsh_contract_marshal
328 * Convert a contract to a sequence of bytes of minimum size so it can
329 * be sent through the network with the minimum amount of bytes.
333 int frsh_contract_marshal(const frsh_contract_t *contract,
334 unsigned char *buffer,
335 const size_t buffer_size,
339 * frsh_contract_unmarshal
341 * Convert a sequence of bytes generated by frsh_contract_marshal to a contract
345 int frsh_contract_unmarshal(frsh_contract_t *contract,
346 const unsigned char *marshal_bytes,
350 //////////////////////////////////////////////////////////////////////
351 // TWO STEP NEGOTIATION
352 //////////////////////////////////////////////////////////////////////
355 * @defgroup twostepnego Two Step Negotiation
356 * @ingroup distributed
358 * Using the core services of FRSH, contracts may be negotiated in a
361 * An alternative two-step negotiation process is introduced in the
362 * distribution module: the first step involves the reservation of the
363 * resources, but without the right to use them, and the second step
364 * is the commitment to use those resources.
366 * The rationale behind this approach is that in distributed systems,
367 * when a distributed transaction is being negotiated the system
368 * should only commit the virtual resources that were negotiated with
369 * various nodes in the system if the results of all negotiations
370 * match together. This approach enhances the efficiency since the
371 * actual temporal values of the virtual resources on distributed
372 * nodes are only changed if the initiator of the distributed
373 * transaction is satisfied with the results of the negotiations.
375 * After the reservation, it is not necessary to change the actual
376 * virtual resource attributes (and modifying the schedule) on each
377 * node before the initiator of the distributed transaction knows the
378 * amount of available virtual resources. A renegotiation of a
379 * reserved virtual resource is possible, to harmonize for the
380 * available virtual resources in other parts of the system, before a
381 * final commitment is made.
388 * frsh_contract_negotiate_reservation()
390 * Negotiate a service contract, obtaining a virtual resource id that
391 * represents a reservation of resources, but without the right to use
392 * those resources until the reservation is committed via
393 * frsh_vres_commit_reservation. In particular, this virtual resource
394 * cannot be bound until committed, but renegotiations are allowed for
397 int frsh_contract_negotiate_reservation
398 (const frsh_contract_t *contract,
399 frsh_vres_id_t *vres);
402 * frsh_vres_commit_reservation()
404 * Commit the resources reserved for a virtual resource through a
405 * frsh_contract_negotiate_reservation operation. The effects of
406 * subsequent calls to frsh_contract_negotiate_reservation and
407 * frsh_vres_commit_reservation are equivalent to a single call to
408 * frsh_contract_negotiate.
410 int frsh_vres_commit_reservation
411 (const frsh_vres_id_t vres);
417 //////////////////////////////////////////////////////////////////////
418 // TRANSMISSION SERVICES
419 //////////////////////////////////////////////////////////////////////
422 * @defgroup txservices Transmission services
423 * @ingroup distributed
425 * These functions allow to create and manage endpoints for sending
426 * and receiving and to perform send and receive operations both
427 * synchronously (blocking) and asynchronously (non-blocking).
434 * frsh_send_endpoint_create()
436 * This operation creates a unidirectional stream input endpoint
437 * through which, after the corresponding binding, it is possible to
438 * send data to a unicast or multicast destination.
440 * @param[in] resource_id Identifier of the network referred in the
441 * network contract as a resource_id.
442 * @param[in] destination FRSH abstraction of the protocol address for the
444 * @param[in] stream_id Identifier of the communication channel between
445 * the nodes. Multiplexing is achieved by using
446 * different streams between the same nodes and the
448 * @param[in] queueing_info Queueing params of the endpoint (size and
450 * @param[in] protocol_info Optional protocol-dependent info.
451 * @param[out] endpoint Placeholder for the endpoint object.
453 int frsh_send_endpoint_create
454 (frsh_resource_id_t resource_id,
455 frsh_network_address_t destination,
456 frsh_stream_id_t stream_id,
457 frsh_send_endpoint_protocol_info_t protocol_info,
458 frsh_send_endpoint_t *endpoint);
461 * frsh_send_endpoint_get_params()
463 * This operation returns in the variables associated to the
464 * endpoint at creation time.
466 int frsh_send_endpoint_get_params
467 (const frsh_send_endpoint_t endpoint,
468 frsh_resource_id_t *resource_id,
469 frsh_network_address_t *destination,
470 frsh_stream_id_t *stream,
471 frsh_send_endpoint_protocol_info_t *protocol_info);
474 * frsh_send_endpoint_destroy()
476 * This operation eliminates any resources reserved for the referenced
477 * endpoint. Pending messages will be discarded and processor-vres
478 * waiting in a synchronous operation will be awoken with an error
481 int frsh_send_endpoint_destroy
482 (frsh_send_endpoint_t endpoint);
485 * frsh_send_endpoint_bind()
487 * This operation associates a send endpoint with a network vres,
488 * which means that messages sent through this endpoint will consume
489 * the vres's reserved bandwidth and its packets will be sent
490 * according to the contract established for that vres.
492 * If the endpoint is already bound to another vres, it is effectively
493 * unbound from it and bound to the specified one. However if a vres
494 * is already bound to another endpoint an error is returned.
496 * A consistency check is done in which the resource_id specified at
497 * endpoint creation must correspond to the resource_id of the vres
500 * @return 0 if successful \n
501 * FRSH_ERR_BAD_ARGUMENT if the endpoint or the vres are not
503 * FRSH_ERR_ALREADY_BOUND if the vres is already bound to some
504 * other send endpoint \n
505 * FRSH_ERR_WRONG_NETWORK if the vres network id is not the same
506 * as the one in the endpoint \n
508 int frsh_send_endpoint_bind
509 (frsh_vres_id_t vres,
510 frsh_send_endpoint_t endpoint);
513 * frsh_send_endpoint_unbind()
515 * This operation unbinds a send endpoint from a vres. Endpoints with
516 * no vres associated cannot be used to send data, and they stay in
517 * that state until they are either eliminated or bound again.
519 * @return 0 if successful \n
520 * FRSH_ERR_NOT_BOUND if the endpoint was not bound \n
522 int frsh_send_endpoint_unbind
523 (frsh_send_endpoint_t endpoint);
526 * frsh_send_endpoint_get_vres_id()
528 * This operation copies the id of the vres that is bound to the
529 * specified send endpoint into the variable pointed to by vres.
531 * @return 0 if successful \n
532 * FRSH_ERR_NOT_BOUND if the endpoint was not bound \n
533 * FRSH_ERR_BAD_ARGUMENT if the endpoint is not valid or vres
536 int frsh_send_endpoint_get_vres_id
537 (const frsh_send_endpoint_t endpoint,
538 frsh_vres_id_t *vres);
543 * This operation sends a message stored in msg and of length size
544 * through the given endpoint. The operation is non-blocking and
545 * returns immediately.
547 * An internal frsh service will schedule the sending of messages and
548 * implement the communications sporadic vres corresponding to the
549 * network vres bound to the given endpoint.
551 * @returns 0 if successful \n
552 * FRSH_ERR_BAD_ARGUMENT if endpoint is not valid \n
553 * FRSH_ERR_NOT_BOUND if endpoint is not bound to a valid vres \n
554 * FRSH_ERR_TOO_LARGE if the message is too large for the
555 * network protocol \n
556 * FRSH_ERR_BUFFER_FULL if the message has been discarded
557 * because the queue is full (and does not
558 * have the policy FRSH_QP_OLDEST \n
561 (const frsh_send_endpoint_t endpoint,
568 * Similar to previous function but now the sending vres gets blocked
569 * until the message is processed.
572 (const frsh_send_endpoint_t endpoint,
577 * frsh_send_endpoint_get_status()
579 * This function tells the number of messages still pending in the
580 * endpoint queue, whether the network is up or down with some
581 * optional information which is protocol_dependent.
583 int frsh_send_endpoint_get_status
584 (const frsh_send_endpoint_t endpoint,
585 int *number_pending_msg,
586 frsh_endpoint_network_status_t *network_status,
587 frsh_protocol_status_t *protocol_status);
590 * frsh_receive_endpoint_create()
592 * This operation creates a receive endpoint associated with a
593 * undirectional stream within a network interface of the node.
595 * Receiving endpoints are not bound to any network vres, this is
596 * because don't originate any traffic.
598 * Note that the protocol address is not needed for reception because
599 * it can be determined internally by FRSH based on the resource_id.
601 * Note also that messages may come from diferent originators.
603 * @param[in] resource_id Id of the network from which we listen.
604 * @param[in] stream_id Id of the stream within the network.
605 * @param[in] queueing_info Buffering information(queue size and
607 * @param[in] protocol_info Extra protocol info opaque for the
609 * @param[in] endpoin Placeholder for the endpoint object.
611 * @return 0 if successful \n
612 * FRSH_ERR_BAD_ARGUMENT if the stream or the network id are not
615 int frsh_receive_endpoint_create
616 (frsh_resource_id_t resource_id,
617 frsh_stream_id_t stream_id,
618 frsh_endpoint_queueing_info_t queueing_info,
619 frsh_receive_endpoint_protocol_info_t protocol_info,
620 frsh_receive_endpoint_t *endpoint);
623 * frsh_receive_endpoint_get_params()
625 * This operation returns in the variables associated to the
626 * endpoint at creation time.
628 int frsh_receive_endpoint_get_params
629 (const frsh_receive_endpoint_t endpoint,
630 frsh_resource_id_t *resource_id,
631 frsh_stream_id_t *stream,
632 frsh_endpoint_queueing_info_t *queueing_info,
633 frsh_receive_endpoint_protocol_info_t *protocol_info);
636 * frsh_receive_endpoint_destroy()
638 * This operation eliminates any resources reserved for the referenced
639 * endpoint. Pending messages will be discarded and processor-vres
640 * waiting in a synchronous operation will be awoken with an error
643 int frsh_receive_endpoint_destroy
644 (frsh_receive_endpoint_t endpoint);
648 * frsh_receive_sync()
650 * If there are no messages available in the specified receive endpoint
651 * this operation blocks the calling thread waiting for a message to be
654 * When a message is available, if its size is less than or
655 * equal to the buffer_size, the function stores it in the variable
656 * pointed to by buffer and puts the number of bytes received in the
657 * variable pointed to by message size.
659 * The function fails with FRSH_ERR_NO_SPACE if the buffersize is
660 * too small for the message received. In this case the message is
663 * Messages arriving at a destination buffer that is full will be
664 * silently discarded (details in the queueing policy of the
665 * endpoint). The application is responsible of reading the receive
666 * endpoints with appropriate regularity, or of using a sequence
667 * number or some other mechanism to detect any lost messages.
669 * @return 0 if successful \n
670 * FRSH_ERR_BAD_ARGUMENT if the endpoint is not valid, or if
671 * buffer or message_size are NULL.\n
672 * FRSH_ERR_NO_SPACE if the message size is bigger than the
675 int frsh_receive_sync
676 (const frsh_receive_endpoint_t endpoint,
679 size_t *message_size,
680 frsh_network_address_t *from);
683 * frsh_receive_async()
685 * This operation is similar to the previous one but it works in a non
686 * blocking (asynchronous) fashion. If no message is available it
687 * returns with error FRSH_NO_MESSAGE.
689 * @return 0 if successful \n
690 * FRSH_ERR_BAD_ARGUMENT if the endpoint is not valid, or if
691 * buffer or message_size are NULL \n
692 * FRSH_NO_MESSAGE if no messages are available in the queue \n
693 * FRSH_ERR_NO_SPACE if the message size is bigger than the
696 int frsh_receive_async
697 (const frsh_receive_endpoint_t endpoint,
700 size_t *message_size,
701 frsh_network_address_t *from);
705 * frsh_receive_endpoint_get_status
707 * This function tells the number of messages still pending in the
708 * endpoint queue, whether the network is up or down and some optional
709 * information which is protocol dependent.
711 int frsh_receive_endpoint_get_status
712 (const frsh_receive_endpoint_t endpoint,
713 int *number_pending_messages,
714 frsh_endpoint_network_status_t *network_status,
715 frsh_protocol_status_t *protocol_status);
721 #endif // _FRSH_DISTRIBUTED_H_