Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'surf++'
[simgrid.git] / src / surf / workstation.c
1 /* Copyright (c) 2004-2013. 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 <<<<<<< HEAD
15 #include <inttypes.h>
16
17 typedef struct workstation_CLM03 {
18   s_surf_resource_t generic_resource;   /* Must remain first to add this to a trace */
19   void *net_elm;
20   xbt_dynar_t storage;
21 } s_workstation_CLM03_t, *workstation_CLM03_t;
22 ||||||| merged common ancestors
23
24 typedef struct workstation_CLM03 {
25   s_surf_resource_t generic_resource;   /* Must remain first to add this to a trace */
26   void *net_elm;
27   xbt_dynar_t storage;
28 } s_workstation_CLM03_t, *workstation_CLM03_t;
29 =======
30 #include "workstation_private.h"
31 #include "vm_workstation_private.h"
32 #include "cpu_cas01_private.h"
33 #include "maxmin_private.h"
34 >>>>>>> surf++
35
36 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_workstation, surf,
37                                 "Logging specific to the SURF workstation module");
38
39 surf_model_t surf_workstation_model = NULL;
40
41
42 static void workstation_new(sg_platf_host_cbarg_t host)
43 {
44   const char *name = host->id;
45
46   /* NOTE: The properties object is NULL, because the current code uses that of
47    * that of a cpu resource. */
48   workstation_CLM03_t ws = (workstation_CLM03_t) surf_resource_new(sizeof(s_workstation_CLM03_t), surf_workstation_model, name, NULL, NULL);
49
50   ws->storage = xbt_lib_get_or_null(storage_lib, name, ROUTING_STORAGE_HOST_LEVEL);
51   ws->net_elm = xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL);
52
53   XBT_DEBUG("Create ws %s with %ld mounted disks", name, xbt_dynar_length(ws->storage));
54   xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, ws);
55 }
56
57 static void ws_parallel_action_cancel(surf_action_t action)
58 {
59   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
60 }
61
62 static int ws_parallel_action_free(surf_action_t action)
63 {
64   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
65   return -1;
66 }
67
68 int ws_action_unref(surf_action_t action)
69 {
70   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
71     return surf_network_model->action_unref(action);
72   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
73     return action->model_obj->action_unref(action);
74       // previously was: Adrien/Arnaud 6 feb
75           // surf_cpu_model->action_unref(action);
76   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
77     return ws_parallel_action_free(action);
78   else
79     DIE_IMPOSSIBLE;
80   return 0;
81 }
82
83 void ws_action_cancel(surf_action_t action)
84 {
85   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
86     surf_network_model->action_cancel(action);
87   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
88     action->model_obj->action_cancel(action);
89   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
90     ws_parallel_action_cancel(action);
91   else
92     DIE_IMPOSSIBLE;
93   return;
94 }
95
96 static void ws_action_state_set(surf_action_t action,
97                                 e_surf_action_state_t state)
98 {
99   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
100     surf_network_model->action_state_set(action, state);
101   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
102     action->model_obj->action_state_set(action, state);
103   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
104     surf_action_state_set(action, state);
105   else
106     DIE_IMPOSSIBLE;
107   return;
108 }
109
110
111 /* -- The callback functions at model_private -- */
112 /* These callbacks are also used for the vm workstation model. */
113 int ws_resource_used(void *resource_id)
114 {
115   /* This model does not implement parallel tasks */
116   THROW_IMPOSSIBLE;
117   return -1;
118 }
119
120
121 /* TODO: iterating active constraint_set may be faster? */
122 #if 0
123 static void deactivate_dummy_cpu_action(void)
124 {
125   lmm_system_t sys = surf_cpu_model_vm->model_private->maxmin_system;
126
127   lmm_constraint_t cnst;
128   xbt_swag_foreach(cnst, &sys->active_constraint_set) {
129     /* get vcpu resource */
130     surf_resource_t cpu = lmm_constraint_id(cnst);
131     xbt_assert(cpu->model == surf_cpu_model_vm);
132
133     /* get vm_ws resource */
134     workstation_CLM03_t ws = xbt_lib_get_or_null(host_lib, cpu->name, SURF_WKS_LEVEL);
135
136     /* make sure we can cast */
137     xbt_assert(ws->generic_resouce.model == surf_vm_workstation_model);
138     workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
139
140     /* make it active in the PM layer */
141     surf_action_set_priority(vm_ws->cpu_action, 1);
142   }
143 }
144 #endif
145
146
147 /* TODO: Delete this unused code if everything looks good. */
148 #if 0
149 static int constraint_is_active(cpu_Cas01_t cpu_cas01)
150 {
151   surf_model_t cpu_model = cpu_cas01->generic_resource.model;
152   lmm_system_t sys = cpu_model->model_private->maxmin_system;
153   int found = 0;
154   lmm_constraint_t cnst_tmp;
155
156   xbt_swag_foreach(cnst_tmp, &sys->active_constraint_set) {
157     if (cnst_tmp == cpu_cas01->constraint) {
158       found = 1;
159       break;
160     }
161   }
162
163   return found;
164 }
165 #endif
166
167
168 /* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
169  * constraint (capacity) of the VM in the PM layer. If the VM does not have any
170  * active task, the dummy CPU action must be deactivated, so that the VM does
171  * not get any CPU share in the PM layer. */
172 static void adjust_weight_of_dummy_cpu_actions(void)
173 {
174   /* iterate for all hosts including virtual machines */
175   xbt_lib_cursor_t cursor;
176   char *key;
177   void **ind_host;
178
179   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
180     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
181     cpu_Cas01_t cpu_cas01 = ind_host[SURF_CPU_LEVEL];
182
183     if (!ws_clm03)
184       continue;
185     /* skip if it is not a virtual machine */
186     if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
187       continue;
188     xbt_assert(cpu_cas01, "cpu-less workstation");
189
190     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
191     workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
192
193     lmm_system_t sys = surf_cpu_model_vm->model_private->maxmin_system;
194     int is_active = lmm_constraint_used(sys, cpu_cas01->constraint);
195     // int is_active_old = constraint_is_active(cpu_cas01);
196
197     // {
198     //   xbt_assert(is_active == is_active_old, "%d %d", is_active, is_active_old);
199     // }
200
201     if (is_active) {
202       /* some tasks exist on this VM */
203       XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
204
205       /* FIXME: we shoud use lmm_update_variable_weight() ? */
206       /* FIXME: If we assgign 1.05 and 0.05, the system makes apparently wrong values. */
207       surf_action_set_priority(ws_vm2013->cpu_action, 1);
208
209     } else {
210       /* no task exits on this VM */
211       XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
212
213       surf_action_set_priority(ws_vm2013->cpu_action, 0);
214     }
215   }
216 }
217
218
219 double ws_share_resources(surf_model_t workstation_model, double now)
220 {
221   if (workstation_model->type == SURF_MODEL_TYPE_WORKSTATION)
222     adjust_weight_of_dummy_cpu_actions();
223
224   /* Invoke the share_resources() callback of the physical cpu model object and
225    * the network model objects. */
226   surf_model_t cpu_model = workstation_model->extension.workstation.cpu_model;
227   surf_model_t net_model = surf_network_model;
228
229   double min_by_cpu = cpu_model->model_private->share_resources(cpu_model, now);
230   double min_by_net = net_model->model_private->share_resources(net_model, now);
231
232   XBT_DEBUG("model %p, %s min_by_cpu %f, %s min_by_net %f",
233       workstation_model, cpu_model->name, min_by_cpu, net_model->name, min_by_net);
234
235   if (min_by_cpu >= 0.0 && min_by_net >= 0.0)
236     return min(min_by_cpu, min_by_net);
237   else if (min_by_cpu >= 0.0)
238     return min_by_cpu;
239   else if (min_by_net >= 0.0)
240     return min_by_net;
241   else
242     return min_by_cpu;  /* probably min_by_cpu == min_by_net == -1 */
243 }
244
245 void ws_update_actions_state(surf_model_t workstation_model, double now, double delta)
246 {
247   return;
248 }
249
250 void ws_update_resource_state(void *id, tmgr_trace_event_t event_type, double value, double date)
251 {
252   /* This model does not implement parallel tasks */
253   THROW_IMPOSSIBLE;
254 }
255
256 void ws_finalize(surf_model_t workstation_model)
257 {
258   surf_model_exit(workstation_model);
259   workstation_model = NULL;
260 }
261
262
263
264 surf_action_t ws_execute(void *workstation, double size)
265 {
266   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
267   return cpu->model->extension.cpu.execute(workstation, size);
268 }
269
270 surf_action_t ws_action_sleep(void *workstation, double duration)
271 {
272   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
273   return cpu->model->extension.cpu.sleep(workstation, duration);
274 }
275
276 void ws_action_suspend(surf_action_t action)
277 {
278   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
279     surf_network_model->suspend(action);
280   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
281     action->model_obj->suspend(action);
282   else
283     DIE_IMPOSSIBLE;
284 }
285
286 void ws_action_resume(surf_action_t action)
287 {
288   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
289     surf_network_model->resume(action);
290   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
291     action->model_obj->resume(action);
292   else
293     DIE_IMPOSSIBLE;
294 }
295
296 static int ws_action_is_suspended(surf_action_t action)
297 {
298   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
299     return surf_network_model->is_suspended(action);
300   if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
301     return action->model_obj->is_suspended(action);
302   DIE_IMPOSSIBLE;
303   return -1;
304 }
305
306 static void ws_action_set_max_duration(surf_action_t action,
307                                        double duration)
308 {
309   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
310     surf_network_model->set_max_duration(action, duration);
311   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
312     action->model_obj->set_max_duration(action, duration);
313   else
314     DIE_IMPOSSIBLE;
315 }
316
317 void ws_action_set_priority(surf_action_t action, double priority)
318 {
319   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
320     surf_network_model->set_priority(action, priority);
321   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
322     action->model_obj->set_priority(action, priority);
323   else
324     DIE_IMPOSSIBLE;
325 }
326
327 void ws_action_set_bound(surf_action_t action, double bound)
328 {
329   /* FIXME: only for CPU model object? */
330   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
331     surf_network_model->set_bound(action, bound);
332   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
333     action->model_obj->set_bound(action, bound);
334   else
335     DIE_IMPOSSIBLE;
336 }
337
338 void ws_action_set_affinity(surf_action_t action, void *workstation, unsigned long mask)
339 {
340   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
341     DIE_IMPOSSIBLE;
342   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
343     action->model_obj->set_affinity(action, workstation, mask);
344   else
345     DIE_IMPOSSIBLE;
346 }
347
348 #ifdef HAVE_TRACING
349 static void ws_action_set_category(surf_action_t action, const char *category)
350 {
351   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
352     surf_network_model->set_category(action, category);
353   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
354     action->model_obj->set_category(action, category);
355   else
356     DIE_IMPOSSIBLE;
357 }
358 #endif
359
360 #ifdef HAVE_LATENCY_BOUND_TRACKING
361 static int ws_get_latency_limited(surf_action_t action)
362 {
363   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
364     return surf_network_model->get_latency_limited(action);
365   else
366     return 0;
367 }
368 #endif
369
370 double ws_action_get_remains(surf_action_t action)
371 {
372   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
373     return surf_network_model->get_remains(action);
374   if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
375     return action->model_obj->get_remains(action);
376   DIE_IMPOSSIBLE;
377   return -1.0;
378 }
379
380 static surf_action_t ws_communicate(void *workstation_src,
381                                     void *workstation_dst, double size,
382                                     double rate)
383 {
384   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
385   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
386   return surf_network_model->extension.network.
387       communicate(src->net_elm,
388                   dst->net_elm, size, rate);
389 }
390
391 e_surf_resource_state_t ws_get_state(void *workstation)
392 {
393   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
394   return cpu->model->extension.cpu.get_state(workstation);
395 }
396
397 static void ws_set_state(void *workstation, e_surf_resource_state_t state)
398 {
399   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
400   cpu->model->extension.cpu.set_state(workstation, state);
401 }
402
403 double ws_get_speed(void *workstation, double load)
404 {
405   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
406   return cpu->model->extension.cpu.get_speed(workstation, load);
407 }
408
409 static int ws_get_core(void *workstation)
410 {
411   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
412   return cpu->model->extension.cpu.get_core(workstation);
413 }
414 static double ws_get_available_speed(void *workstation)
415 {
416   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
417   return cpu->model->extension.cpu.get_available_speed(workstation);
418 }
419
420 static double ws_get_current_power_peak(void *workstation)
421 {
422   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
423   return cpu->model->extension.cpu.
424       get_current_power_peak(workstation);
425 }
426
427 static double ws_get_power_peak_at(void *workstation, int pstate_index)
428 {
429   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
430   return cpu->model->extension.cpu.
431       get_power_peak_at(workstation, pstate_index);
432 }
433
434 static int ws_get_nb_pstates(void *workstation)
435 {
436   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
437   return cpu->model->extension.cpu.
438       get_nb_pstates(workstation);
439 }
440
441 static void ws_set_power_peak_at(void *workstation, int pstate_index)
442 {
443   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
444   cpu->model->extension.cpu.
445       set_power_peak_at(workstation, pstate_index);
446 }
447
448 static double ws_get_consumed_energy(void *workstation)
449 {
450   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
451   return cpu->model->extension.cpu.
452       get_consumed_energy(workstation);
453 }
454
455
456 static surf_action_t ws_execute_parallel_task(int workstation_nb,
457                                               void **workstation_list,
458                                               double *computation_amount,
459                                               double *communication_amount,
460                                               double rate)
461 {
462 #define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0)
463   if ((workstation_nb == 1)
464       && (cost_or_zero(communication_amount, 0) == 0.0))
465     return ws_execute(workstation_list[0], computation_amount[0]);
466   else if ((workstation_nb == 1)
467            && (cost_or_zero(computation_amount, 0) == 0.0))
468     return ws_communicate(workstation_list[0], workstation_list[0],communication_amount[0], rate);
469   else if ((workstation_nb == 2)
470              && (cost_or_zero(computation_amount, 0) == 0.0)
471              && (cost_or_zero(computation_amount, 1) == 0.0)) {
472     int i,nb = 0;
473     double value = 0.0;
474
475     for (i = 0; i < workstation_nb * workstation_nb; i++) {
476       if (cost_or_zero(communication_amount, i) > 0.0) {
477         nb++;
478         value = cost_or_zero(communication_amount, i);
479       }
480     }
481     if (nb == 1)
482       return ws_communicate(workstation_list[0], workstation_list[1],value, rate);
483   }
484 #undef cost_or_zero
485
486   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
487   return NULL;
488 }
489
490
491 /* returns an array of network_link_CM02_t */
492 static xbt_dynar_t ws_get_route(void *workstation_src, void *workstation_dst)
493 {
494   XBT_DEBUG("ws_get_route");
495   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
496   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
497   return surf_network_model->extension.
498       network.get_route(src->net_elm,
499                   dst->net_elm);
500 }
501
502 static double ws_get_link_bandwidth(const void *link)
503 {
504   return surf_network_model->extension.network.get_link_bandwidth(link);
505 }
506
507 static double ws_get_link_latency(const void *link)
508 {
509   return surf_network_model->extension.network.get_link_latency(link);
510 }
511
512 static int ws_link_shared(const void *link)
513 {
514   return surf_network_model->extension.network.link_shared(link);
515 }
516
517 static xbt_dict_t ws_get_properties(const void *ws)
518 {
519   return surf_resource_properties(surf_cpu_resource_priv(ws));
520 }
521
522 static storage_t find_storage_on_mount_list(void *workstation,const char* mount)
523 {
524   storage_t st = NULL;
525   s_mount_t mnt;
526   unsigned int cursor;
527   workstation_CLM03_t ws = (workstation_CLM03_t) surf_workstation_resource_priv(workstation);
528   xbt_dynar_t storage_list = ws->storage;
529
530   XBT_DEBUG("Search for storage name '%s' on '%s'",mount,ws->generic_resource.name);
531   xbt_dynar_foreach(storage_list,cursor,mnt)
532   {
533     XBT_DEBUG("See '%s'",mnt.name);
534     if(!strcmp(mount,mnt.name)){
535       st = mnt.storage;
536       break;
537     }
538   }
539   if(!st) xbt_die("Can't find mount '%s' for '%s'",mount,ws->generic_resource.name);
540   return st;
541 }
542
543 static xbt_dict_t ws_get_storage_list(void *workstation)
544 {
545   s_mount_t mnt;
546   unsigned int i;
547   xbt_dict_t storage_list = xbt_dict_new_homogeneous(NULL);
548   char *storage_name = NULL;
549
550   workstation_CLM03_t ws = (workstation_CLM03_t) surf_workstation_resource_priv(workstation);
551   xbt_dynar_t storages = ws->storage;
552
553   xbt_dynar_foreach(storages,i,mnt){
554     storage_name = ((storage_t)mnt.storage)->generic_resource.name;
555     xbt_dict_set(storage_list,mnt.name,storage_name,NULL);
556   }
557   return storage_list;
558 }
559
560 static surf_action_t ws_action_open(void *workstation, const char* mount,
561                                     const char* path)
562 {
563   storage_t st = find_storage_on_mount_list(workstation, mount);
564   XBT_DEBUG("OPEN on disk '%s'",st->generic_resource.name);
565   surf_model_t model = st->generic_resource.model;
566   return model->extension.storage.open(st, mount, path);
567 }
568
569 static surf_action_t ws_action_close(void *workstation, surf_file_t fd)
570 {
571   storage_t st = find_storage_on_mount_list(workstation, fd->mount);
572   XBT_DEBUG("CLOSE on disk '%s'",st->generic_resource.name);
573   surf_model_t model = st->generic_resource.model;
574   return model->extension.storage.close(st, fd);
575 }
576
577 static surf_action_t ws_action_read(void *workstation, surf_file_t fd, sg_storage_size_t size)
578 {
579   storage_t st = find_storage_on_mount_list(workstation, fd->mount);
580   XBT_DEBUG("READ on disk '%s'",st->generic_resource.name);
581   surf_model_t model = st->generic_resource.model;
582   return model->extension.storage.read(st, fd, size);
583 }
584
585 static surf_action_t ws_action_write(void *workstation, surf_file_t fd, sg_storage_size_t size)
586 {
587   storage_t st = find_storage_on_mount_list(workstation, fd->mount);
588   XBT_DEBUG("WRITE on disk '%s'",st->generic_resource.name);
589   surf_model_t model = st->generic_resource.model;
590   return model->extension.storage.write(st, fd, size);
591 }
592
593 static int ws_file_unlink(void *workstation, surf_file_t fd)
594 {
595   if (!fd){
596     XBT_WARN("No such file descriptor. Impossible to unlink");
597     return 0;
598   } else {
599 //    XBT_INFO("%s %zu", fd->storage, fd->size);
600     storage_t st = find_storage_on_mount_list(workstation, fd->mount);
601     xbt_dict_t content_dict = (st)->content;
602     /* Check if the file is on this storage */
603     if (!xbt_dict_get_or_null(content_dict, fd->name)){
604       XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name,
605           st->generic_resource.name);
606       return 0;
607     } else {
608       XBT_DEBUG("UNLINK on disk '%s'",st->generic_resource.name);
609       st->used_size -= fd->size;
610
611       // Remove the file from storage
612       xbt_dict_remove(content_dict,fd->name);
613
614       free(fd->name);
615       free(fd->mount);
616       xbt_free(fd);
617       return 1;
618     }
619   }
620 }
621
622 static surf_action_t ws_action_ls(void *workstation, const char* mount,
623                                   const char *path)
624 {
625   XBT_DEBUG("LS on mount '%s' and file '%s'",mount, path);
626   storage_t st = find_storage_on_mount_list(workstation, mount);
627   surf_model_t model = st->generic_resource.model;
628   return model->extension.storage.ls(st, path);
629 }
630
631 static sg_storage_size_t ws_file_get_size(void *workstation, surf_file_t fd)
632 {
633   return fd->size;
634 }
635
636 static xbt_dynar_t ws_file_get_info(void *workstation, surf_file_t fd)
637 {
638   storage_t st = find_storage_on_mount_list(workstation, fd->mount);
639   sg_storage_size_t *psize = xbt_new(sg_storage_size_t, 1);
640   *psize = fd->size;
641   xbt_dynar_t info = xbt_dynar_new(sizeof(void*), NULL);
642   xbt_dynar_push_as(info, sg_storage_size_t *, psize);
643   xbt_dynar_push_as(info, void *, fd->mount);
644   xbt_dynar_push_as(info, void *, st->generic_resource.name);
645   xbt_dynar_push_as(info, void *, st->type_id);
646   xbt_dynar_push_as(info, void *, st->content_type);
647
648   return info;
649 }
650
651 static sg_storage_size_t ws_storage_get_free_size(void *workstation,const char* name)
652 {
653   storage_t st = find_storage_on_mount_list(workstation, name);
654   return st->size - st->used_size;
655 }
656
657 static sg_storage_size_t ws_storage_get_used_size(void *workstation,const char* name)
658 {
659   storage_t st = find_storage_on_mount_list(workstation, name);
660   return st->used_size;
661 }
662
663 void ws_get_params(void *ws, ws_params_t params)
664 {
665   workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
666   memcpy(params, &ws_clm03->params, sizeof(s_ws_params_t));
667 }
668
669 void ws_set_params(void *ws, ws_params_t params)
670 {
671   workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
672   /* may check something here. */
673   memcpy(&ws_clm03->params, params, sizeof(s_ws_params_t));
674 }
675
676 static xbt_dynar_t ws_get_vms(void *pm)
677 {
678   xbt_dynar_t dyn = xbt_dynar_new(sizeof(smx_host_t), NULL);
679
680   /* iterate for all hosts including virtual machines */
681   xbt_lib_cursor_t cursor;
682   char *key;
683   void **ind_host;
684   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
685     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
686     if (!ws_clm03)
687       continue;
688     /* skip if it is not a virtual machine */
689     if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
690       continue;
691
692     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
693     workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
694     if (pm == ws_vm2013->sub_ws)
695       xbt_dynar_push(dyn, &ws_vm2013->sub_ws);
696   }
697
698   return dyn;
699 }
700
701
702 static void surf_workstation_model_init_internal(void)
703 {
704   surf_model_t model = surf_model_init();
705
706   model->name = "Workstation";
707   model->type = SURF_MODEL_TYPE_WORKSTATION;
708   model->action_unref     = ws_action_unref;
709   model->action_cancel    = ws_action_cancel;
710   model->action_state_set = ws_action_state_set;
711
712   model->model_private->resource_used         = ws_resource_used;
713   model->model_private->share_resources       = ws_share_resources;
714   model->model_private->update_actions_state  = ws_update_actions_state;
715   model->model_private->update_resource_state = ws_update_resource_state;
716   model->model_private->finalize              = ws_finalize;
717
718   model->suspend          = ws_action_suspend;
719   model->resume           = ws_action_resume;
720   model->is_suspended     = ws_action_is_suspended;
721   model->set_max_duration = ws_action_set_max_duration;
722   model->set_priority     = ws_action_set_priority;
723   model->set_bound        = ws_action_set_bound;
724   model->set_affinity     = ws_action_set_affinity;
725   #ifdef HAVE_TRACING
726   model->set_category     = ws_action_set_category;
727   #endif
728   model->get_remains      = ws_action_get_remains;
729   #ifdef HAVE_LATENCY_BOUND_TRACKING
730   model->get_latency_limited = ws_get_latency_limited;
731   #endif
732
733   /* For VM support, we have a surf cpu model object for each workstation model
734    * object. The physical workstation model object has the cpu model object of
735    * the physical machine layer. */
736   xbt_assert(surf_cpu_model_pm);
737   model->extension.workstation.cpu_model = surf_cpu_model_pm;
738
739   model->extension.workstation.execute   = ws_execute;
740   model->extension.workstation.sleep     = ws_action_sleep;
741   model->extension.workstation.get_state = ws_get_state;
742   model->extension.workstation.set_state = ws_set_state;
743   model->extension.workstation.get_core  = ws_get_core;
744   model->extension.workstation.get_speed = ws_get_speed;
745   model->extension.workstation.get_available_speed =
746       ws_get_available_speed;
747   model->extension.workstation.get_current_power_peak = ws_get_current_power_peak;
748   model->extension.workstation.get_power_peak_at = ws_get_power_peak_at;
749   model->extension.workstation.get_nb_pstates = ws_get_nb_pstates;
750   model->extension.workstation.set_power_peak_at = ws_set_power_peak_at;
751   model->extension.workstation.get_consumed_energy = ws_get_consumed_energy;
752
753   model->extension.workstation.communicate = ws_communicate;
754   model->extension.workstation.get_route = ws_get_route;
755   model->extension.workstation.execute_parallel_task = ws_execute_parallel_task;
756   model->extension.workstation.get_link_bandwidth = ws_get_link_bandwidth;
757   model->extension.workstation.get_link_latency = ws_get_link_latency;
758   model->extension.workstation.link_shared = ws_link_shared;
759   model->extension.workstation.get_properties = ws_get_properties;
760
761   model->extension.workstation.open = ws_action_open;
762   model->extension.workstation.close = ws_action_close;
763   model->extension.workstation.read = ws_action_read;
764   model->extension.workstation.write = ws_action_write;
765   model->extension.workstation.unlink = ws_file_unlink;
766   model->extension.workstation.ls = ws_action_ls;
767   model->extension.workstation.get_size = ws_file_get_size;
768   model->extension.workstation.get_info = ws_file_get_info;
769   model->extension.workstation.get_free_size = ws_storage_get_free_size;
770   model->extension.workstation.get_used_size = ws_storage_get_used_size;
771   model->extension.workstation.get_storage_list = ws_get_storage_list;
772
773   model->extension.workstation.get_params = ws_get_params;
774   model->extension.workstation.set_params = ws_set_params;
775   model->extension.workstation.get_vms    = ws_get_vms;
776
777   surf_workstation_model = model;
778 }
779
780 void surf_workstation_model_init_current_default(void)
781 {
782   xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", "yes");
783   surf_cpu_model_init_Cas01();
784   surf_network_model_init_LegrandVelho();
785
786   /* surf_cpu_mode_pm and surf_network_model must be initialized in advance. */
787   xbt_assert(surf_cpu_model_pm);
788   xbt_assert(surf_network_model);
789   surf_workstation_model_init_internal();
790
791   xbt_dynar_push(model_list, &surf_workstation_model);
792   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
793   sg_platf_host_add_cb(workstation_new);
794 }
795
796 void surf_workstation_model_init_compound()
797 {
798   xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
799   xbt_assert(surf_network_model, "No network model defined yet!");
800
801   surf_workstation_model_init_internal();
802   xbt_dynar_push(model_list, &surf_workstation_model);
803   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
804   sg_platf_host_add_cb(workstation_new);
805 }