Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
LUA: Added support for backbone, host_link and ASroute
[simgrid.git] / src / bindings / lua / simgrid_lua.c
1 /* Copyright (c) 2010-2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /* SimGrid Lua bindings                                                     */
8
9 #include "lua_private.h"
10 #include "lua_state_cloner.h"
11 #include "lua_utils.h"
12 #include "xbt.h"
13 #include "simgrid/msg.h"
14 #include "simgrid/simdag.h"
15 #include "surf/surfxml_parse.h"
16 #include <lauxlib.h>
17
18
19 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua, bindings, "Lua Bindings");
20
21 static lua_State* sglua_maestro_state;
22
23 int luaopen_simgrid(lua_State *L);
24 static void sglua_register_c_functions(lua_State *L);
25 static int run_lua_code(int argc, char **argv);
26
27 /* ********************************************************************************* */
28 /*                                  simgrid API                                      */
29 /* ********************************************************************************* */
30
31 /**
32  * \brief Deploys your application.
33  * \param L a Lua state
34  * \return number of values returned to Lua
35  *
36  * - Argument 1 (string): name of the deployment file to load
37  */
38 static int launch_application(lua_State* L) {
39
40   const char* file = luaL_checkstring(L, 1);
41   MSG_function_register_default(run_lua_code);
42   MSG_launch_application(file);
43   return 0;
44 }
45
46
47 /**
48  * \brief Creates the platform.
49  * \param L a Lua state
50  * \return number of values returned to Lua
51  *
52  * - Argument 1 (string): name of the platform file to load
53  */
54 static int create_environment(lua_State* L) {
55
56   const char* file = luaL_checkstring(L, 1);
57   XBT_DEBUG("Loading environment file %s", file);
58   MSG_create_environment(file);
59   return 0;
60 }
61
62 /**
63  * \brief Prints a log string with debug level.
64  * \param L a Lua state
65  * \return number of values returned to Lua
66  *
67  * - Argument 1 (string): the text to print
68  */
69 static int debug(lua_State* L) {
70
71   const char* str = luaL_checkstring(L, 1);
72   XBT_DEBUG("%s", str);
73   return 0;
74 }
75
76 /**
77  * \brief Prints a log string with info level.
78  * \param L a Lua state
79  * \return number of values returned to Lua
80  *
81  * - Argument 1 (string): the text to print
82  */
83 static int info(lua_State* L) {
84
85   const char* str = luaL_checkstring(L, 1);
86   XBT_INFO("%s", str);
87   return 0;
88 }
89
90 /**
91  * \brief Runs your application.
92  * \param L a Lua state
93  * \return number of values returned to Lua
94  */
95 static int run(lua_State*  L) {
96
97   MSG_main();
98   return 0;
99 }
100
101 /**
102  * \brief Returns the current simulated time.
103  * \param L a Lua state
104  * \return number of values returned to Lua
105  *
106  * - Return value (number): the simulated time
107  */
108 static int get_clock(lua_State* L) {
109
110   lua_pushnumber(L, MSG_get_clock());
111   return 1;
112 }
113
114 /**
115  * \brief Cleans the simulation.
116  * \param L a Lua state
117  * \return number of values returned to Lua
118  */
119 static int simgrid_gc(lua_State * L)
120 {
121   // There is no need to cleanup the C world anymore, as it gets cleaned at system process closing automatically
122   // Maybe at some point we'll want to reintroduce this, for example when encapsulating the simulation properly
123   //if (sglua_is_maestro(L)) {
124   //  MSG_clean();
125   //}
126   return 0;
127 }
128
129 /*
130  * Register platform for MSG
131  */
132 static int msg_register_platform(lua_State * L)
133 {
134   /* Tell Simgrid we don't wanna use its parser */
135   //surf_parse = console_parse_platform;
136   surf_parse_reset_callbacks();
137   MSG_create_environment(NULL);
138   return 0;
139 }
140
141 /*
142  * Register platform for Simdag
143  */
144 static int sd_register_platform(lua_State * L)
145 {
146   //surf_parse = console_parse_platform_wsL07;
147   surf_parse_reset_callbacks();
148   SD_create_environment(NULL);
149   return 0;
150 }
151
152 /**
153  * Register application for MSG
154  */
155 static int msg_register_application(lua_State * L)
156 {
157   MSG_function_register_default(run_lua_code);
158   //surf_parse = console_parse_application;
159   MSG_launch_application(NULL);
160   return 0;
161 }
162
163 static int console_init_application(lua_State *L) {
164   MSG_function_register_default(run_lua_code);
165   SIMIX_init_application();
166   return 0;
167 }
168
169
170 static const luaL_Reg simgrid_functions[] = {
171   {"create_environment", create_environment},
172   {"launch_application", launch_application},
173   {"debug", debug},
174   {"info", info},
175   {"run", run},
176   {"get_clock", get_clock},
177   /* short names */
178   {"platform", create_environment},
179   {"application", launch_application},
180   /* methods to bypass XML parser */
181   {"msg_register_platform", msg_register_platform},
182   {"sd_register_platform", sd_register_platform},
183   {"msg_register_application", msg_register_application},
184   {"init_application", console_init_application},
185   {NULL, NULL}
186 };
187
188 /* ********************************************************************************* */
189 /*                           module management functions                             */
190 /* ********************************************************************************* */
191
192 #define LUA_MAX_ARGS_COUNT 10   /* maximum amount of arguments we can get from lua on command line */
193
194 /**
195  * \brief Opens the simgrid Lua module.
196  *
197  * This function is called automatically by the Lua interpreter when some
198  * Lua code requires the "simgrid" module.
199  *
200  * \param L the Lua state
201  */
202
203 int luaopen_simgrid(lua_State *L)
204 {
205   XBT_DEBUG("luaopen_simgrid *****");
206
207   /* Get the command line arguments from the lua interpreter */
208   char **argv = xbt_malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
209   int argc = 1;
210   argv[0] = (char *) "/usr/bin/lua";    /* Lie on the argv[0] so that the stack dumping facilities find the right binary. FIXME: what if lua is not in that location? */
211
212   lua_getglobal(L, "arg");
213   /* if arg is a null value, it means we use lua only as a script to init platform
214    * else it should be a table and then take arg in consideration
215    */
216   if (lua_istable(L, -1)) {
217     int done = 0;
218     while (!done) {
219       argc++;
220       lua_pushinteger(L, argc - 2);
221       lua_gettable(L, -2);
222       if (lua_isnil(L, -1)) {
223         done = 1;
224       } else {
225         xbt_assert(lua_isstring(L, -1),
226                     "argv[%d] got from lua is no string", argc - 1);
227         xbt_assert(argc < LUA_MAX_ARGS_COUNT,
228                     "Too many arguments, please increase LUA_MAX_ARGS_COUNT in %s before recompiling SimGrid if you insist on having more than %d args on command line",
229                     __FILE__, LUA_MAX_ARGS_COUNT - 1);
230         argv[argc - 1] = (char *) luaL_checkstring(L, -1);
231         lua_pop(L, 1);
232         XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
233       }
234     }
235     argv[argc--] = NULL;
236
237     /* Initialize the MSG core */
238     XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
239   }
240   MSG_init(&argc, argv);
241   MSG_process_set_data_cleanup((void_f_pvoid_t) lua_close);
242
243   /* Keep the context mechanism informed of our lua world today */
244   sglua_maestro_state = L;
245
246   /* initialize access to my tables by children Lua states */
247   lua_newtable(L);
248   lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.maestro_tables");
249
250   sglua_register_c_functions(L);
251
252   return 1;
253 }
254
255 /**
256  * \brief Returns whether a Lua state is the maestro state.
257  * \param L a Lua state
258  * \return true if this is maestro
259  */
260 int sglua_is_maestro(lua_State* L) {
261   return L == sglua_maestro_state;
262 }
263
264 /**
265  * \brief Returns the maestro state.
266  * \return the maestro Lua state
267  */
268 lua_State* sglua_get_maestro(void) {
269   return sglua_maestro_state;
270 }
271
272 /**
273  * \brief Makes the core functions available to the Lua world.
274  * \param L a Lua world
275  */
276 static void sglua_register_core_functions(lua_State *L)
277 {
278   /* register the core C functions to lua */
279   luaL_register(L, "simgrid", simgrid_functions);
280                                   /* simgrid */
281
282   /* set a finalizer that cleans simgrid, by adding to the simgrid module a
283    * dummy userdata whose __gc metamethod calls MSG_clean() */
284   lua_newuserdata(L, sizeof(void*));
285                                   /* simgrid udata */
286   lua_newtable(L);
287                                   /* simgrid udata mt */
288   lua_pushcfunction(L, simgrid_gc);
289                                   /* simgrid udata mt simgrid_gc */
290   lua_setfield(L, -2, "__gc");
291                                   /* simgrid udata mt */
292   lua_setmetatable(L, -2);
293                                   /* simgrid udata */
294   lua_setfield(L, -2, "__simgrid_loaded");
295                                   /* simgrid */
296   lua_pop(L, 1);
297                                   /* -- */
298 }
299
300 /**
301  * \brief Creates the simgrid module and make it available to Lua.
302  * \param L a Lua world
303  */
304 static void sglua_register_c_functions(lua_State *L)
305 {
306   sglua_register_core_functions(L);
307   sglua_register_task_functions(L);
308   sglua_register_comm_functions(L);
309   sglua_register_host_functions(L);
310   sglua_register_process_functions(L);
311   sglua_register_platf_functions(L);
312 }
313
314 /**
315  * \brief Runs a Lua function as a new simulated process.
316  * \param argc number of arguments of the function
317  * \param argv name of the Lua function and array of its arguments
318  * \return result of the function
319  */
320 static int run_lua_code(int argc, char **argv)
321 {
322   XBT_DEBUG("Run lua code %s", argv[0]);
323
324   /* create a new state, getting globals from maestro */
325   lua_State *L = sglua_clone_maestro();
326   MSG_process_set_data(MSG_process_self(), L);
327
328   /* start the function */
329   lua_getglobal(L, argv[0]);
330   xbt_assert(lua_isfunction(L, -1),
331               "There is no Lua function with name `%s'", argv[0]);
332
333   /* push arguments onto the stack */
334   int i;
335   for (i = 1; i < argc; i++)
336     lua_pushstring(L, argv[i]);
337
338   /* call the function */
339   XBT_ATTRIB_UNUSED int err;
340   err = lua_pcall(L, argc - 1, 1, 0);
341   xbt_assert(err == 0, "Error running function `%s': %s", argv[0],
342               lua_tostring(L, -1));
343
344   /* retrieve result */
345   int res = 1;
346   if (lua_isnumber(L, -1)) {
347     res = lua_tonumber(L, -1);
348     lua_pop(L, 1);              /* pop returned value */
349   }
350
351   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
352
353   return res;
354 }
355
356 /**
357  * \brief Returns a string corresponding to an MSG error code.
358  * \param err an MSG error code
359  * \return a string describing this error
360  */
361 const char* sglua_get_msg_error(msg_error_t err) {
362
363   static const char* msg_errors[] = {
364       NULL,
365       "timeout",
366       "transfer failure",
367       "host failure",
368       "task canceled"
369   };
370
371   return msg_errors[err];
372 }