Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix problems so that the VM example works
[simgrid.git] / src / surf / workstation.c
1 /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "xbt/ex.h"
8 #include "xbt/dict.h"
9 #include "portable.h"
10 #include "surf_private.h"
11 #include "storage_private.h"
12 #include "surf/surf_resource.h"
13 #include "simgrid/sg_config.h"
14 #include "workstation_private.h"
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_workstation, surf,
17                                 "Logging specific to the SURF workstation module");
18
19 surf_model_t surf_workstation_model = NULL;
20
21
22 static void workstation_new(sg_platf_host_cbarg_t host)
23 {
24   const char *name = host->id;
25
26   /* NOTE: The properties object is NULL, because the current code uses that of
27    * that of a cpu resource. */
28   workstation_CLM03_t ws = (workstation_CLM03_t) surf_resource_new(sizeof(s_workstation_CLM03_t), surf_workstation_model, name, NULL);
29
30   ws->storage = xbt_lib_get_or_null(storage_lib, name, ROUTING_STORAGE_HOST_LEVEL);
31   ws->net_elm = xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL);
32
33   XBT_DEBUG("Create ws %s with %ld mounted disks", name, xbt_dynar_length(ws->storage));
34   xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, ws);
35 }
36
37
38 static void ws_parallel_action_cancel(surf_action_t action)
39 {
40   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
41 }
42
43 static int ws_parallel_action_free(surf_action_t action)
44 {
45   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
46   return -1;
47 }
48
49 int ws_action_unref(surf_action_t action)
50 {
51   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
52     return surf_network_model->action_unref(action);
53   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
54     return action->model_obj->action_unref(action);
55       // previously was: Adrien/Arnaud 6 feb
56           // surf_cpu_model->action_unref(action);
57   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
58     return ws_parallel_action_free(action);
59   else
60     DIE_IMPOSSIBLE;
61   return 0;
62 }
63
64 void ws_action_cancel(surf_action_t action)
65 {
66   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
67     surf_network_model->action_cancel(action);
68   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
69     action->model_obj->action_cancel(action);
70   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
71     ws_parallel_action_cancel(action);
72   else
73     DIE_IMPOSSIBLE;
74   return;
75 }
76
77 static void ws_action_state_set(surf_action_t action,
78                                 e_surf_action_state_t state)
79 {
80   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
81     surf_network_model->action_state_set(action, state);
82   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
83     action->model_obj->action_state_set(action, state);
84   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
85     surf_action_state_set(action, state);
86   else
87     DIE_IMPOSSIBLE;
88   return;
89 }
90
91
92 /* -- The callback functions at model_private -- */
93 /* These callbacks are also used for the vm workstation model. */
94 int ws_resource_used(void *resource_id)
95 {
96   /* This model does not implement parallel tasks */
97   THROW_IMPOSSIBLE;
98   return -1;
99 }
100
101 double ws_share_resources(surf_model_t workstation_model, double now)
102 {
103   /* Invoke the share_resources() callback of the physical cpu model object and
104    * the network model objects. */
105   surf_model_t cpu_model = workstation_model->extension.workstation.cpu_model;
106   surf_model_t net_model = surf_network_model;
107
108   double min_by_cpu = cpu_model->model_private->share_resources(cpu_model, now);
109   double min_by_net = net_model->model_private->share_resources(net_model, now);
110
111   XBT_DEBUG("model %p, %s min_by_cpu %f, %s min_by_net %f",
112       workstation_model, cpu_model->name, min_by_cpu, net_model->name, min_by_net);
113
114   if (min_by_cpu >= 0.0 && min_by_net >= 0.0)
115     return min(min_by_cpu, min_by_net);
116   else if (min_by_cpu >= 0.0)
117     return min_by_cpu;
118   else if (min_by_net >= 0.0)
119     return min_by_net;
120   else
121     return min_by_cpu;  /* probably min_by_cpu == min_by_net == -1 */
122 }
123
124 void ws_update_actions_state(surf_model_t workstation_model, double now, double delta)
125 {
126   return;
127 }
128
129 void ws_update_resource_state(void *id, tmgr_trace_event_t event_type, double value, double date)
130 {
131   /* This model does not implement parallel tasks */
132   THROW_IMPOSSIBLE;
133 }
134
135 void ws_finalize(surf_model_t workstation_model)
136 {
137   surf_model_exit(workstation_model);
138   workstation_model = NULL;
139 }
140
141
142
143 surf_action_t ws_execute(void *workstation, double size)
144 {
145   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
146   return cpu->model->extension.cpu.execute(workstation, size);
147 }
148
149 surf_action_t ws_action_sleep(void *workstation, double duration)
150 {
151   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
152   return cpu->model->extension.cpu.sleep(workstation, duration);
153 }
154
155 void ws_action_suspend(surf_action_t action)
156 {
157   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
158     surf_network_model->suspend(action);
159   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
160     action->model_obj->suspend(action);
161   else
162     DIE_IMPOSSIBLE;
163 }
164
165 void ws_action_resume(surf_action_t action)
166 {
167   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
168     surf_network_model->resume(action);
169   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
170     action->model_obj->resume(action);
171   else
172     DIE_IMPOSSIBLE;
173 }
174
175 static int ws_action_is_suspended(surf_action_t action)
176 {
177   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
178     return surf_network_model->is_suspended(action);
179   if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
180     return action->model_obj->is_suspended(action);
181   DIE_IMPOSSIBLE;
182   return -1;
183 }
184
185 static void ws_action_set_max_duration(surf_action_t action,
186                                        double duration)
187 {
188   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
189     surf_network_model->set_max_duration(action, duration);
190   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
191     action->model_obj->set_max_duration(action, duration);
192   else
193     DIE_IMPOSSIBLE;
194 }
195
196 void ws_action_set_priority(surf_action_t action, double priority)
197 {
198   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
199     surf_network_model->set_priority(action, priority);
200   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
201     action->model_obj->set_priority(action, priority);
202   else
203     DIE_IMPOSSIBLE;
204 }
205
206 #ifdef HAVE_TRACING
207 static void ws_action_set_category(surf_action_t action, const char *category)
208 {
209   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
210     surf_network_model->set_category(action, category);
211   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
212     action->model_obj->set_category(action, category);
213   else
214     DIE_IMPOSSIBLE;
215 }
216 #endif
217
218 #ifdef HAVE_LATENCY_BOUND_TRACKING
219 static int ws_get_latency_limited(surf_action_t action)
220 {
221   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
222     return surf_network_model->get_latency_limited(action);
223   else
224     return 0;
225 }
226 #endif
227
228 static double ws_action_get_remains(surf_action_t action)
229 {
230   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
231     return surf_network_model->get_remains(action);
232   if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
233     return action->model_obj->get_remains(action);
234   DIE_IMPOSSIBLE;
235   return -1.0;
236 }
237
238 static surf_action_t ws_communicate(void *workstation_src,
239                                     void *workstation_dst, double size,
240                                     double rate)
241 {
242   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
243   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
244   return surf_network_model->extension.network.
245       communicate(src->net_elm,
246                   dst->net_elm, size, rate);
247 }
248
249 e_surf_resource_state_t ws_get_state(void *workstation)
250 {
251   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
252   return cpu->model->extension.cpu.get_state(workstation);
253 }
254
255 static double ws_get_speed(void *workstation, double load)
256 {
257   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
258   return cpu->model->extension.cpu.get_speed(workstation, load);
259 }
260
261 static double ws_get_available_speed(void *workstation)
262 {
263   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
264   return cpu->model->extension.cpu.get_available_speed(workstation);
265 }
266
267 static surf_action_t ws_execute_parallel_task(int workstation_nb,
268                                               void **workstation_list,
269                                               double *computation_amount,
270                                               double *communication_amount,
271                                               double rate)
272 {
273 #define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0)
274   if ((workstation_nb == 1)
275       && (cost_or_zero(communication_amount, 0) == 0.0))
276     return ws_execute(workstation_list[0], computation_amount[0]);
277   else if ((workstation_nb == 1)
278            && (cost_or_zero(computation_amount, 0) == 0.0))
279     return ws_communicate(workstation_list[0], workstation_list[0],communication_amount[0], rate);
280   else if ((workstation_nb == 2)
281              && (cost_or_zero(computation_amount, 0) == 0.0)
282              && (cost_or_zero(computation_amount, 1) == 0.0)) {
283     int i,nb = 0;
284     double value = 0.0;
285
286     for (i = 0; i < workstation_nb * workstation_nb; i++) {
287       if (cost_or_zero(communication_amount, i) > 0.0) {
288         nb++;
289         value = cost_or_zero(communication_amount, i);
290       }
291     }
292     if (nb == 1)
293       return ws_communicate(workstation_list[0], workstation_list[1],value, rate);
294   }
295 #undef cost_or_zero
296
297   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
298   return NULL;
299 }
300
301
302 /* returns an array of network_link_CM02_t */
303 static xbt_dynar_t ws_get_route(void *workstation_src, void *workstation_dst)
304 {
305   XBT_DEBUG("ws_get_route");
306   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
307   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
308   return surf_network_model->extension.
309       network.get_route(src->net_elm,
310                   dst->net_elm);
311 }
312
313 static double ws_get_link_bandwidth(const void *link)
314 {
315   return surf_network_model->extension.network.get_link_bandwidth(link);
316 }
317
318 static double ws_get_link_latency(const void *link)
319 {
320   return surf_network_model->extension.network.get_link_latency(link);
321 }
322
323 static int ws_link_shared(const void *link)
324 {
325   return surf_network_model->extension.network.link_shared(link);
326 }
327
328 static xbt_dict_t ws_get_properties(const void *ws)
329 {
330   return surf_resource_properties(surf_cpu_resource_priv(ws));
331 }
332
333 static storage_t find_storage_on_mount_list(void *workstation,const char* storage)
334 {
335   storage_t st = NULL;
336   s_mount_t mnt;
337   unsigned int cursor;
338   workstation_CLM03_t ws = (workstation_CLM03_t) surf_workstation_resource_priv(workstation);
339   xbt_dynar_t storage_list = ws->storage;
340
341   XBT_DEBUG("Search for storage name '%s' on '%s'",storage,ws->generic_resource.name);
342   xbt_dynar_foreach(storage_list,cursor,mnt)
343   {
344     XBT_DEBUG("See '%s'",mnt.name);
345     if(!strcmp(storage,mnt.name)){
346       st = mnt.id;
347       break;
348     }
349   }
350   if(!st) xbt_die("Can't find mount '%s' for '%s'",storage,ws->generic_resource.name);
351   return st;
352 }
353
354 static surf_action_t ws_action_open(void *workstation, const char* mount, const char* path, const char* mode)
355 {
356   storage_t st = find_storage_on_mount_list(workstation, mount);
357   XBT_DEBUG("OPEN on disk '%s'",st->generic_resource.name);
358   surf_model_t model = st->generic_resource.model;
359   return model->extension.storage.open(st, mount, path, mode);
360 }
361
362 static surf_action_t ws_action_close(void *workstation, surf_file_t fp)
363 {
364   storage_t st = find_storage_on_mount_list(workstation, fp->storage);
365   XBT_DEBUG("CLOSE on disk '%s'",st->generic_resource.name);
366   surf_model_t model = st->generic_resource.model;
367   return model->extension.storage.close(st, fp);
368 }
369
370 static surf_action_t ws_action_read(void *workstation, void* ptr, size_t size, size_t nmemb, surf_file_t stream)
371 {
372   storage_t st = find_storage_on_mount_list(workstation, stream->storage);
373   XBT_DEBUG("READ on disk '%s'",st->generic_resource.name);
374   surf_model_t model = st->generic_resource.model;
375   return model->extension.storage.read(st, ptr, (double)size, nmemb, stream);
376 }
377
378 static surf_action_t ws_action_write(void *workstation, const void* ptr, size_t size, size_t nmemb, surf_file_t stream)
379 {
380   storage_t st = find_storage_on_mount_list(workstation, stream->storage);
381   XBT_DEBUG("WRITE on disk '%s'",st->generic_resource.name);
382   surf_model_t model = st->generic_resource.model;
383   return model->extension.storage.write(st,  ptr, size, nmemb, stream);
384 }
385
386 static surf_action_t ws_action_stat(void *workstation, surf_file_t stream)
387 {
388   storage_t st = find_storage_on_mount_list(workstation, stream->storage);
389   XBT_DEBUG("STAT on disk '%s'",st->generic_resource.name);
390   surf_model_t model = st->generic_resource.model;
391   return model->extension.storage.stat(st,  stream);
392 }
393
394 static surf_action_t ws_action_unlink(void *workstation, surf_file_t stream)
395 {
396   storage_t st = find_storage_on_mount_list(workstation, stream->storage);
397   XBT_DEBUG("UNLINK on disk '%s'",st->generic_resource.name);
398   surf_model_t model = st->generic_resource.model;
399   return model->extension.storage.unlink(st,  stream);
400 }
401
402 static surf_action_t ws_action_ls(void *workstation, const char* mount, const char *path)
403 {
404   XBT_DEBUG("LS on mount '%s' and file '%s'",mount, path);
405   storage_t st = find_storage_on_mount_list(workstation, mount);
406   surf_model_t model = st->generic_resource.model;
407   return model->extension.storage.ls(st, path);
408 }
409
410 static void surf_workstation_model_init_internal(void)
411 {
412   surf_model_t model = surf_model_init();
413
414   model->name = "Workstation";
415   model->type = SURF_MODEL_TYPE_WORKSTATION;
416   model->action_unref     = ws_action_unref;
417   model->action_cancel    = ws_action_cancel;
418   model->action_state_set = ws_action_state_set;
419
420   model->model_private->resource_used         = ws_resource_used;
421   model->model_private->share_resources       = ws_share_resources;
422   model->model_private->update_actions_state  = ws_update_actions_state;
423   model->model_private->update_resource_state = ws_update_resource_state;
424   model->model_private->finalize              = ws_finalize;
425
426   model->suspend          = ws_action_suspend;
427   model->resume           = ws_action_resume;
428   model->is_suspended     = ws_action_is_suspended;
429   model->set_max_duration = ws_action_set_max_duration;
430   model->set_priority     = ws_action_set_priority;
431   #ifdef HAVE_TRACING
432   model->set_category     = ws_action_set_category;
433   #endif
434   model->get_remains      = ws_action_get_remains;
435   #ifdef HAVE_LATENCY_BOUND_TRACKING
436   model->get_latency_limited = ws_get_latency_limited;
437   #endif
438
439   /* For VM support, we have a surf cpu model object for each workstation model
440    * object. The physical workstation model object has the cpu model object of
441    * the physical machine layer. */
442   xbt_assert(surf_cpu_model_pm);
443   model->extension.workstation.cpu_model = surf_cpu_model_pm;
444
445   model->extension.workstation.execute   = ws_execute;
446   model->extension.workstation.sleep     = ws_action_sleep;
447   model->extension.workstation.get_state = ws_get_state;
448   model->extension.workstation.get_speed = ws_get_speed;
449   model->extension.workstation.get_available_speed = ws_get_available_speed;
450
451   model->extension.workstation.communicate           = ws_communicate;
452   model->extension.workstation.get_route             = ws_get_route;
453   model->extension.workstation.execute_parallel_task = ws_execute_parallel_task;
454   model->extension.workstation.get_link_bandwidth    = ws_get_link_bandwidth;
455   model->extension.workstation.get_link_latency      = ws_get_link_latency;
456   model->extension.workstation.link_shared           = ws_link_shared;
457   model->extension.workstation.get_properties        = ws_get_properties;
458
459   model->extension.workstation.open   = ws_action_open;
460   model->extension.workstation.close  = ws_action_close;
461   model->extension.workstation.read   = ws_action_read;
462   model->extension.workstation.write  = ws_action_write;
463   model->extension.workstation.stat   = ws_action_stat;
464   model->extension.workstation.unlink = ws_action_unlink;
465   model->extension.workstation.ls     = ws_action_ls;
466
467   surf_workstation_model = model;
468 }
469
470 void surf_workstation_model_init_current_default(void)
471 {
472   xbt_cfg_setdefault_int(_sg_cfg_set, "network/crosstraffic", 1);
473   surf_cpu_model_init_Cas01();
474   surf_network_model_init_LegrandVelho();
475
476   /* surf_cpu_mode_pm and surf_network_model must be initialized in advance. */
477   xbt_assert(surf_cpu_model_pm);
478   xbt_assert(surf_network_model);
479   surf_workstation_model_init_internal();
480
481   xbt_dynar_push(model_list, &surf_workstation_model);
482   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
483   sg_platf_host_add_cb(workstation_new);
484 }
485
486 void surf_workstation_model_init_compound()
487 {
488   xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
489   xbt_assert(surf_network_model, "No network model defined yet!");
490
491   surf_workstation_model_init_internal();
492   xbt_dynar_push(model_list, &surf_workstation_model);
493   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
494   sg_platf_host_add_cb(workstation_new);
495 }