Logo AND Algorithmique Numérique Distribuée

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