Logo AND Algorithmique Numérique Distribuée

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