Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
SURF: Kill the SDP model
[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_lagrange_solver = 0; KILLME
17
18 /* Additional declarations for Windows potability. */
19
20 #ifndef MAX_DRIVE
21 #define MAX_DRIVE 26
22 #endif
23
24 #ifdef _WIN32
25 #include <windows.h>
26 static const char *disk_drives_letter_table[MAX_DRIVE] = {
27   "A:\\",
28   "B:\\",
29   "C:\\",
30   "D:\\",
31   "E:\\",
32   "F:\\",
33   "G:\\",
34   "H:\\",
35   "I:\\",
36   "J:\\",
37   "K:\\",
38   "L:\\",
39   "M:\\",
40   "N:\\",
41   "O:\\",
42   "P:\\",
43   "Q:\\",
44   "R:\\",
45   "S:\\",
46   "T:\\",
47   "U:\\",
48   "V:\\",
49   "W:\\",
50   "X:\\",
51   "Y:\\",
52   "Z:\\"
53 };
54 #endif /* #ifdef _WIN32 */
55
56 /*
57  * Returns the initial path. On Windows the initial path is
58  * the current directory for the current process in the other
59  * case the function returns "./" that represents the current
60  * directory on Unix/Linux platforms.
61  */
62
63 const char *__surf_get_initial_path(void)
64 {
65
66 #ifdef _WIN32
67   unsigned i;
68   char current_directory[MAX_PATH + 1] = { 0 };
69   unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
70   char root[4] = { 0 };
71
72   if (!len)
73     return NULL;
74
75   strncpy(root, current_directory, 3);
76
77   for (i = 0; i < MAX_DRIVE; i++) {
78     if (toupper(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 static double NOW = 0;
109
110 xbt_dynar_t model_list = NULL;
111 tmgr_history_t history = NULL;
112 lmm_system_t maxmin_system = NULL;
113 xbt_dynar_t surf_path = NULL;
114
115 /* Don't forget to update the option description in smx_config when you change this */
116 s_surf_model_description_t surf_network_model_description[] = {
117   {"Constant", NULL, surf_network_model_init_Constant},
118   {"CM02", NULL, surf_network_model_init_CM02},
119   {"LegrandVelho", NULL, surf_network_model_init_LegrandVelho},
120 #ifdef HAVE_GTNETS
121   {"GTNets", NULL, surf_network_model_init_GTNETS},
122 #endif
123   {"Reno", NULL, surf_network_model_init_Reno},
124   {"Reno2", NULL, surf_network_model_init_Reno2},
125   {"Vegas", NULL, surf_network_model_init_Vegas},
126   {NULL, NULL, NULL}            /* this array must be NULL terminated */
127 };
128
129 s_surf_model_description_t surf_cpu_model_description[] = {
130   {"Cas01", NULL, surf_cpu_model_init_Cas01},
131   {NULL, NULL, NULL}            /* this array must be NULL terminated */
132 };
133
134 s_surf_model_description_t surf_workstation_model_description[] = {
135   {"CLM03", NULL, surf_workstation_model_init_CLM03, create_workstations},
136   {"compound", NULL, surf_workstation_model_init_compound,
137    create_workstations},
138   {"ptask_L07", NULL, surf_workstation_model_init_ptask_L07, NULL},
139   {NULL, NULL, NULL}            /* this array must be NULL terminated */
140 };
141
142 void update_model_description(s_surf_model_description_t * table,
143                               const char *name, surf_model_t model)
144 {
145   int i = find_model_description(table, name);
146   table[i].model = model;
147 }
148
149 int find_model_description(s_surf_model_description_t * table,
150                            const char *name)
151 {
152   int i;
153   char *name_list = NULL;
154
155   for (i = 0; table[i].name; i++)
156     if (!strcmp(name, table[i].name)) {
157       return i;
158     }
159   name_list = strdup(table[0].name);
160   for (i = 1; table[i].name; i++) {
161     name_list =
162       xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 2);
163     strcat(name_list, ", ");
164     strcat(name_list, table[i].name);
165   }
166   xbt_assert2(0, "Model '%s' is invalid! Valid models are: %s.", name,
167               name_list);
168 }
169
170 double generic_maxmin_share_resources(xbt_swag_t running_actions,
171                                       size_t offset,
172                                       lmm_system_t sys,
173                                       void (*solve) (lmm_system_t))
174 {
175   surf_action_t action = NULL;
176   double min = -1;
177   double value = -1;
178 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
179
180   xbt_assert0(solve, "Give me a real solver function!");
181   solve(sys);
182
183   xbt_swag_foreach(action, running_actions) {
184     value = lmm_variable_getvalue(VARIABLE(action));
185     if ((value > 0) || (action->max_duration >= 0))
186       break;
187   }
188
189   if (!action)
190     return -1.0;
191
192   if (value > 0) {
193     if (action->remains > 0)
194       min = action->remains / value;
195     else
196       min = 0.0;
197     if ((action->max_duration >= 0) && (action->max_duration < min))
198       min = action->max_duration;
199   } else
200     min = action->max_duration;
201
202
203   for (action = xbt_swag_getNext(action, running_actions->offset);
204        action; action = xbt_swag_getNext(action, running_actions->offset)) {
205     value = lmm_variable_getvalue(VARIABLE(action));
206     if (value > 0) {
207       if (action->remains > 0)
208         value = action->remains / value;
209       else
210         value = 0.0;
211       if (value < min) {
212         min = value;
213         DEBUG2("Updating min (value) with %p: %f", action, min);
214       }
215     }
216     if ((action->max_duration >= 0) && (action->max_duration < min)) {
217       min = action->max_duration;
218       DEBUG2("Updating min (duration) with %p: %f", action, min);
219     }
220   }
221   DEBUG1("min value : %f", min);
222
223 #undef VARIABLE
224   return min;
225 }
226
227
228 XBT_LOG_EXTERNAL_CATEGORY(surf_cpu);
229 XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
230 XBT_LOG_EXTERNAL_CATEGORY(surf_lagrange);
231 XBT_LOG_EXTERNAL_CATEGORY(surf_lagrange_dichotomy);
232 XBT_LOG_EXTERNAL_CATEGORY(surf_maxmin);
233 XBT_LOG_EXTERNAL_CATEGORY(surf_network);
234 XBT_LOG_EXTERNAL_CATEGORY(surf_trace);
235 XBT_LOG_EXTERNAL_CATEGORY(surf_parse);
236 XBT_LOG_EXTERNAL_CATEGORY(surf_timer);
237 XBT_LOG_EXTERNAL_CATEGORY(surf_workstation);
238 XBT_LOG_EXTERNAL_CATEGORY(surf_config);
239
240
241 #ifdef HAVE_GTNETS
242 XBT_LOG_EXTERNAL_CATEGORY(surf_network_gtnets);
243 #endif
244
245 void surf_init(int *argc, char **argv)
246 {
247   /* Connect our log channels: that must be done manually under windows */
248   XBT_LOG_CONNECT(surf_cpu, surf);
249   XBT_LOG_CONNECT(surf_kernel, surf);
250   XBT_LOG_CONNECT(surf_lagrange, surf);
251   XBT_LOG_CONNECT(surf_lagrange_dichotomy, surf_lagrange);
252   XBT_LOG_CONNECT(surf_maxmin, surf);
253   XBT_LOG_CONNECT(surf_network, surf);
254   XBT_LOG_CONNECT(surf_trace, surf);
255   XBT_LOG_CONNECT(surf_parse, surf);
256   XBT_LOG_CONNECT(surf_timer, surf);
257   XBT_LOG_CONNECT(surf_workstation, surf);
258   XBT_LOG_CONNECT(surf_config, surf);
259
260 #ifdef HAVE_GTNETS
261   XBT_LOG_CONNECT(surf_network_gtnets, surf);
262 #endif
263
264   xbt_init(argc, argv);
265   if (!model_list)
266     model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
267   if (!history)
268     history = tmgr_history_new();
269
270   surf_config_init(argc, argv);
271 }
272
273 static char *path_name = NULL;
274 FILE *surf_fopen(const char *name, const char *mode)
275 {
276   unsigned int iter;
277   char *path = NULL;
278   FILE *file = NULL;
279   unsigned int path_name_len = 0;       /* don't count '\0' */
280
281   xbt_assert0(name, "Need a non-NULL file name");
282
283   xbt_assert0(surf_path,
284               "surf_init has to be called before using surf_fopen");
285
286   if (__surf_is_absolute_file_path(name)) {     /* don't mess with absolute file names */
287     return fopen(name, mode);
288
289   } else {                      /* search relative files in the path */
290
291     if (!path_name) {
292       path_name_len = strlen(name);
293       path_name = xbt_new0(char, path_name_len + 1);
294     }
295
296     xbt_dynar_foreach(surf_path, iter, path) {
297       if (path_name_len < strlen(path) + strlen(name) + 1) {
298         path_name_len = strlen(path) + strlen(name) + 1;        /* plus '/' */
299         path_name = xbt_realloc(path_name, path_name_len + 1);
300       }
301 #ifdef WIN32
302       sprintf(path_name, "%s\\%s", path, name);
303 #else
304       sprintf(path_name, "%s/%s", path, name);
305 #endif
306       file = fopen(path_name, mode);
307       if (file)
308         return file;
309     }
310   }
311   return file;
312 }
313
314 void surf_exit(void)
315 {
316   unsigned int iter;
317   surf_model_t model = NULL;
318
319   surf_config_finalize();
320
321   xbt_dynar_foreach(model_list, iter, model) {
322     model->model_private->finalize();
323   }
324
325   if (maxmin_system) {
326     lmm_system_free(maxmin_system);
327     maxmin_system = NULL;
328   }
329   if (history) {
330     tmgr_history_free(history);
331     history = NULL;
332   }
333   if (model_list)
334     xbt_dynar_free(&model_list);
335
336   if (surf_path)
337     xbt_dynar_free(&surf_path);
338
339   tmgr_finalize();
340   surf_parse_lex_destroy();
341   if (path_name) {
342     free(path_name);
343     path_name = NULL;
344   }
345   surf_parse_free_callbacks();
346   xbt_dict_free(&route_table);
347   NOW = 0;                      /* Just in case the user plans to restart the simulation afterward */
348   xbt_exit();
349 }
350
351 void surf_presolve(void)
352 {
353   double next_event_date = -1.0;
354   tmgr_trace_event_t event = NULL;
355   double value = -1.0;
356   surf_resource_t resource = NULL;
357   surf_model_t model = NULL;
358   unsigned int iter;
359
360   DEBUG0
361     ("First Run! Let's \"purge\" events and put models in the right state");
362   while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
363     if (next_event_date > NOW)
364       break;
365     while ((event =
366             tmgr_history_get_next_event_leq(history, next_event_date,
367                                             &value, (void **) &resource))) {
368       resource->model->model_private->update_resource_state(resource,
369                                                             event, value,
370                                                             NOW);
371     }
372   }
373   xbt_dynar_foreach(model_list, iter, model) {
374     model->model_private->update_actions_state(NOW, 0.0);
375   }
376 }
377
378 double surf_solve(void)
379 {
380   double min = -1.0;
381   double next_event_date = -1.0;
382   double model_next_action_end = -1.0;
383   double value = -1.0;
384   surf_resource_t resource = NULL;
385   surf_model_t model = NULL;
386   tmgr_trace_event_t event = NULL;
387   unsigned int iter;
388
389   min = -1.0;
390
391   DEBUG0("Looking for next action end");
392   xbt_dynar_foreach(model_list, iter, model) {
393     DEBUG1("Running for Resource [%s]", model->name);
394     model_next_action_end = model->model_private->share_resources(NOW);
395     DEBUG2("Resource [%s] : next action end = %f",
396            model->name, model_next_action_end);
397     if (((min < 0.0) || (model_next_action_end < min))
398         && (model_next_action_end >= 0.0))
399       min = model_next_action_end;
400   }
401   DEBUG1("Next action end : %f", min);
402
403   if (min < 0.0)
404     return -1.0;
405
406   DEBUG0("Looking for next event");
407   while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
408     DEBUG1("Next event : %f", next_event_date);
409     if (next_event_date > NOW + min)
410       break;
411     DEBUG0("Updating models");
412     while ((event =
413             tmgr_history_get_next_event_leq(history, next_event_date,
414                                             &value, (void **) &resource))) {
415       if (resource->model->model_private->resource_used(resource)) {
416         min = next_event_date - NOW;
417         DEBUG1
418           ("This event will modify model state. Next event set to %f", min);
419       }
420       /* update state of model_obj according to new value. Does not touch lmm.
421          It will be modified if needed when updating actions */
422       resource->model->model_private->update_resource_state(resource,
423                                                             event, value,
424                                                             NOW + min);
425     }
426   }
427
428   DEBUG1("Duration set to %f", min);
429
430   NOW = NOW + min;
431
432   xbt_dynar_foreach(model_list, iter, model) {
433     model->model_private->update_actions_state(NOW, min);
434   }
435
436   return min;
437 }
438
439 double surf_get_clock(void)
440 {
441   return NOW;
442 }