Logo AND Algorithmique Numérique Distribuée

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