Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
678842f1fe1dcf3fa2da6f83acede777bf76cbb6
[simgrid.git] / src / bindings / lua / simgrid_lua.c
1 /* SimGrid Lua bindings                                                     */
2
3 /* Copyright (c) 2010. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #include <stdio.h>
10 #include <lauxlib.h>
11 #include <lualib.h>
12 #include "msg/msg.h"
13 #include "simdag/simdag.h"
14 #include <gras.h>
15 #include "xbt.h"
16 #include "lua_stub_generator.h"
17
18 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua,bindings,"Lua Bindings");
19
20 #define TASK_MODULE_NAME "simgrid.Task"
21 #define HOST_MODULE_NAME "simgrid.Host"
22 // Surf ( bypass XML )
23 #define LINK_MODULE_NAME "simgrid.Link"
24 #define ROUTE_MODULE_NAME "simgrid.Route"
25
26 /* ********************************************************************************* */
27 /*                            helper functions                                       */
28 /* ********************************************************************************* */
29 static void stackDump (const char *msg, lua_State *L) {
30   char buff[2048];
31   char *p=buff;
32   int i;
33   int top = lua_gettop(L);
34
35   fflush(stdout);
36   p+=sprintf(p,"STACK(top=%d): ",top);
37
38   for (i = 1; i <= top; i++) {  /* repeat for each level */
39     int t = lua_type(L, i);
40     switch (t) {
41
42     case LUA_TSTRING:  /* strings */
43       p+=sprintf(p,"`%s'", lua_tostring(L, i));
44       break;
45
46     case LUA_TBOOLEAN:  /* booleans */
47       p+=sprintf(p,lua_toboolean(L, i) ? "true" : "false");
48       break;
49
50     case LUA_TNUMBER:  /* numbers */
51       p+=sprintf(p,"%g", lua_tonumber(L, i));
52       break;
53
54     case LUA_TTABLE:
55       p+=sprintf(p, "Table");
56       break;
57
58     default:  /* other values */
59       p+=sprintf(p, "???");
60 /*      if ((ptr = luaL_checkudata(L,i,TASK_MODULE_NAME))) {
61         p+=sprintf(p,"task");
62       } else {
63         p+=printf(p,"%s", lua_typename(L, t));
64       }*/
65       break;
66
67     }
68     p+=sprintf(p,"  ");  /* put a separator */
69   }
70   INFO2("%s%s",msg,buff);
71 }
72
73 /** @brief ensures that a userdata on the stack is a task and returns the pointer inside the userdata */
74 static m_task_t checkTask (lua_State *L,int index) {
75   m_task_t *pi,tk;
76   luaL_checktype(L,index,LUA_TTABLE);
77   lua_getfield(L,index,"__simgrid_task");
78   pi = (m_task_t*)luaL_checkudata(L,-1,TASK_MODULE_NAME);
79   if(pi == NULL)
80          luaL_typerror(L,index,TASK_MODULE_NAME);
81   tk = *pi;
82   if(!tk)
83          luaL_error(L,"null Task");
84   lua_pop(L,1);
85   return  tk;
86 }
87 /* ********************************************************************************* */
88 /*                           wrapper functions                                       */
89 /* ********************************************************************************* */
90
91 /**
92  * A task is either something to compute somewhere, or something to exchange between two hosts (or both).
93  * It is defined by a computing amount and a message size.
94  *
95  */
96
97 /* *              * *
98  * * Constructors * *
99  * *              * */
100 /**
101  * Construct an new task with the specified processing amount and amount
102  * of data needed.
103  *
104  * @param name  Task's name
105  *
106  * @param computeDuration       A value of the processing amount (in flop) needed to process the task.
107  *                              If 0, then it cannot be executed with the execute() method.
108  *                              This value has to be >= 0.
109  *
110  * @param messageSize           A value of amount of data (in bytes) needed to transfert this task.
111  *                              If 0, then it cannot be transfered with the get() and put() methods.
112  *                              This value has to be >= 0.
113  */
114 static int Task_new(lua_State* L) {
115           const char *name=luaL_checkstring(L,1);
116           int comp_size = luaL_checkint(L,2);
117           int msg_size = luaL_checkint(L,3);
118           m_task_t msg_task = MSG_task_create(name,comp_size,msg_size,NULL);
119           lua_newtable (L); /* create a table, put the userdata on top of it */
120           m_task_t *lua_task = (m_task_t*)lua_newuserdata(L,sizeof(m_task_t));
121           *lua_task = msg_task;
122           luaL_getmetatable(L,TASK_MODULE_NAME);
123           lua_setmetatable(L,-2);
124           lua_setfield (L, -2, "__simgrid_task"); /* put the userdata as field of the table */
125           /* remove the args from the stack */
126           lua_remove(L,1);
127           lua_remove(L,1);
128           lua_remove(L,1);
129           return 1;
130 }
131
132 static int Task_get_name(lua_State *L) {
133   m_task_t tk = checkTask(L,-1);
134   lua_pushstring(L,MSG_task_get_name(tk));
135   return 1;
136 }
137
138 static int Task_computation_duration(lua_State *L){
139   m_task_t tk = checkTask(L,-1);
140   lua_pushnumber(L,MSG_task_get_compute_duration (tk));
141   return 1;
142 }
143
144 static int Task_execute(lua_State *L){
145   m_task_t tk = checkTask(L,-1);
146   int res = MSG_task_execute(tk);
147   lua_pushnumber(L,res);
148   return 1;
149 }
150
151 static int Task_destroy(lua_State *L) {
152   m_task_t tk = checkTask(L,-1);
153   int res = MSG_task_destroy(tk);
154   lua_pushnumber(L,res);
155   return 1;
156 }
157
158 static int Task_send(lua_State *L)  {
159   //stackDump("send ",L);
160   m_task_t tk = checkTask(L,-2);
161   const char *mailbox = luaL_checkstring(L,-1);
162   lua_pop(L,1); // remove the string so that the task is on top of it
163   MSG_task_set_data(tk,L); // Copy my stack into the task, so that the receiver can copy the lua task directly
164   MSG_error_t res = MSG_task_send(tk,mailbox);
165   while (MSG_task_get_data(tk)!=NULL) // Don't mess up with my stack: the receiver didn't copy the data yet
166     MSG_process_sleep(0); // yield
167
168   if (res != MSG_OK) switch(res) {
169     case MSG_TIMEOUT :
170       ERROR0("MSG_task_send failed : Timeout");
171       break;
172     case MSG_TRANSFER_FAILURE :
173       ERROR0("MSG_task_send failed : Transfer Failure");
174       break;
175     case MSG_HOST_FAILURE :
176       ERROR0("MSG_task_send failed : Host Failure ");
177       break;
178     default :
179       ERROR0("MSG_task_send failed : Unexpected error , please report this bug");
180       break;
181     }
182   return 0;
183 }
184
185 static int Task_recv(lua_State *L)  {
186   m_task_t tk = NULL;
187   const char *mailbox = luaL_checkstring(L,-1);
188   MSG_error_t res = MSG_task_receive(&tk,mailbox);
189
190   lua_State *sender_stack = MSG_task_get_data(tk);
191   lua_xmove(sender_stack,L,1); // copy the data directly from sender's stack
192   MSG_task_set_data(tk,NULL);
193
194   if(res != MSG_OK) switch(res){
195           case MSG_TIMEOUT :
196                   ERROR0("MSG_task_receive failed : Timeout");
197                   break;
198           case MSG_TRANSFER_FAILURE :
199                   ERROR0("MSG_task_receive failed : Transfer Failure");
200                   break;
201           case MSG_HOST_FAILURE :
202                   ERROR0("MSG_task_receive failed : Host Failure ");
203                   break;
204           default :
205                   ERROR0("MSG_task_receive failed : Unexpected error , please report this bug");
206                   break;
207                   }
208
209   return 1;
210 }
211
212 static const luaL_reg Task_methods[] = {
213     {"new",   Task_new},
214     {"name",  Task_get_name},
215     {"computation_duration",  Task_computation_duration},
216     {"execute", Task_execute},
217     {"destroy", Task_destroy},
218     {"send",    Task_send},
219     {"recv",    Task_recv},
220     {0,0}
221 };
222 static int Task_gc(lua_State *L) {
223   m_task_t tk=checkTask(L,-1);
224   if (tk) MSG_task_destroy(tk);
225   return 0;
226 }
227
228 static int Task_tostring(lua_State *L) {
229   lua_pushfstring(L, "Task :%p",lua_touserdata(L,1));
230   return 1;
231 }
232
233 static const luaL_reg Task_meta[] = {
234     {"__gc",  Task_gc},
235     {"__tostring",  Task_tostring},
236     {0,0}
237 };
238
239 /**
240  * Host
241  */
242 static m_host_t checkHost (lua_State *L,int index) {
243   m_host_t *pi,ht;
244   luaL_checktype(L,index,LUA_TTABLE);
245   lua_getfield(L,index,"__simgrid_host");
246   pi = (m_host_t*)luaL_checkudata(L,-1,HOST_MODULE_NAME);
247   if(pi == NULL)
248          luaL_typerror(L,index,HOST_MODULE_NAME);
249   ht = *pi;
250   if(!ht)
251          luaL_error(L,"null Host");
252   lua_pop(L,1);
253   return  ht;
254 }
255
256 static int Host_get_by_name(lua_State *L)
257 {
258         const char *name=luaL_checkstring(L,1);
259         DEBUG0("Getting Host from name...");
260         m_host_t msg_host = MSG_get_host_by_name(name);
261         if (!msg_host)
262                 {
263                 luaL_error(L,"null Host : MSG_get_host_by_name failled");
264                 }
265     lua_newtable (L); /* create a table, put the userdata on top of it */
266         m_host_t *lua_host = (m_host_t*)lua_newuserdata(L,sizeof(m_host_t));
267         *lua_host = msg_host;
268         luaL_getmetatable(L,HOST_MODULE_NAME);
269         lua_setmetatable(L,-2);
270         lua_setfield (L, -2, "__simgrid_host"); /* put the userdata as field of the table */
271         /* remove the args from the stack */
272         lua_remove(L,1);
273         return 1;
274 }
275
276
277 static int Host_get_name(lua_State *L) {
278   m_host_t ht = checkHost(L,-1);
279   lua_pushstring(L,MSG_host_get_name(ht));
280   return 1;
281 }
282
283 static int Host_number(lua_State *L) {
284   lua_pushnumber(L,MSG_get_host_number());
285   return 1;
286 }
287
288 static int Host_at(lua_State *L)
289 {
290         int index = luaL_checkinteger(L,1);
291         m_host_t host = MSG_get_host_table()[index-1]; // lua indexing start by 1 (lua[1] <=> C[0])
292         lua_newtable (L); /* create a table, put the userdata on top of it */
293         m_host_t *lua_host = (m_host_t*)lua_newuserdata(L,sizeof(m_host_t));
294         *lua_host = host;
295         luaL_getmetatable(L,HOST_MODULE_NAME);
296         lua_setmetatable(L,-2);
297         lua_setfield (L, -2, "__simgrid_host"); /* put the userdata as field of the table */
298         return 1;
299
300 }
301
302 /*****************************************************************************************
303                                                              * BYPASS XML SURF Methods *
304                                                                  ***************************
305                                                                  ***************************
306 ******************************************************************************************/
307 #include "surf/surfxml_parse.h" /* to override surf_parse and bypass the parser */
308 #include "surf/surf_private.h"
309 typedef struct t_host_attr
310 {
311         //platform attribute
312         // Mandatory attributes
313         const char* id;
314         double power_peak;
315         // Optional attributes
316         double power_scale;
317         const char *power_trace;
318         int state_initial;
319         const char *state_trace;
320         //deployment attribute
321         const char* function;
322         xbt_dynar_t args_list;
323 }host_attr,*p_host_attr;
324
325 typedef struct t_link_attr
326 {
327         //mandatory attributes
328         const char* id;
329         double bandwidth;
330         double latency;
331         // Optional attributes
332         const char* bandwidth_trace;
333         const char* latency_trace;
334         const char*     state_trace;
335         int state_initial;
336         int policy;
337 }link_attr,*p_link_attr;
338
339 typedef struct t_route_attr
340 {
341         const char *src_id;
342         const char *dest_id;
343         xbt_dynar_t links_id;
344
345 }route_attr,*p_route_attr;
346
347 //using xbt_dynar_t :
348 static xbt_dynar_t host_list_d ;
349 static xbt_dynar_t link_list_d ;
350 static xbt_dynar_t route_list_d ;
351
352
353 /**
354  * create host resource via CPU model [for MSG]
355  */
356
357 static void create_host(const char* id,double power_peak,double power_sc,
358                                                 const char* power_tr,int state_init,
359                                                 const char* state_tr)
360 {
361
362         double power_scale = 1.0;
363         tmgr_trace_t power_trace = NULL;
364         e_surf_resource_state_t state_initial;
365         tmgr_trace_t state_trace;
366         if(power_sc) // !=0
367                 power_scale = power_sc;
368         if (state_init == -1)
369                 state_initial = SURF_RESOURCE_OFF;
370         else
371                 state_initial = SURF_RESOURCE_ON;
372         if(power_tr)
373                 power_trace = tmgr_trace_new(power_tr);
374         else
375                 power_trace = tmgr_trace_new("");
376         if(state_tr)
377                 state_trace = tmgr_trace_new(state_tr);
378         else
379                 state_trace = tmgr_trace_new("");
380         current_property_set = xbt_dict_new();
381         surf_host_create_resource(xbt_strdup(id), power_peak, power_scale,
382                                                power_trace, state_initial, state_trace, current_property_set);
383
384 }
385
386 /**
387  * create link resource via network model
388  */
389 static void create_link(const char *name,
390         double bw_initial,const char *trace,double lat_initial,
391         const char* latency_trace,int state_init, const char* state_trace,int policy)
392 {
393         tmgr_trace_t bw_trace;
394         tmgr_trace_t lat_trace;
395         e_surf_resource_state_t state_initial_link = SURF_RESOURCE_ON;
396         e_surf_link_sharing_policy_t policy_initial_link = SURF_LINK_SHARED;
397         tmgr_trace_t st_trace;
398         if(trace)
399                 bw_trace = tmgr_trace_new(trace);
400         else
401                 bw_trace = tmgr_trace_new("");
402
403         if(latency_trace)
404                 lat_trace = tmgr_trace_new(latency_trace);
405         else
406                 lat_trace = tmgr_trace_new("");
407
408         if(state_trace)
409                 st_trace = tmgr_trace_new(state_trace);
410         else
411                 st_trace = tmgr_trace_new("");
412
413         if(state_init == -1)
414                 state_initial_link = SURF_RESOURCE_OFF;
415         if(policy == -1)
416                 policy_initial_link = SURF_LINK_FATPIPE;
417
418         surf_link_create_resource(xbt_strdup(name), bw_initial, bw_trace,
419                    lat_initial, lat_trace, state_initial_link, st_trace,
420                    policy_initial_link, xbt_dict_new());
421 }
422
423
424 /*
425  *create host resource via workstation_ptask_L07 model [for SimDag]
426  */
427 static void create_host_wsL07(const char* id,double power_peak,double power_sc,
428                                                 const char* power_tr,int state_init,
429                                                 const char* state_tr)
430 {
431         double power_scale = 1.0;
432         tmgr_trace_t power_trace = NULL;
433         e_surf_resource_state_t state_initial;
434         tmgr_trace_t state_trace;
435         if(power_sc) // !=0
436                 power_scale = power_sc;
437         if (state_init == -1)
438                 state_initial = SURF_RESOURCE_OFF;
439         else
440                 state_initial = SURF_RESOURCE_ON;
441         if(power_tr)
442                 power_trace = tmgr_trace_new(power_tr);
443         else
444                 power_trace = tmgr_trace_new("");
445         if(state_tr)
446                 state_trace = tmgr_trace_new(state_tr);
447         else
448                 state_trace = tmgr_trace_new("");
449         current_property_set = xbt_dict_new();
450         surf_wsL07_host_create_resource(xbt_strdup(id), power_peak, power_scale,
451                                                power_trace, state_initial, state_trace, current_property_set);
452
453 }
454
455 /**
456  * create link resource via workstation_ptask_L07 model [for SimDag]
457  */
458
459 static void create_link_wsL07(const char *name,
460         double bw_initial,const char *trace,double lat_initial,
461         const char* latency_trace,int state_init, const char* state_trace,int policy)
462 {
463         tmgr_trace_t bw_trace;
464         tmgr_trace_t lat_trace;
465         e_surf_resource_state_t state_initial_link = SURF_RESOURCE_ON;
466         e_surf_link_sharing_policy_t policy_initial_link = SURF_LINK_SHARED;
467         tmgr_trace_t st_trace;
468         if(trace)
469                 bw_trace = tmgr_trace_new(trace);
470         else
471                 bw_trace = tmgr_trace_new("");
472
473         if(latency_trace)
474                 lat_trace = tmgr_trace_new(latency_trace);
475         else
476                 lat_trace = tmgr_trace_new("");
477
478         if(state_trace)
479                 st_trace = tmgr_trace_new(state_trace);
480         else
481                 st_trace = tmgr_trace_new("");
482
483         if(state_init == -1)
484                 state_initial_link = SURF_RESOURCE_OFF;
485         if(policy == -1)
486                 policy_initial_link = SURF_LINK_FATPIPE;
487
488         surf_wsL07_link_create_resource(xbt_strdup(name), bw_initial, bw_trace,
489                    lat_initial, lat_trace, state_initial_link, st_trace,
490                    policy_initial_link, xbt_dict_new());
491 }
492
493 /*
494  * add new host to platform hosts list
495  */
496 static int Host_new(lua_State *L)
497 {
498
499         if(xbt_dynar_is_empty(host_list_d))
500                 host_list_d = xbt_dynar_new(sizeof(p_host_attr), &xbt_free_ref);
501
502         p_host_attr host;
503         const char * id;
504         const char *power_trace;
505         const char *state_trace;
506         double power,power_scale;
507         int state_initial;
508         //get values from the table passed as argument
509     if (lua_istable(L,-1)) {
510
511             // get Id Value
512             lua_pushstring(L,"id");
513             lua_gettable(L, -2 );
514             id = lua_tostring(L,-1);
515             lua_pop(L,1);
516
517             // get power value
518             lua_pushstring(L,"power");
519             lua_gettable(L, -2 );
520             power = lua_tonumber(L,-1);
521             lua_pop(L,1);
522
523             //get power_scale
524             lua_pushstring(L,"power_scale");
525             lua_gettable(L, -2 );
526             power_scale = lua_tonumber(L,-1);
527             lua_pop(L,1);
528
529             //get power_trace
530             lua_pushstring(L,"power_trace");
531             lua_gettable(L, -2 );
532             power_trace = lua_tostring(L,-1);
533             lua_pop(L,1);
534
535             //get state initial
536             lua_pushstring(L,"state_initial");
537             lua_gettable(L, -2 );
538             state_initial = lua_tonumber(L,-1);
539             lua_pop(L,1);
540
541             //get trace state
542             lua_pushstring(L,"state_trace");
543             lua_gettable(L, -2 );
544             state_trace = lua_tostring(L,-1);
545             lua_pop(L,1);
546
547     } else {
548             ERROR0("Bad Arguments to create host, Should be a table with named arguments");
549             return -1;
550     }
551
552             host = malloc(sizeof(host_attr));
553                 host->id = id;
554                 host->power_peak = power;
555                 host->power_scale = power_scale;
556                 host->power_trace = power_trace;
557                 host->state_initial = state_initial;
558                 host->state_trace = state_trace;
559                 host->function = NULL;
560                 xbt_dynar_push(host_list_d, &host);
561
562     return 0;
563 }
564
565 /**
566  * add link to platform links list
567  */
568 static int Link_new(lua_State *L) // (id,bandwidth,latency)
569 {
570         if(xbt_dynar_is_empty(link_list_d))
571                 link_list_d = xbt_dynar_new(sizeof(p_link_attr), &xbt_free_ref);
572
573         const char* id;
574         double bandwidth,latency;
575         const char* bandwidth_trace;
576         const char* latency_trace;
577         const char* state_trace;
578         int state_initial,policy;
579
580         //get values from the table passed as argument
581         if (lua_istable(L,-1)) {
582                     // get Id Value
583                     lua_pushstring(L,"id");
584                     lua_gettable(L, -2 );
585                     id = lua_tostring(L,-1);
586                     lua_pop(L,1);
587
588                     // get bandwidth value
589                     lua_pushstring(L,"bandwidth");
590                     lua_gettable(L, -2 );
591                     bandwidth = lua_tonumber(L,-1);
592                     lua_pop(L,1);
593
594                     //get latency value
595                     lua_pushstring(L,"latency");
596                     lua_gettable(L, -2 );
597                     latency = lua_tonumber(L,-1);
598                     lua_pop(L,1);
599
600                     /*Optional Arguments  */
601
602                     //get bandwidth_trace value
603                     lua_pushstring(L,"bandwidth_trace");
604                     lua_gettable(L, -2 );
605                     bandwidth_trace = lua_tostring(L,-1);
606                     lua_pop(L,1);
607
608                     //get latency_trace value
609                     lua_pushstring(L,"latency_trace");
610                     lua_gettable(L, -2 );
611                     latency_trace = lua_tostring(L,-1);
612                     lua_pop(L,1);
613
614                     //get state_trace value
615                     lua_pushstring(L,"state_trace");
616                     lua_gettable(L, -2 );
617                     state_trace = lua_tostring(L,-1);
618                     lua_pop(L,1);
619
620                                 //get state_initial value
621                     lua_pushstring(L,"state_initial");
622                     lua_gettable(L, -2 );
623                     state_initial = lua_tonumber(L,-1);
624                     lua_pop(L,1);
625
626
627                                 //get policy value
628                     lua_pushstring(L,"policy");
629                     lua_gettable(L, -2 );
630                     policy = lua_tonumber(L,-1);
631                     lua_pop(L,1);
632
633             } else {
634                     ERROR0("Bad Arguments to create link, Should be a table with named arguments");
635                     return -1;
636             }
637
638         p_link_attr link = malloc(sizeof(link_attr));
639         link->id = id;
640         link->bandwidth = bandwidth;
641         link->latency = latency;
642         link->bandwidth_trace = bandwidth_trace;
643         link->latency_trace = latency_trace;
644         link->state_trace = state_trace;
645         link->state_initial= state_initial;
646         link->policy = policy;
647         xbt_dynar_push(link_list_d,&link);
648         return 0;
649 }
650
651 /**
652  * add route to platform routes list
653  */
654 static int Route_new(lua_State *L) // (src_id,dest_id,links_number,link_table)
655 {
656         if(xbt_dynar_is_empty(route_list_d))
657                 route_list_d = xbt_dynar_new(sizeof(p_route_attr), &xbt_free_ref);
658         const char * link_id;
659         p_route_attr route = malloc(sizeof(route_attr));
660         route->src_id = luaL_checkstring(L,1);
661         route->dest_id = luaL_checkstring(L,2);
662         route->links_id = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
663         lua_pushnil(L);
664         while (lua_next(L,3) != 0) {
665                 link_id = lua_tostring(L, -1);
666                 xbt_dynar_push(route->links_id, &link_id);
667             DEBUG2("index = %f , Link_id = %s \n",lua_tonumber(L, -2),lua_tostring(L, -1));
668             lua_pop(L, 1);
669         }
670         lua_pop(L, 1);
671
672         //add route to platform's route list
673         xbt_dynar_push(route_list_d,&route);
674         return 0;
675 }
676
677 /**
678  * set function to process
679  */
680 static int Host_set_function(lua_State *L) //(host,function,nb_args,list_args)
681 {
682         // look for the index of host in host_list
683         const char *host_id = luaL_checkstring(L,1);
684         const char* argument;
685         unsigned int i;
686         p_host_attr p_host;
687
688         xbt_dynar_foreach(host_list_d,i,p_host)
689         {
690                 if(p_host->id == host_id)
691                 {
692                         p_host->function = luaL_checkstring(L,2);
693                         if(lua_istable(L,3))
694                         {
695                                 p_host->args_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
696                                 // fill the args list
697                                 lua_pushnil(L);
698                                 int j = 0;
699                                 while (lua_next(L,3) != 0) {
700                                                 argument = lua_tostring(L, -1);
701                                                 xbt_dynar_push(p_host->args_list, &argument);
702                                                 DEBUG2("index = %f , Arg_id = %s \n",lua_tonumber(L, -2),lua_tostring(L, -1));
703                                                 j++;
704                                                 lua_pop(L, 1);
705                                         }
706                         }
707                         lua_pop(L, 1);
708                         return 0;
709                 }
710         }
711         ERROR1("Host : %s Not Fount !!",host_id);
712         return 1;
713 }
714
715 /*
716  * surf parse bypass platform
717  * through CPU/network Models
718  */
719
720 static int surf_parse_bypass_platform()
721 {
722         unsigned int i;
723         p_host_attr p_host;
724         p_link_attr p_link;
725         p_route_attr p_route;
726
727         // Add Hosts
728         xbt_dynar_foreach(host_list_d,i,p_host)
729         {
730                 create_host(p_host->id,p_host->power_peak,p_host->power_scale,p_host->power_trace,
731                                         p_host->state_initial,p_host->state_trace);
732                 //add to routing model host list
733                 surf_route_add_host((char*)p_host->id);
734         }
735
736         //add Links
737         xbt_dynar_foreach(link_list_d,i,p_link)
738         {
739                 create_link(p_link->id,p_link->bandwidth,p_link->bandwidth_trace,p_link->latency,
740                                 p_link->latency_trace,p_link->state_initial,p_link->state_trace,p_link->policy);
741         }
742         // add route
743         xbt_dynar_foreach(route_list_d,i,p_route)
744         {
745                 surf_route_set_resource((char*)p_route->src_id,(char*)p_route->dest_id,p_route->links_id,0);
746         }
747         /* </platform> */
748
749         surf_add_host_traces();
750         surf_set_routes();
751         surf_add_link_traces();
752
753         return 0; // must return 0 ?!!
754
755 }
756
757 /**
758  *
759  * surf parse bypass platform
760  * through workstation_ptask_L07 Model
761  */
762
763
764 static int surf_wsL07_parse_bypass_platform()
765 {
766         unsigned int i;
767         p_host_attr p_host;
768         p_link_attr p_link;
769         p_route_attr p_route;
770
771         // Add Hosts
772         xbt_dynar_foreach(host_list_d,i,p_host)
773         {
774                 create_host_wsL07(p_host->id,p_host->power_peak,p_host->power_scale,p_host->power_trace,
775                                         p_host->state_initial,p_host->state_trace);
776                 //add to routing model host list
777                 surf_route_add_host((char*)p_host->id);
778         }
779
780         //add Links
781         xbt_dynar_foreach(link_list_d,i,p_link)
782         {
783                 create_link_wsL07(p_link->id,p_link->bandwidth,p_link->bandwidth_trace,p_link->latency,
784                                                 p_link->latency_trace,p_link->state_initial,p_link->state_trace,p_link->policy);
785         }
786         // add route
787         xbt_dynar_foreach(route_list_d,i,p_route)
788         {
789                 surf_route_set_resource((char*)p_route->src_id,(char*)p_route->dest_id,p_route->links_id,0);
790         }
791         /* </platform> */
792
793         surf_wsL07_add_traces();
794         surf_set_routes();
795
796         return 0;
797
798 }
799 /*
800  * surf parse bypass application for MSG Module
801  */
802 static int surf_parse_bypass_application()
803 {
804           unsigned int i;
805           p_host_attr p_host;
806           xbt_dynar_foreach(host_list_d,i,p_host)
807                   {
808                   if(p_host->function)
809                           MSG_set_function(p_host->id,p_host->function,p_host->args_list);
810                   }
811           return 0;
812 }
813
814
815 /**
816  *  Generate Gras Templates File from lua
817  */
818
819 xbt_dict_t process_function_set;
820 xbt_dynar_t process_list;
821 xbt_dict_t machine_set;
822 static s_process_t process;
823
824 void s_process_free(void *process)
825 {
826   s_process_t *p = (s_process_t *) process;
827   int i;
828   for (i = 0; i < p->argc; i++)
829     free(p->argv[i]);
830   free(p->argv);
831   free(p->host);
832 }
833
834 static int gras_add_process_function(lua_State *L)
835 {
836         const char * arg;
837         const char* process_host = luaL_checkstring(L,1);
838         const char *process_function = luaL_checkstring(L,2);
839
840         if(xbt_dict_is_empty(machine_set) || xbt_dict_is_empty(process_function_set)
841                         || xbt_dynar_is_empty(process_list))
842                 {
843                   process_function_set = xbt_dict_new();
844                   process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
845                   machine_set = xbt_dict_new();
846                 }
847
848         xbt_dict_set(machine_set,process_host, NULL, NULL);
849         xbt_dict_set(process_function_set,process_function, NULL, NULL);
850
851         process.argc = 1;
852         process.argv = xbt_new(char *, 1);
853         process.argv[0] = xbt_strdup(process_function);
854         process.host = strdup(process_host);
855
856         lua_pushnil(L);
857         while (lua_next(L,3) != 0) {
858                 arg = lua_tostring(L, -1);
859                 process.argc++;
860                 process.argv = xbt_realloc(process.argv, (process.argc) * sizeof(char *));
861                 process.argv[(process.argc) - 1] = xbt_strdup(arg);
862
863                 DEBUG2("index = %f , arg = %s \n",lua_tonumber(L, -2),lua_tostring(L, -1));
864                 lua_pop(L, 1);
865                 }
866         lua_pop(L, 1);
867         //add to the process list
868         xbt_dynar_push(process_list, &process);
869
870         return 0;
871
872 }
873
874
875 static int gras_generate(lua_State *L)
876 {
877   const char *project_name = luaL_checkstring(L,1);
878   generate_sim(project_name);
879   generate_rl(project_name);
880   generate_makefile_local(project_name);
881
882   return 0;
883 }
884
885 //***********Register Methods *******************************************//
886 /*
887  * Host Methods
888  */
889 static const luaL_reg Host_methods[] = {
890     {"getByName",   Host_get_by_name},
891     {"name",            Host_get_name},
892     {"number",          Host_number},
893     {"at",                      Host_at},
894     // Bypass XML Methods
895     {"new",                     Host_new},
896     {"setFunction",     Host_set_function},
897     {0,0}
898 };
899
900 static int Host_gc(lua_State *L)
901 {
902   m_host_t ht = checkHost(L,-1);
903   if (ht) ht = NULL;
904   return 0;
905 }
906
907 static int Host_tostring(lua_State *L)
908 {
909   lua_pushfstring(L,"Host :%p",lua_touserdata(L,1));
910   return 1;
911 }
912
913 static const luaL_reg Host_meta[] = {
914     {"__gc",  Host_gc},
915     {"__tostring",  Host_tostring},
916     {0,0}
917 };
918
919 /*
920  * Link Methods
921  */
922 static const luaL_reg Link_methods[] = {
923     {"new",Link_new},
924     {0,0}
925 };
926 /*
927  * Route Methods
928  */
929 static const luaL_reg Route_methods[] ={
930    {"new",Route_new},
931    {0,0}
932 };
933
934 /*
935  * Environment related
936  */
937
938 extern lua_State *simgrid_lua_state;
939
940 static int run_lua_code(int argc,char **argv) {
941   DEBUG1("Run lua code %s",argv[0]);
942   lua_State *L = lua_newthread(simgrid_lua_state);
943   int ref = luaL_ref(simgrid_lua_state, LUA_REGISTRYINDEX); // protect the thread from being garbage collected
944   int res = 1;
945
946   /* Start the co-routine */
947   lua_getglobal(L,argv[0]);
948   xbt_assert1(lua_isfunction(L,-1),
949       "The lua function %s does not seem to exist",argv[0]);
950
951   // push arguments onto the stack
952   int i;
953   for(i=1;i<argc;i++)
954     lua_pushstring(L,argv[i]);
955
956   // Call the function (in resume)
957   xbt_assert2(lua_pcall(L, argc-1, 1, 0) == 0,
958     "error running function `%s': %s",argv[0], lua_tostring(L, -1));
959
960   /* retrieve result */
961   if (lua_isnumber(L, -1)) {
962     res = lua_tonumber(L, -1);
963     lua_pop(L, 1);  /* pop returned value */
964   }
965   // cleanups
966   luaL_unref(simgrid_lua_state,LUA_REGISTRYINDEX,ref );
967   DEBUG1("Execution of lua code %s is over", (argv ? argv[0] : "(null)"));
968   return res;
969 }
970 static int launch_application(lua_State *L) {
971   const char * file = luaL_checkstring(L,1);
972   MSG_function_register_default(run_lua_code);
973   MSG_launch_application(file);
974   return 0;
975 }
976 #include "simix/simix.h" //FIXME: KILLME when debugging on simix internals become useless
977 static int create_environment(lua_State *L) {
978   const char *file = luaL_checkstring(L,1);
979   DEBUG1("Loading environment file %s",file);
980   MSG_create_environment(file);
981   smx_host_t *hosts = SIMIX_host_get_table();
982   int i;
983   for (i=0;i<SIMIX_host_get_number();i++) {
984     DEBUG1("We have an host %s", SIMIX_host_get_name(hosts[i]));
985   }
986
987   return 0;
988 }
989
990 static int debug(lua_State *L) {
991   const char *str = luaL_checkstring(L,1);
992   DEBUG1("%s",str);
993   return 0;
994 }
995 static int info(lua_State *L) {
996   const char *str = luaL_checkstring(L,1);
997   INFO1("%s",str);
998   return 0;
999 }
1000 static int run(lua_State *L) {
1001   MSG_main();
1002   return 0;
1003 }
1004 static int clean(lua_State *L) {
1005   MSG_clean();
1006   return 0;
1007 }
1008
1009 /*
1010  * Bypass XML Parser
1011  */
1012
1013 /*
1014  * Register platform for MSG
1015  */
1016 static int msg_register_platform(lua_State *L)
1017 {
1018         /* Tell Simgrid we dont wanna use its parser*/
1019         surf_parse = surf_parse_bypass_platform;
1020         MSG_create_environment(NULL);
1021         return 0;
1022 }
1023
1024 /*
1025  * Register platform for Simdag
1026  */
1027
1028 static int sd_register_platform(lua_State *L)
1029 {
1030         surf_parse = surf_wsL07_parse_bypass_platform;
1031         SD_create_environment(NULL);
1032         return 0;
1033 }
1034 /*
1035  * Register platform for gras
1036  */
1037 static int gras_register_platform(lua_State *L)
1038 {
1039         /* Tell Simgrid we dont wanna use surf parser*/
1040         surf_parse = surf_parse_bypass_platform;
1041         gras_create_environment(NULL);
1042         return 0;
1043 }
1044
1045 /**
1046  * Register applicaiton for MSG
1047  */
1048 static int msg_register_application(lua_State *L)
1049 {
1050          MSG_function_register_default(run_lua_code);
1051          surf_parse = surf_parse_bypass_application;
1052          MSG_launch_application(NULL);
1053          return 0;
1054 }
1055
1056 /*
1057  * Register application for gras
1058  */
1059 static int gras_register_application(lua_State *L)
1060 {
1061         gras_function_register_default(run_lua_code);
1062         surf_parse = surf_parse_bypass_application;
1063         gras_launch_application(NULL);
1064         return 0;
1065 }
1066 static const luaL_Reg simgrid_funcs[] = {
1067     { "create_environment", create_environment},
1068     { "launch_application", launch_application},
1069     { "debug", debug},
1070     { "info", info},
1071     { "run", run},
1072     { "clean", clean},
1073     /* short names */
1074     { "platform", create_environment},
1075     { "application", launch_application},
1076     /* methods to bypass XML parser*/
1077     { "msg_register_platform",msg_register_platform},
1078     { "sd_register_platform",sd_register_platform},
1079     { "msg_register_application",msg_register_application},
1080     { "gras_register_platform",gras_register_platform},
1081     { "gras_register_application",gras_register_application},
1082     /* gras sub generator method*/
1083     {"gras_set_process_function",gras_add_process_function},
1084     {"gras_generate",gras_generate},
1085     { NULL, NULL }
1086 };
1087
1088 /* ********************************************************************************* */
1089 /*                       module management functions                                 */
1090 /* ********************************************************************************* */
1091
1092 extern const char*xbt_ctx_factory_to_use; /*Hack: let msg load directly the right factory */
1093
1094 #define LUA_MAX_ARGS_COUNT 10 /* maximum amount of arguments we can get from lua on command line */
1095 #define TEST
1096 int luaopen_simgrid(lua_State* L); // Fuck gcc: we don't need that prototype
1097 int luaopen_simgrid(lua_State* L) {
1098
1099   //xbt_ctx_factory_to_use = "lua";
1100   char **argv=malloc(sizeof(char*)*LUA_MAX_ARGS_COUNT);
1101   int argc=1;
1102   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? */
1103   /* Get the command line arguments from the lua interpreter */
1104   lua_getglobal(L,"arg");
1105   /* if arg is a null value, it means we use lua only as a script to init platform
1106    * else it should be a table and then take arg in consideration
1107    */
1108   if(lua_istable(L,-1))
1109   {
1110           int done=0;
1111           while (!done) {
1112                 argc++;
1113                 lua_pushinteger(L,argc-2);
1114                 lua_gettable(L,-2);
1115                 if (lua_isnil(L,-1)) {
1116                   done = 1;
1117                 } else {
1118                   xbt_assert1(lua_isstring(L,-1),"argv[%d] got from lua is no string",argc-1);
1119                   xbt_assert2(argc<LUA_MAX_ARGS_COUNT,
1120                            "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",
1121                            __FILE__,LUA_MAX_ARGS_COUNT-1);
1122                   argv[argc-1] = (char*)luaL_checkstring(L,-1);
1123                   lua_pop(L,1);
1124                   DEBUG1("Got command line argument %s from lua",argv[argc-1]);
1125                 }
1126           }
1127           argv[argc--]=NULL;
1128
1129           /* Initialize the MSG core */
1130           MSG_global_init(&argc,argv);
1131           DEBUG1("Still %d arguments on command line",argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
1132  }
1133   /* register the core C functions to lua */
1134   luaL_register(L, "simgrid", simgrid_funcs);
1135   /* register the task methods to lua */
1136   luaL_openlib(L,TASK_MODULE_NAME,Task_methods,0); //create methods table,add it to the globals
1137   luaL_newmetatable(L,TASK_MODULE_NAME); //create metatable for Task,add it to the Lua registry
1138   luaL_openlib(L,0,Task_meta,0);// fill metatable
1139   lua_pushliteral(L,"__index");
1140   lua_pushvalue(L,-3);  //dup methods table
1141   lua_rawset(L,-3); //matatable.__index = methods
1142   lua_pushliteral(L,"__metatable");
1143   lua_pushvalue(L,-3);  //dup methods table
1144   lua_rawset(L,-3); //hide metatable:metatable.__metatable = methods
1145   lua_pop(L,1);   //drop metatable
1146
1147   /* register the hosts methods to lua*/
1148   luaL_openlib(L,HOST_MODULE_NAME,Host_methods,0);
1149   luaL_newmetatable(L,HOST_MODULE_NAME);
1150   luaL_openlib(L,0,Host_meta,0);
1151   lua_pushliteral(L,"__index");
1152   lua_pushvalue(L,-3);
1153   lua_rawset(L,-3);
1154   lua_pushliteral(L,"__metatable");
1155   lua_pushvalue(L,-3);
1156   lua_rawset(L,-3);
1157   lua_pop(L,1);
1158
1159   /* register the links methods to lua*/
1160   luaL_openlib(L,LINK_MODULE_NAME,Link_methods,0);
1161   luaL_newmetatable(L,LINK_MODULE_NAME);
1162   lua_pop(L,1);
1163
1164   /*register the routes methods to lua*/
1165   luaL_openlib(L,ROUTE_MODULE_NAME,Route_methods,0);
1166   luaL_newmetatable(L,LINK_MODULE_NAME);
1167   lua_pop(L,1);
1168
1169   /* Keep the context mechanism informed of our lua world today */
1170   simgrid_lua_state = L;
1171   return 1;
1172 }