Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Try to activate coverity for simgrid
[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 static int error(lua_State* L) {
91
92   const char* str = luaL_checkstring(L, 1);
93   XBT_ERROR("%s", str);
94   return 0;
95 }
96
97 static int critical(lua_State* L) {
98
99   const char* str = luaL_checkstring(L, 1);
100   XBT_CRITICAL("%s", str);
101   return 0;
102 }
103
104 /**
105  * \brief Runs your application.
106  * \param L a Lua state
107  * \return number of values returned to Lua
108  */
109 static int run(lua_State*  L) {
110
111   MSG_main();
112   return 0;
113 }
114
115 /**
116  * \brief Returns the current simulated time.
117  * \param L a Lua state
118  * \return number of values returned to Lua
119  *
120  * - Return value (number): the simulated time
121  */
122 static int get_clock(lua_State* L) {
123
124   lua_pushnumber(L, MSG_get_clock());
125   return 1;
126 }
127
128 /**
129  * \brief Cleans the simulation.
130  * \param L a Lua state
131  * \return number of values returned to Lua
132  */
133 static int simgrid_gc(lua_State * L)
134 {
135   // There is no need to cleanup the C world anymore, as it gets cleaned at system process closing automatically
136   // Maybe at some point we'll want to reintroduce this, for example when encapsulating the simulation properly
137   //if (sglua_is_maestro(L)) {
138   //  MSG_clean();
139   //}
140   return 0;
141 }
142
143 /*
144  * Register platform for MSG
145  */
146 static int msg_register_platform(lua_State * L)
147 {
148   /* Tell Simgrid we don't wanna use its parser */
149   //surf_parse = console_parse_platform;
150   surf_parse_reset_callbacks();
151   MSG_create_environment(NULL);
152   return 0;
153 }
154
155 /*
156  * Register platform for Simdag
157  */
158 static int sd_register_platform(lua_State * L)
159 {
160   //surf_parse = console_parse_platform_wsL07;
161   surf_parse_reset_callbacks();
162   SD_create_environment(NULL);
163   return 0;
164 }
165
166 /**
167  * Register application for MSG
168  */
169 static int msg_register_application(lua_State * L)
170 {
171   MSG_function_register_default(run_lua_code);
172   //surf_parse = console_parse_application;
173   MSG_launch_application(NULL);
174   return 0;
175 }
176
177 static int console_init_application(lua_State *L) {
178   MSG_function_register_default(run_lua_code);
179   SIMIX_init_application();
180   return 0;
181 }
182
183
184 static const luaL_Reg simgrid_functions[] = {
185   {"create_environment", create_environment},
186   {"launch_application", launch_application},
187   {"debug", debug},
188   {"info", info},
189   {"critical", critical},
190   {"error", error},
191   {"run", run},
192   {"get_clock", get_clock},
193   /* short names */
194   {"platform", create_environment},
195   {"application", launch_application},
196   /* methods to bypass XML parser */
197   {"msg_register_platform", msg_register_platform},
198   {"sd_register_platform", sd_register_platform},
199   {"msg_register_application", msg_register_application},
200   {"init_application", console_init_application},
201   {NULL, NULL}
202 };
203
204 /* ********************************************************************************* */
205 /*                           module management functions                             */
206 /* ********************************************************************************* */
207
208 #define LUA_MAX_ARGS_COUNT 10   /* maximum amount of arguments we can get from lua on command line */
209
210 /**
211  * \brief Opens the simgrid Lua module.
212  *
213  * This function is called automatically by the Lua interpreter when some
214  * Lua code requires the "simgrid" module.
215  *
216  * \param L the Lua state
217  */
218
219 int luaopen_simgrid(lua_State *L)
220 {
221   XBT_DEBUG("luaopen_simgrid *****");
222
223   /* Get the command line arguments from the lua interpreter */
224   char **argv = xbt_malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
225   int argc = 1;
226   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? */
227
228   lua_getglobal(L, "arg");
229   /* if arg is a null value, it means we use lua only as a script to init platform
230    * else it should be a table and then take arg in consideration
231    */
232   if (lua_istable(L, -1)) {
233     int done = 0;
234     while (!done) {
235       argc++;
236       lua_pushinteger(L, argc - 2);
237       lua_gettable(L, -2);
238       if (lua_isnil(L, -1)) {
239         done = 1;
240       } else {
241         xbt_assert(lua_isstring(L, -1),
242                     "argv[%d] got from lua is no string", argc - 1);
243         xbt_assert(argc < LUA_MAX_ARGS_COUNT,
244                     "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",
245                     __FILE__, LUA_MAX_ARGS_COUNT - 1);
246         argv[argc - 1] = (char *) luaL_checkstring(L, -1);
247         lua_pop(L, 1);
248         XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
249       }
250     }
251     argv[argc--] = NULL;
252
253     /* Initialize the MSG core */
254     XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
255   }
256   MSG_init(&argc, argv);
257   MSG_process_set_data_cleanup((void_f_pvoid_t) lua_close);
258
259   /* Keep the context mechanism informed of our lua world today */
260   sglua_maestro_state = L;
261
262   /* initialize access to my tables by children Lua states */
263   lua_newtable(L);
264   lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.maestro_tables");
265
266   sglua_register_c_functions(L);
267
268   return 1;
269 }
270
271 /**
272  * \brief Returns whether a Lua state is the maestro state.
273  * \param L a Lua state
274  * \return true if this is maestro
275  */
276 int sglua_is_maestro(lua_State* L) {
277   return L == sglua_maestro_state;
278 }
279
280 /**
281  * \brief Returns the maestro state.
282  * \return the maestro Lua state
283  */
284 lua_State* sglua_get_maestro(void) {
285   return sglua_maestro_state;
286 }
287
288 /**
289  * \brief Makes the core functions available to the Lua world.
290  * \param L a Lua world
291  */
292 static void sglua_register_core_functions(lua_State *L)
293 {
294   /* register the core C functions to lua */
295   luaL_newlib(L, simgrid_functions); /* simgrid */
296   lua_pushvalue(L, -1);              /* simgrid simgrid */
297   lua_setglobal(L, "simgrid");       /* simgrid */
298
299   /* set a finalizer that cleans simgrid, by adding to the simgrid module a
300    * dummy userdata whose __gc metamethod calls MSG_clean() */
301   lua_newuserdata(L, sizeof(void*)); /* simgrid udata */
302   lua_newtable(L);                   /* simgrid udata mt */
303   lua_pushcfunction(L, simgrid_gc);  /* simgrid udata mt simgrid_gc */
304   lua_setfield(L, -2, "__gc");       /* simgrid udata mt */
305   lua_setmetatable(L, -2);           /* simgrid udata */
306   lua_setfield(L, -2, "__simgrid_loaded"); /* simgrid */
307   lua_pop(L, 1);                     /* -- */
308 }
309
310 /**
311  * \brief Creates the simgrid module and make it available to Lua.
312  * \param L a Lua world
313  */
314 static void sglua_register_c_functions(lua_State *L)
315 {
316   sglua_register_core_functions(L);
317   sglua_register_task_functions(L);
318   sglua_register_comm_functions(L);
319   sglua_register_host_functions(L);
320   sglua_register_process_functions(L);
321   sglua_register_platf_functions(L);
322 }
323
324 /**
325  * \brief Runs a Lua function as a new simulated process.
326  * \param argc number of arguments of the function
327  * \param argv name of the Lua function and array of its arguments
328  * \return result of the function
329  */
330 static int run_lua_code(int argc, char **argv)
331 {
332   XBT_DEBUG("Run lua code %s", argv[0]);
333
334   /* create a new state, getting globals from maestro */
335   lua_State *L = sglua_clone_maestro();
336   MSG_process_set_data(MSG_process_self(), L);
337
338   /* start the function */
339   lua_getglobal(L, argv[0]);
340   xbt_assert(lua_isfunction(L, -1),
341               "There is no Lua function with name `%s'", argv[0]);
342
343   /* push arguments onto the stack */
344   int i;
345   for (i = 1; i < argc; i++)
346     lua_pushstring(L, argv[i]);
347
348   /* call the function */
349   XBT_ATTRIB_UNUSED int err;
350   err = lua_pcall(L, argc - 1, 1, 0);
351   xbt_assert(err == 0, "Error running function `%s': %s", argv[0],
352               lua_tostring(L, -1));
353
354   /* retrieve result */
355   int res = 1;
356   if (lua_isnumber(L, -1)) {
357     res = lua_tointeger(L, -1);
358     lua_pop(L, 1);              /* pop returned value */
359   }
360
361   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
362
363   return res;
364 }
365
366 /**
367  * \brief Returns a string corresponding to an MSG error code.
368  * \param err an MSG error code
369  * \return a string describing this error
370  */
371 const char* sglua_get_msg_error(msg_error_t err) {
372
373   static const char* msg_errors[] = {
374       NULL,
375       "timeout",
376       "transfer failure",
377       "host failure",
378       "task canceled"
379   };
380
381   return msg_errors[err];
382 }