Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Added function prototypes in maxmin_private, minor bug corrections in
[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);
135 }
136
137 double generic_maxmin_share_resources2(xbt_swag_t running_actions,
138                                        size_t offset,
139                                        lmm_system_t sys)
140 {
141   surf_action_t action = NULL;
142   double min = -1;
143   double value = -1;
144 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
145
146   if(!use_sdp_solver)
147     lmm_solve(sys);
148   else if(!use_lagrange_solver){
149 #ifdef HAVE_SDP
150     sdp_solve(sys);
151 #else
152     xbt_assert0(0, "No CSDP found! You cannot use this model!");
153 #endif
154   }else{
155     lagrange_solve(sys);
156   }
157
158   xbt_swag_foreach(action, running_actions) {
159     value = lmm_variable_getvalue(VARIABLE(action));
160     if ((value > 0) || (action->max_duration >= 0))
161       break;
162   }
163
164   if (!action)
165     return -1.0;
166
167   if (value > 0) {
168     min = action->remains / value;
169     if ((action->max_duration >= 0) && (action->max_duration < min))
170       min = action->max_duration;
171   } else
172     min = action->max_duration;
173
174   DEBUG5("Found an action (%p: duration = %f, remains = %f, value = %f) ! %f",action, action->max_duration, action->remains, value, min); 
175
176   for (action = xbt_swag_getNext(action, running_actions->offset);
177        action;
178        action = xbt_swag_getNext(action, running_actions->offset)) {
179     value = lmm_variable_getvalue(VARIABLE(action));
180     if (value > 0) {
181       value = action->remains / value;
182       if (value < min) {
183         min = value;
184         DEBUG2("Updating min (value) with %p: %f",action, min);
185       }
186     }
187     if ((action->max_duration >= 0) && (action->max_duration < min)) {
188       min = action->max_duration;
189       DEBUG2("Updating min (duration) with %p: %f",action, min);
190     }
191   }
192   DEBUG1("min value : %f",min);
193
194 #undef VARIABLE
195   return min;
196 }
197
198 e_surf_action_state_t surf_action_get_state(surf_action_t action)
199 {
200   surf_action_state_t action_state =
201       &(action->resource_type->common_public->states);
202
203   if (action->state_set == action_state->ready_action_set)
204     return SURF_ACTION_READY;
205   if (action->state_set == action_state->running_action_set)
206     return SURF_ACTION_RUNNING;
207   if (action->state_set == action_state->failed_action_set)
208     return SURF_ACTION_FAILED;
209   if (action->state_set == action_state->done_action_set)
210     return SURF_ACTION_DONE;
211   return SURF_ACTION_NOT_IN_THE_SYSTEM;
212 }
213
214 double surf_action_get_start_time(surf_action_t action) {
215   return action->start;
216 }
217
218 double surf_action_get_finish_time(surf_action_t action) {
219   return action->finish;
220 }
221
222 void surf_action_free(surf_action_t * action)
223 {
224   (*action)->resource_type->common_public->action_cancel(*action);
225   free(*action);
226   *action = NULL;
227 }
228
229 void surf_action_change_state(surf_action_t action,
230                               e_surf_action_state_t state)
231 {
232   surf_action_state_t action_state =
233       &(action->resource_type->common_public->states);
234   XBT_IN2("(%p,%s)", action, surf_action_state_names[state]);
235   xbt_swag_remove(action, action->state_set);
236
237   if (state == SURF_ACTION_READY)
238     action->state_set = action_state->ready_action_set;
239   else if (state == SURF_ACTION_RUNNING)
240     action->state_set = action_state->running_action_set;
241   else if (state == SURF_ACTION_FAILED)
242     action->state_set = action_state->failed_action_set;
243   else if (state == SURF_ACTION_DONE)
244     action->state_set = action_state->done_action_set;
245   else
246     action->state_set = NULL;
247
248   if (action->state_set)
249     xbt_swag_insert(action, action->state_set);
250   XBT_OUT;
251 }
252
253 void surf_action_set_data(surf_action_t action,
254                           void *data)
255 {
256   action->data=data;
257 }
258
259 void surf_init(int *argc, char **argv)
260 {
261   int i,j;
262   char *opt;
263   
264   const char* initial_path;
265
266   xbt_init(argc, argv);
267   if (!surf_path) {
268     
269     /* retrieves the current directory of the current process*/
270     initial_path = __surf_get_initial_path();
271                 
272         xbt_assert0((initial_path), "__surf_get_initial_path() failed! Can't resolves current Windows directory");
273     
274     surf_path = xbt_dynar_new(sizeof(char*), NULL);
275     xbt_dynar_push(surf_path,&initial_path);
276
277     for (i=1; i<*argc; i++) {
278       if (!strncmp(argv[i],"--surf-path=",strlen("--surf-path="))) {
279         opt=strchr(argv[i],'=');
280         opt++;
281         xbt_dynar_push(surf_path,&opt);
282         /*remove this from argv*/
283         for (j=i+1; j<*argc; j++) {
284           argv[j-1] = argv[j];
285         } 
286         argv[j-1] = NULL;
287         (*argc)--;
288         i--; /* compensate effect of next loop incrementation */
289       }
290     }
291   }
292   if (!resource_list)
293     resource_list = xbt_dynar_new(sizeof(surf_resource_private_t), NULL);
294   if (!history)
295     history = tmgr_history_new();
296   if (!maxmin_system)
297     maxmin_system = lmm_system_new();
298 }
299
300 static char* path_name = NULL;
301 FILE *surf_fopen(const char *name, const char *mode)
302 {
303   int i; 
304   char* path = NULL;
305   FILE *file = NULL;
306   int path_name_len = 0; /* don't count '\0' */
307
308   xbt_assert0(name, "Need a non-NULL file name");
309
310   xbt_assert0(surf_path,"surf_init has to be called before using surf_fopen");
311    
312   if (__surf_is_absolute_file_path(name)) { /* don't mess with absolute file names */
313     return fopen(name,mode);
314      
315   } else { /* search relative files in the path */
316    
317     if(!path_name) {
318        path_name_len = strlen(name);
319        path_name=xbt_new0(char,path_name_len+1);
320     }
321
322     xbt_dynar_foreach(surf_path,i,path) {
323       if(path_name_len < strlen(path)+strlen(name)+1) {
324          path_name_len = strlen(path)+strlen(name)+1; /* plus '/' */
325          path_name=xbt_realloc(path_name,path_name_len+1);
326       }
327       sprintf(path_name,"%s/%s",path, name);
328       file = fopen(path_name,mode);
329       if (file) return file;
330     }
331   }
332   return file;
333 }
334
335 void surf_exit(void)
336 {
337   int i;
338   surf_resource_t resource = NULL;
339
340   xbt_dynar_foreach(resource_list, i, resource) {
341     resource->common_private->finalize();
342   }
343
344   if (maxmin_system) {
345     lmm_system_free(maxmin_system);
346     maxmin_system = NULL;
347   }
348   if (history) {
349     tmgr_history_free(history);
350     history = NULL;
351   }
352   if (resource_list)
353     xbt_dynar_free(&resource_list);
354
355   if(surf_path) 
356     xbt_dynar_free(&surf_path);
357
358   tmgr_finalize();
359   surf_parse_lex_destroy();
360   if(path_name) {
361     free(path_name);
362     path_name = NULL;
363   }
364   xbt_exit();
365 }
366
367 double surf_solve(void)
368 {
369   static int first_run = 1;
370
371   double min = -1.0;
372   double next_event_date = -1.0;
373   double resource_next_action_end = -1.0;
374   double value = -1.0;
375   surf_resource_object_t resource_obj = NULL;
376   surf_resource_t resource = NULL;
377   tmgr_trace_event_t event = NULL;
378   int i;
379
380   if (first_run) {
381     DEBUG0("First Run! Let's \"purge\" events and put resources in the right state");
382     while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
383       if (next_event_date > NOW)
384         break;
385       while ((event =
386               tmgr_history_get_next_event_leq(history, next_event_date,
387                                               &value,
388                                               (void **) &resource_obj))) {
389         resource_obj->resource->common_private->
390             update_resource_state(resource_obj, event, value);
391       }
392     }
393     xbt_dynar_foreach(resource_list, i, resource) {
394       resource->common_private->update_actions_state(NOW, 0.0);
395     }
396     first_run = 0;
397     return 0.0;
398   }
399
400   min = -1.0;
401
402   DEBUG0("Looking for next action end");
403   xbt_dynar_foreach(resource_list, i, resource) {
404     resource_next_action_end =
405         resource->common_private->share_resources(NOW);
406     DEBUG2("Resource [%s] : next action end = %f",resource->common_public->name,
407            resource_next_action_end);
408     if (((min < 0.0) || (resource_next_action_end < min))
409         && (resource_next_action_end >= 0.0))
410       min = resource_next_action_end;
411   }
412   DEBUG1("Next action end : %f", min);
413
414   if (min < 0.0)
415     return -1.0;
416
417   DEBUG0("Looking for next event");
418   while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
419     DEBUG1("Next event : %f",next_event_date);
420     if (next_event_date > NOW + min)
421       break;
422     DEBUG0("Updating resources");
423     while ((event =
424             tmgr_history_get_next_event_leq(history, next_event_date,
425                                             &value,
426                                             (void **) &resource_obj))) {
427       if (resource_obj->resource->common_private->
428           resource_used(resource_obj)) {
429         min = next_event_date - NOW;
430         DEBUG1("This event will modify resource state. Next event set to %f", min);
431       }
432       /* update state of resource_obj according to new value. Does not touch lmm.
433          It will be modified if needed when updating actions */
434       resource_obj->resource->common_private->
435           update_resource_state(resource_obj, event, value);
436     }
437   }
438
439   DEBUG1("Duration set to %f", min);
440
441   NOW = NOW + min;
442
443   xbt_dynar_foreach(resource_list, i, resource) {
444     resource->common_private->update_actions_state(NOW, min);
445   }
446
447   return min;
448 }
449
450 double surf_get_clock(void)
451 {
452   return NOW;
453 }