====== GAIA APIs ======
In the following of this page it will be described the Application Programming Interfaces (APIs) provided by the GAIA framework. The JAVA and the C bindings are only slightly different, mainly due to the Java Native Interface implementation. Each interface will be briefly described and commented, for the implementation details and the general structure of a simulated model please refer to the examples provided in the binary package. Many acronyms will be used in the following: all of them have been described in the [[PADS:glossary|glossary]].
===== JAVA bindings =====
int GAIA_Initialize (int max_objs_count, int nlp, String RandFile, String cname, String sima_host_name, int sima_port);
void GAIA_Finalize ( );
void GAIA_SetFstID (int first_id);
void GAIA_SetHistory (int new_size);
void GAIA_SetMF (int migr_factor);
void GAIA_SetMigration (int state);
void GAIA_SetLoadBalancing (int state);
double GAIA_GetStep ( );
int GAIA_Register (int migrable);
double GAIA_TimeAdvance ();
void GAIA_Migrate (int id, String data, int size);
void GAIA_ByteMigrate (int id, byte[] data, int size);
void GAIA_Send (int obj_src, int obj_dest, double Ts, String Msg, int Size);
void GAIA_ByteSend (int obj_src, int obj_dest, double Ts, byte[] Msg, int Size);
void GAIA_Broadcast (int obj_src, double Ts, String Msg, int Size);
void GAIA_ByteBroadcast (int obj_src, double Ts, byte[] Msg, int Size);
String GAIA_Receive (int maxlen);
byte[] GAIA_ByteReceive (int maxlen);
void GAIA_GetStatistics (int local, int remote, int migrations);
==== Simulation Management ====
=== GAIA_Initialize() ===
int GAIA_Initialize (int max_objs_count, int nlp, String RandFile, String cname, String sima_host_name, int sima_port);
**Parameters**:
* int **max_objs_count**: Maximum number of SE in the whole simulation;
* int **nlp**: Number of LPs defined in the simulation;
* String **RandFile**: Name of the file containing the seeds for the random generator;
* String **cname**: Canonical name of the LP (it can be empty or void);
* String **sima_host_name**: Hostname or IP address of the SIMA server;
* int **sima_port**: Port number of the SIMA server.
**Description**:
Initialization of the GAIA framework: it is used by each LP to enter in the simulation.
**Notes**:
At runtime, more than **max_objs_count** can be defined in the simulation but with a performance loss.
**Return value:**
Returns the LP identifier.
----
=== GAIA_Finalize() ===
void GAIA_Finalize ( );
**Parameters**:
//none//
**Description**:
Shutdown of the GAIA framework: it is used by each LP to end the simulation.
**Notes**:
//none//
**Return value:**
//none//
----
=== GAIA_SetFstID() ===
void GAIA_SetFstID (int first_id);
**Parameters**:
* int **first_id**: In the local LP, it defines the starting identifier (progressive numbers) to be used as SE handler;
**Description**:
A unique descriptor (unique in the whole simulation) is assigned to each registered SE. This function is used to set the starting descriptor to be used in the local LP. At simulation bootstrap each LP manages a range of descriptors, that are used to register the locally instantiated SE. It worth noting that at runtime the SE descriptor **can not** be used to identify what LP is managing the SE. This is due to the adaptive migration mechanism that dynamically re-allocates the SEs among the distributed execution unit.
**Notes**:
//none//
**Return value:**
//none//
----
=== GAIA_GetStep() ===
double GAIA_GetStep ( );
**Parameters**:
//none//
**Description**:
Returns the length of the timestep used in the simulation. This parameter is initialized using the **GLOBAL_LA** parameters as defined in the file "**channels.txt**". For example, GLOBAL_LA=1 defines a global lookahead (timestep) of 1 time-unit, and GLOBAL_LA=0.01 is to define timesteps with a length of 1/100 of time-unit.
**Notes**:
//none//
**Return value:**
The timestep length (double).
----
=== GAIA_Register() ===
int GAIA_Register (int migrable);
**Parameters**:
* int **migrable**: MIGRABLE if the SE can be migrated, NOT_MIGRABLE if the SE can not be relocated;
**Description**:
This API is used to register a SE, the runtime returns a descriptor that will be used to identify the SE. The registration of a SE is required to extend the scope of the SE outside the local LP (to the whole simulation). Only after the registration the SE will be able to send and receive messages, furthermore it could be involved in the migration and load balancing mechanisms.
**Notes**:
The registration of a SE is an event that has to be propagated to the whole simulator. Therefore, if the registration of a SE happens at timestep **t**, only starting from timestep **t+1** will be possible to send or receive messages regarding such SE. For example, it is NOT possible to register a new SE at timestep **t** and to immediately send a message from this SE in the same timestep.
**Return value:**
The descriptor (integer) of the SE.
----
=== GAIA_TimeAdvance() ===
double GAIA_TimeAdvance ();
**Parameters**:
//none//
**Description**:
It is used by the LP to notify to the runtime that the current timestep is ended, and therefore, the local LP is ready to start the next timestep. The LP will remain blocked until the runtime will enable the transition to the next timestep.
**Notes**:
//none//
**Return value:**
Returns the next timestep value (double).
----
==== Migration ====
=== GAIA_Migrate() ===
void GAIA_Migrate (int id, String data, int size);
**Parameters**:
* int **id**: Identifier of the migrating SE;
* String **data**: A string containing the internal state of the SE;
* int **size**: String size;
**Description**:
It is used by a local LP to migrate a SE to a remote LP. The local LP is **not** free to define what SEs should be migrated. During the simulation execution, the migration mechanism defines what SEs have to be migrated and informs the LP using a "NOTIF_MIGR" message. The other LPs that are not directly involved in the migration will be informed of the event with a "NOTIF_MIGR_EXT".
**Notes**:
* The "NOTIF_MIGR" message and the related migration are **mandatory**. The LPs cannot independently migrate any SE without previously receiving a "NOTIF_MIGR" message. This migration of "notified" SEs have to be done at the end of the timestep in which is received the notification.
* The GAIA_Migrate() is implemented using a "EXEC_MIGR" message. Therefore, the LP that receives a message of this type is receiving a migrating Simulated Entity.
**Return value:**
//none//
----
=== GAIA_ByteMigrate() ===
void GAIA_ByteMigrate (int id, byte[] data, int size);
**Parameters**:
* int **id**: Identifier of the migrating SE;
* byte[] **data**: A byte-array containing the internal state of the SE;
* int **size**: String size;
**Description**:
It is used by a local LP to migrate a SE to a remote LP. The local LP is **not** free to define what SEs should be migrated. During the simulation execution, the migration mechanism defines what SEs have to be migrated and informs the LP using a "NOTIF_MIGR" message. The other LPs that are not directly involved in the migration will be informed of the event with a “NOTIF_MIGR_EXT”.
**Notes**:
* The "NOTIF_MIGR" message and the related migration are **mandatory**. The LPs cannot independently migrate any SE without previously receiving a "NOTIF_MIGR" message. This migration of “notified” SEs have to be done at the end of the timestep in which is received the notification.
* The GAIA_ByteMigrate() is implemented using a “EXEC_MIGR” message. Therefore, the LP that receives a message of this type is receiving a migrating Simulated Entity.
* This API has the exactly the same semantic of GAIA_Migrate(). For performance reasons, in this case the SE state is contained in an array instead of a String.
**Return value:**
//none//
----
=== GAIA_SetCountDown() ===
void GAIA_SetCountDown (int events);
**Parameters**:
* int **events**: interval of events before a new evaluation of the heuristic.
**Description**:
The migration heuristic 3 (MIGR_E3) is based on the events history but differently from MIGR_E2 it is triggered only after a given number of events (unicast messages sent by the SE). This API can be used to modify this threshold that is also called E3_EVENT_COUNTDOWN.
**Notes**:
The default value of E3_EVENT_COUNTDOWN is 30 events.
**Return value:**
//none//
----
=== GAIA_SetMT() ===
void GAIA_SetMT (int new_size);
**Parameters**:
* int **new_size**: it defines the threshold of the migration heuristic;
**Description**:
The Migration Threshold (MT) is a value used to limit the migration rate of SEs (default value = 10). Each SE can evaluate the migration heuristic only if its counter has a value that is bigger than MT. At bootstrap and at each migration the counter is re-initialized. The detailed semantic of the counter depends on what migration heuristic is used.
^ Migration heuristic ^ SetHistory() semantic ^
| MIGR_OFF | //none// |
| MIGR_ON / MIGR_E1 | Threshold: number of timesteps (since the last reset) |
| MIGR_E2 | Threshold: number of UNICAST events generated (since the last reset) |
\\
**Notes**:
Some degree of randomization is included in the mechanism to reduce the "wave effects" of migrating entities.
**Return value:**
//none//
----
=== GAIA_SetMF() ===
void GAIA_SetMF (float migr_factor);
**Parameters**:
* float **migr_factor**: it defines the relocation threshold of the migration heuristic;
**Description**:
All the implemented migration heuristics are based on the evaluation of the outbound UNICAST traffic generated by each Simulated Entity. The migration factor is a tuning parameters of the heuristics: a low value would increase the number of migrations, conversely a higher value would reduce the number of migrations (default value = 3).
**Notes**:
The number of migrations is a trade-off between a high LCR and the overhead due to migrations.
**Return value:**
//none//
----
=== GAIA_SetHistorySlots() ===
void GAIA_SetHistorySlots (int history_slots);
**Parameters**:
* int **history_slots**: number of slots considered in the history matrix;
**Description**:
The migration heuristic 1 (MIGR_ON / MIGR_E1) uses a sliding window mechanism to evaluate the communication pattern of each SE (HISTORY_SLOTS, default value = 4). The number of slots composing the sliding window can be defined at the simulation bootstrap using this API.
**Notes**:
Too many slots would reduce the reactivity of the migration mechanism. Conversely, a too small value would cause an excessive number of migrations.
**Return value:**
//none//
----
=== GAIA_SetEventHistorySize() ===
void GAIA_SetEventHistorySize (int size);
**Parameters**:
* int **size**: number of events (FIFO order) considered by the migration heuristic 2 and 3.
**Description**:
The migration heuristics 2 and 3 (MIGR_E2 / MIGR_E3) are based on the a sliding window with the last E2_EVENT_HISTORY_SIZE messages sent by the SE (default value 100). The number of events composing the sliding window can be defined at the simulation bootstrap using this API.
**Notes**:
//none//
**Return value:**
//none//
----
=== GAIA_SetMigration() ===
void GAIA_SetMigration (int state);
**Parameters**:
* int **state**: it selects the migration heuristic, {MIGR_OFF, MIGR_ON, MIGR_E1, MIGR_E2, MIGR_E3}, default MIGR_OFF;
**Description**:
All the implemented migration heuristics are based on the evaluation of the outbound UNICAST traffic generated by each SE (also called events).
^ Migration heuristic ^ Description ^ Pros ^ Cons ^
| MIGR_OFF | //none// | none | none |
| MIGR_ON / MIGR_E1 | The heuristic is evaluated each timestep. It is based on the last E1_HISTORY_SLOTS timesteps of the simulation. It is implemented a sliding window approach that at each step throws away the oldest events and inserts the more recent ones | Very high LCR \\ Well-suited for communication intensive models | In some cases, relevant overhead |
| MIGR_E2 | The heuristic is evaluated each timestep. It is based on the a sliding window with the last E2_EVENT_HISTORY_SIZE messages sent by the SE | Well suited for simulations in which the communication pattern of entities changes frequently | In some cases, relevant overhead |
| MIGR_E3 | The heuristic is evaluated only if the SE has sent at least E3_EVENT_COUNTDOWN events after the last evaluation. The rest of the mechanism is the same as MIGR_E2 | Well suited for simulations with a very high number of SEs and in which the communication pattern of entities changes frequently | In some cases slow convergence and slightly lower LCR |
\\
**Notes**:
For tuning of the heuristics please see:
* GAIA_SetMT(): for an introduction to the Migration Threshold, that is a mechanism that reduces the migration rate of SEs;
* GAIA_SetMF(): for an introduction to the Migration Factor, that is the parameter that is used to evaluate if and where activate the migration mechanism for a SE;
* E1_HISTORY_SLOTS, default value = 4. It can be modified in the simulation setup using the GAIA_SetHistorySlots() API.
* E2_EVENT_HISTORY_SIZE, default value = 100. It is how many events (FIFO order) are considered by migration heuristics 2 and 3. This value can be changed using the GAIA_SetEventHistorySize() API.
* E3_EVENT_COUNTDOWN, default value = 30. It is the interval of events before a new evaluation of the heuristic. This value can be changed using the GAIA_SetCountDown() API.
**Return value:**
//none//
----
==== Load Balancing ====
=== GAIA_SetLoadBalancing() ===
void GAIA_SetLoadBalancing (int state);
**Parameters**:
* int **state**: it turns ON and OFF the load balancing mechanism provided by GAIA+, {LOAD_ON, LOAD_OFF}, default LOAD_OFF;
**Description**:
The GAIA+ mechanism automatically reacts to heterogeneous hardware (in terms of performances) and background load, dynamically reallocating the SE from the "slow" to the "fast" LPs.
**Notes**:
//none//
**Return value:**
//none//
----
==== Communication ====
=== GAIA_Send() ===
void GAIA_Send (int obj_src, int obj_dest, double Ts, String Msg, int Size);
**Parameters**:
* int **obj_src**: Identifier of the SE sending the message;
* int **obj_dest**: Identifier of the SE destination of the message;
* double **Ts**: Time-stamp of the message;
* String **Msg**: Body of the message;
* int **Size**: Message size;
**Description**:
It used to send a message from a local SE to a remote SE. The message is contained in a string and is time-stamped.
**Notes**:
The message time-stamp has to respect the constraints given by the synchronization algorithm (timestepped).
**Return value:**
//none//
----
=== GAIA_ByteSend() ===
void GAIA_ByteSend (int obj_src, int obj_dest, double Ts, byte[] Msg, int Size);
**Parameters**:
* int **obj_src**: Identifier of the SE sending the message;
* int **obj_dest**: Identifier of the SE destination of the message;
* double **Ts**: Time-stamp of the message;
* byte[] **Msg**: Body of the message;
* int **Size**: Message size;
**Description**:
It used to send a message from a local SE to a remote SE. The message is contained in a byte-array and is time-stamped.
**Notes**:
* The message time-stamp has to respect the constraints given by the synchronization algorithm (timestepped).
* This API has the exactly the same semantic of GAIA_Send(). For performance reasons, in this case the message is contained in an array instead of a String.
**Return value:**
//none//
----
=== GAIA_Broadcast() ===
void GAIA_Broadcast (int obj_src, double Ts, String Msg, int Size);
**Parameters**:
* int **obj_src**: Identifier of the SE sending the message;
* double **Ts**: Time-stamp of the message;
* String **Msg**: Body of the message;
* int **Size**: Message size;
**Description**:
It used to send a message from a local SE to all the SE in the simulation (the message is delivered also to the SE that is originating the message). The message is contained in a string and is time-stamped.
**Notes**:
* The message time-stamp has to respect the constraints given by the synchronization algorithm (timestepped).
* Given that the message is delivered also to the SE that is originating it, it must be carefully managed to avoid loops.
**Return value:**
//none//
----
=== GAIA_ByteBroadcast() ===
void GAIA_ByteBroadcast (int obj_src, double Ts, byte[] Msg, int Size);
**Parameters**:
* int **obj_src**: Identifier of the SE sending the message;
* double **Ts**: Time-stamp of the message;
* byte[] **Msg**: Body of the message;
* int **Size**: Message size;
**Description**:
It used to send a message from a local SE to all the SE in the simulation (the message is delivered also to the SE that is originating the message). The message is contained in a byte-array and is time-stamped.
**Notes**:
* The message time-stamp has to respect the constraints given by the synchronization algorithm (timestepped).
* Given that the message is delivered also to the SE that is originating it, it must be carefully managed to avoid loops.
* This API has the exactly the same semantic of GAIA_Broadcast(). For performance reasons, in this case the message is contained in an array instead of a String.
**Return value:**
//none//
----
=== GAIA_Receive() ===
String GAIA_Receive(int maxlen);
**Parameters**:
* int **maxlen**: Max length of the received message;
**Description**:
It is used to receive messages, a string containing the message body is returned. The message type is set in the **type** variable.
**Notes**:
Defined message type are:
* **REGISTER**: a new SE has been registered;
* **NOTIF_MIGR**: notify of migration, the SE indicated by the runtime will have to be migrated (mandatory) at the end of the current timestep;
* **NOTIF_MIGR_EXT**: external notify of migration, an external SE has been indicated as migrating, the local LP is not directly involved in the migration;
* **EXEC_MIGR**: a SE is arriving in the LP, the message contains its state;
* **EOS**: End-Of-Step, the LP is authorized to move to the next step;
* **UNSET**: Model dependent message, it has been generated by the model and it is not related to the GAIA framework.
**Return value:**
Returns the message (String).
----
=== GAIA_ByteReceive() ===
byte[] GAIA_ByteReceive(int maxlen);
**Parameters**:
* int **maxlen**: Max length of the received message;
**Description**:
It is used to receive messages, a byte-array containing the message body is returned. The message type is set in the **type** variable.
**Notes**:
Defined message type are:
* **REGISTER**: a new SE has been registered;
* **NOTIF_MIGR**: notify of migration, the SE indicated by the runtime will have to be migrated (mandatory) at the end of the current timestep;
* **NOTIF_MIGR_EXT**: external notify of migration, an external SE has been indicated as migrating, the local LP is not directly involved in the migration;
* **EXEC_MIGR**: a SE is arriving in the LP, the message contains its state;
* **EOS**: End-Of-Step, the LP is authorized to move to the next step;
* **UNSET**: Model dependent message, it has been generated by the model and it is not related to the GAIA framework.
This API has the exactly the same semantic of GAIA_Receive(). For performance reasons, in this case the returned message is contained in an array instead of a String.
**Return value:**
Returns the message (byte-array).
----
==== Statistics ====
=== GAIA_GetStatistics() ===
void GAIA_GetStatistics();
**Parameters**:
//none//
**Description**:
The GAIA framework provides a way to access some runtime parameters from the model layer. Step-by-step are provided the total number of local messages sent in the whole simulation (intra-LP), the total number of remote messages (inter-LPs) and the total number of migrations that have been executed. The data is collected by the LP_0 (that is the first LP that has been started).
**Notes**:
* The data are updated each timestep.
* Calling the method from a LP that is not the first that has been started leads to null results.
* The output will be placed in the following variables already defined in the JAVA environment:
* int **local**: number of local interactions in the last step, in the whole simulation
* int **remote**: number of remote interactions in the last step, in the whole simulation
* int **migrations**: number of migrations performed in the last step, in the whole simulation
**Return value:**
//none//
----
===== C bindings =====
int GAIA_Initialize (int, int, char *, char *, char *, int);
void GAIA_Finalize ();
void GAIA_SetFstID (int);
void GAIA_SetHistory (int);
void GAIA_SetMF (float);
void GAIA_SetMT (unsigned int);
void GAIA_SetCountDown ( int );
void GAIA_SetHistorySlots (int );
void GAIA_SetEventHistorySize (int );
void GAIA_SetMigration (int);
void GAIA_SetLoadBalancing (int);
int GAIA_Register (int);
double GAIA_GetStep ();
double GAIA_TimeAdvance ();
void GAIA_Migrate (int, void *, int);
void GAIA_Send (int, int, TM_Time, void *, int);
void GAIA_Broadcast (int, TM_Time, void *, int);
char GAIA_Receive (int *, int *, TM_Time *, void *, int *);
void GAIA_GetStatistics (int *, int *, int *);
Please refer to the description of the Java binding to have an introduction to the provided APIs.