Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
f4eac311f01b5bcad4c237e3b44719d571d6901b
[simgrid.git] / src / surf / surf.c
1 /*      $Id$     */
2
3 /* Copyright (c) 2004 Arnaud Legrand. All rights reserved.                  */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "surf_private.h"
9 #include "xbt/module.h"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
12                                 "Logging specific to SURF (kernel)");
13
14 int use_sdp_solver=0;
15
16 /* Additional declarations for Windows potability. */
17
18 #ifndef MAX_DRIVE
19 #define MAX_DRIVE 26
20 #endif 
21
22 #ifdef _WIN32
23 #include <windows.h>
24 static const char* disk_drives_letter_table[MAX_DRIVE] =
25 {
26         "A:\\",
27         "B:\\",
28         "C:\\",
29         "D:\\",
30         "E:\\",
31         "F:\\",
32         "G:\\",
33         "H:\\",
34         "I:\\",
35         "J:\\",
36         "K:\\",
37         "L:\\",
38         "M:\\",
39         "N:\\",
40         "O:\\",
41         "P:\\",
42         "Q:\\",
43         "R:\\",
44         "S:\\",
45         "T:\\",
46         "U:\\",
47         "V:\\",
48         "W:\\",
49         "X:\\",
50         "Y:\\",
51         "Z:\\"
52 };
53 #endif /* #ifdef _WIN32 */
54
55 /*
56  * Returns the initial path. On Windows the initial path is
57  * the current directory for the current process in the other
58  * case the function returns "./" that represents the current
59  * directory on Unix/Linux platforms.
60  */
61                         
62 const char* __surf_get_initial_path(void)
63 {
64
65         #ifdef _WIN32
66         unsigned i;
67         char current_directory[MAX_PATH + 1] = {0};
68         unsigned int len = GetCurrentDirectory(MAX_PATH + 1,current_directory);
69         char root[4] = {0};
70
71         if(!len)
72                 return NULL;
73
74         strncpy(root,current_directory,3);
75
76         for(i = 0; i<MAX_DRIVE;i++)
77         {
78                 if(root[0] == disk_drives_letter_table[i][0])
79                         return disk_drives_letter_table[i];
80         }
81
82         return NULL;
83         #else
84         return "./";
85         #endif
86 }
87
88 /* The __surf_is_absolute_file_path() returns 1 if
89  * file_path is a absolute file path, in the other
90  * case the function returns 0.
91  */
92 int __surf_is_absolute_file_path(const char* file_path)
93 {
94         #ifdef _WIN32
95         WIN32_FIND_DATA wfd ={0};
96         HANDLE hFile = FindFirstFile(file_path,&wfd);
97
98         if(INVALID_HANDLE_VALUE == hFile)
99                 return 0;
100
101         FindClose(hFile);
102         return 1;
103         #else
104         return (file_path[0] == '/');
105         #endif
106 }
107
108 typedef struct surf_resource_object {
109   surf_resource_t resource;
110 } s_surf_resource_object_t, *surf_resource_object_t;
111
112 static double NOW = 0;
113
114 xbt_dynar_t resource_list = NULL;
115 tmgr_history_t history = NULL;
116 lmm_system_t maxmin_system = NULL;
117 xbt_dynar_t surf_path = NULL;
118 const char *surf_action_state_names[6] = {
119   "SURF_ACTION_READY", 
120   "SURF_ACTION_RUNNING", 
121   "SURF_ACTION_FAILED", 
122   "SURF_ACTION_DONE", 
123   "SURF_ACTION_TO_FREE", 
124   "SURF_ACTION_NOT_IN_THE_SYSTEM"
125 };
126
127 double generic_maxmin_share_resources(xbt_swag_t running_actions,
128                                        size_t offset)
129 {
130   return  generic_maxmin_share_resources2(running_actions, offset,
131                                           maxmin_system);
132 }
133
134 double generic_maxmin_share_resources2(xbt_swag_t running_actions,
135                                        size_t offset,
136                                        lmm_system_t sys)
137 {
138   surf_action_t action = NULL;
139   double min = -1;
140   double value = -1;
141 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
142
143   if(!use_sdp_solver)
144     lmm_solve(sys);
145   else {
146 #ifdef HAVE_SDP
147     sdp_solve(sys);
148 #else
149     xbt_assert0(0, "No CSDP found! You cannot use this model!");
150 #endif
151   }
152
153   xbt_swag_foreach(action, running_actions) {
154     value = lmm_variable_getvalue(VARIABLE(action));
155     if ((value > 0) || (action->max_duration >= 0))
156       break;
157   }
158
159   if (!action)
160     return -1.0;
161
162   if (value > 0) {
163     min = action->remains / value;
164     if ((action->max_duration >= 0) && (action->max_duration < min))
165       min = action->max_duration;
166   } else
167     min = action->max_duration;
168
169
170   for (action = xbt_swag_getNext(action, running_actions->offset);
171        action;
172        action = xbt_swag_getNext(action, running_actions->offset)) {
173     value = lmm_variable_getvalue(VARIABLE(action));
174     if (value > 0) {
175       value = action->remains / value;
176       if (value < min)
177         min = value;
178     }
179     if ((action->max_duration >= 0) && (action->max_duration < min))
180       min = action->max_duration;
181   }
182 #undef VARIABLE
183   return min;
184 }
185
186 e_surf_action_state_t surf_action_get_state(surf_action_t action)
187 {
188   surf_action_state_t action_state =
189       &(action->resource_type->common_public->states);
190
191   if (action->state_set == action_state->ready_action_set)
192     return SURF_ACTION_READY;
193   if (action->state_set == action_state->running_action_set)
194     return SURF_ACTION_RUNNING;
195   if (action->state_set == action_state->failed_action_set)
196     return SURF_ACTION_FAILED;
197   if (action->state_set == action_state->done_action_set)
198     return SURF_ACTION_DONE;
199   return SURF_ACTION_NOT_IN_THE_SYSTEM;
200 }
201
202 double surf_action_get_start_time(surf_action_t action) {
203   return action->start;
204 }
205
206 double surf_action_get_finish_time(surf_action_t action) {
207   return action->finish;
208 }
209
210 void surf_action_free(surf_action_t * action)
211 {
212   (*action)->resource_type->common_public->action_cancel(*action);
213   free(*action);
214   *action = NULL;
215 }
216
217 void surf_action_change_state(surf_action_t action,
218                               e_surf_action_state_t state)
219 {
220   surf_action_state_t action_state =
221       &(action->resource_type->common_public->states);
222   XBT_IN2("(%p,%s)", action, surf_action_state_names[state]);
223   xbt_swag_remove(action, action->state_set);
224
225   if (state == SURF_ACTION_READY)
226     action->state_set = action_state->ready_action_set;
227   else if (state == SURF_ACTION_RUNNING)
228     action->state_set = action_state->running_action_set;
229   else if (state == SURF_ACTION_FAILED)
230     action->state_set = action_state->failed_action_set;
231   else if (state == SURF_ACTION_DONE)
232     action->state_set = action_state->done_action_set;
233   else
234     action->state_set = NULL;
235
236   if (action->state_set)
237     xbt_swag_insert(action, action->state_set);
238   XBT_OUT;
239 }
240
241 void surf_action_set_data(surf_action_t action,
242                           void *data)
243 {
244   action->data=data;
245 }
246
247 void surf_init(int *argc, char **argv)
248 {
249   int i,j;
250   char *opt;
251   
252   const char* initial_path;
253
254   xbt_init(argc, argv);
255   if (!surf_path) {
256     
257     /* retrieves the current directory of the current process*/
258     initial_path = __surf_get_initial_path();
259                 
260         xbt_assert0((initial_path), "__surf_get_initial_path() failed! Can't resolves current Windows directory");
261     
262     surf_path = xbt_dynar_new(sizeof(char*), NULL);
263     xbt_dynar_push(surf_path,&initial_path);
264
265     for (i=1; i<*argc; i++) {
266       if (!strncmp(argv[i],"--surf-path=",strlen("--surf-path="))) {
267         opt=strchr(argv[i],'=');
268         opt++;
269         xbt_dynar_push(surf_path,&opt);
270         /*remove this from argv*/
271         for (j=i+1; j<*argc; j++) {
272           argv[j-1] = argv[j];
273         } 
274         argv[j-1] = NULL;
275         (*argc)--;
276         i--; /* compensate effect of next loop incrementation */
277       }
278     }
279   }
280   if (!resource_list)
281     resource_list = xbt_dynar_new(sizeof(surf_resource_private_t), NULL);
282   if (!history)
283     history = tmgr_history_new();
284   if (!maxmin_system)
285     maxmin_system = lmm_system_new();
286 }
287
288 static char* path_name = NULL;
289 FILE *surf_fopen(const char *name, const char *mode)
290 {
291   int i; 
292   char* path = NULL;
293   FILE *file = NULL;
294   int path_name_len = 0; /* don't count '\0' */
295
296   xbt_assert0(name, "Need a non-NULL file name");
297
298   xbt_assert0(surf_path,"surf_init has to be called before using surf_fopen");
299    
300   if (__surf_is_absolute_file_path(name)) { /* don't mess with absolute file names */
301     return fopen(name,mode);
302      
303   } else { /* search relative files in the path */
304    
305     if(!path_name) {
306        path_name_len = strlen(name);
307        path_name=xbt_new0(char,path_name_len+1);
308     }
309
310     xbt_dynar_foreach(surf_path,i,path) {
311       if(path_name_len < strlen(path)+strlen(name)+1) {
312          path_name_len = strlen(path)+strlen(name)+1; /* plus '/' */
313          path_name=xbt_realloc(path_name,path_name_len+1);
314       }
315       sprintf(path_name,"%s/%s",path, name);
316       file = fopen(path_name,mode);
317       if (file) return file;
318     }
319   }
320   return file;
321 }
322
323 void surf_exit(void)
324 {
325   int i;
326   surf_resource_t resource = NULL;
327
328   xbt_dynar_foreach(resource_list, i, resource) {
329     resource->common_private->finalize();
330   }
331
332   if (maxmin_system) {
333     lmm_system_free(maxmin_system);
334     maxmin_system = NULL;
335   }
336   if (history) {
337     tmgr_history_free(history);
338     history = NULL;
339   }
340   if (resource_list)
341     xbt_dynar_free(&resource_list);
342
343   if(surf_path) 
344     xbt_dynar_free(&surf_path);
345
346   tmgr_finalize();
347   surf_parse_lex_destroy();
348   if(path_name) {
349     free(path_name);
350     path_name = NULL;
351   }
352   xbt_exit();
353 }
354
355 double surf_solve(void)
356 {
357   static int first_run = 1;
358
359   double min = -1.0;
360   double next_event_date = -1.0;
361   double resource_next_action_end = -1.0;
362   double value = -1.0;
363   surf_resource_object_t resource_obj = NULL;
364   surf_resource_t resource = NULL;
365   tmgr_trace_event_t event = NULL;
366   int i;
367
368   if (first_run) {
369     DEBUG0("First Run! Let's \"purge\" events and put resources in the right state");
370     while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
371       if (next_event_date > NOW)
372         break;
373       while ((event =
374               tmgr_history_get_next_event_leq(history, next_event_date,
375                                               &value,
376                                               (void **) &resource_obj))) {
377         resource_obj->resource->common_private->
378             update_resource_state(resource_obj, event, value);
379       }
380     }
381     xbt_dynar_foreach(resource_list, i, resource) {
382       resource->common_private->update_actions_state(NOW, 0.0);
383     }
384     first_run = 0;
385     return 0.0;
386   }
387
388   min = -1.0;
389
390   DEBUG0("Looking for next action end");
391   xbt_dynar_foreach(resource_list, i, resource) {
392     resource_next_action_end =
393         resource->common_private->share_resources(NOW);
394     DEBUG2("Resource [%s] : next action end = %f",resource->common_public->name,
395            resource_next_action_end);
396     if (((min < 0.0) || (resource_next_action_end < min))
397         && (resource_next_action_end >= 0.0))
398       min = resource_next_action_end;
399   }
400   DEBUG1("Next action end : %f", min);
401
402   if (min < 0.0)
403     return -1.0;
404
405   DEBUG0("Looking for next event");
406   while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
407     DEBUG1("Next event : %f",next_event_date);
408     if (next_event_date > NOW + min)
409       break;
410     DEBUG0("Updating resources");
411     while ((event =
412             tmgr_history_get_next_event_leq(history, next_event_date,
413                                             &value,
414                                             (void **) &resource_obj))) {
415       if (resource_obj->resource->common_private->
416           resource_used(resource_obj)) {
417         min = next_event_date - NOW;
418         DEBUG1("This event will modify resource state. Next event set to %f", min);
419       }
420       /* update state of resource_obj according to new value. Does not touch lmm.
421          It will be modified if needed when updating actions */
422       resource_obj->resource->common_private->
423           update_resource_state(resource_obj, event, value);
424     }
425   }
426
427   DEBUG1("Duration set to %f", min);
428
429   NOW = NOW + min;
430
431   xbt_dynar_foreach(resource_list, i, resource) {
432     resource->common_private->update_actions_state(NOW, min);
433   }
434
435   return min;
436 }
437
438 double surf_get_clock(void)
439 {
440   return NOW;
441 }