Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ea90f8b98b2e9194df389cda57e275b99320197b
[simgrid.git] / src / surf / workstation.cpp
1 #include "workstation.hpp"
2 #include "vm_workstation.hpp"
3 #include "cpu_cas01.hpp"
4 #include "simgrid/sg_config.h"
5
6 extern "C" {
7 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_workstation, surf,
8                                 "Logging specific to the SURF workstation module");
9 }
10
11 WorkstationModelPtr surf_workstation_model = NULL;
12
13 /*************
14  * CallBacks *
15  *************/
16
17 static void workstation_new(sg_platf_host_cbarg_t host){
18   surf_workstation_model->createResource(host->id);
19 }
20
21 /*********
22  * Model *
23  *********/
24
25 void surf_workstation_model_init_current_default(void)
26 {
27   surf_workstation_model = new WorkstationModel();
28   xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", "yes");
29   surf_cpu_model_init_Cas01();
30   surf_network_model_init_LegrandVelho();
31   surf_workstation_model->p_cpuModel = surf_cpu_model_pm;
32
33   ModelPtr model = static_cast<ModelPtr>(surf_workstation_model);
34   xbt_dynar_push(model_list, &model);
35   xbt_dynar_push(model_list_invoke, &model);
36   sg_platf_host_add_cb(workstation_new);
37 }
38
39 void surf_workstation_model_init_compound()
40 {
41
42   xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
43   xbt_assert(surf_network_model, "No network model defined yet!");
44   surf_workstation_model = new WorkstationModel();
45
46   ModelPtr model = static_cast<ModelPtr>(surf_workstation_model);
47   xbt_dynar_push(model_list, &model);
48   xbt_dynar_push(model_list_invoke, &model);
49   sg_platf_host_add_cb(workstation_new);
50 }
51
52 WorkstationModel::WorkstationModel() : Model("Workstation") {
53   p_cpuModel = surf_cpu_model_pm;
54 }
55
56 WorkstationModel::~WorkstationModel() {
57 }
58
59 void WorkstationModel::parseInit(sg_platf_host_cbarg_t host){
60   createResource(host->id);
61 }
62
63 WorkstationCLM03Ptr WorkstationModel::createResource(string name){
64
65   WorkstationCLM03Ptr workstation = new WorkstationCLM03(surf_workstation_model, name.c_str(), NULL,
66                   (xbt_dynar_t)xbt_lib_get_or_null(storage_lib, name.c_str(), ROUTING_STORAGE_HOST_LEVEL),
67                   (RoutingEdgePtr)xbt_lib_get_or_null(host_lib, name.c_str(), ROUTING_HOST_LEVEL),
68                   dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(xbt_lib_get_or_null(host_lib, name.c_str(), SURF_CPU_LEVEL))));
69   XBT_DEBUG("Create workstation %s with %ld mounted disks", name.c_str(), xbt_dynar_length(workstation->p_storage));
70   xbt_lib_set(host_lib, name.c_str(), SURF_WKS_LEVEL, static_cast<ResourcePtr>(workstation));
71   return workstation;
72 }
73
74 /* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
75  * constraint (capacity) of the VM in the PM layer. If the VM does not have any
76  * active task, the dummy CPU action must be deactivated, so that the VM does
77  * not get any CPU share in the PM layer. */
78 void WorkstationModel::adjustWeightOfDummyCpuActions()
79 {
80   /* iterate for all hosts including virtual machines */
81   xbt_lib_cursor_t cursor;
82   char *key;
83   void **ind_host;
84
85   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
86     WorkstationCLM03Ptr ws_clm03 = dynamic_cast<WorkstationCLM03Ptr>(
87                                        static_cast<ResourcePtr>(ind_host[SURF_WKS_LEVEL]));
88     CpuCas01LmmPtr cpu_cas01 = dynamic_cast<CpuCas01LmmPtr>(
89                                static_cast<ResourcePtr>(ind_host[SURF_CPU_LEVEL]));
90
91     if (!ws_clm03)
92       continue;
93     /* skip if it is not a virtual machine */
94     if (ws_clm03->p_model != static_cast<ModelPtr>(surf_vm_workstation_model))
95       continue;
96     xbt_assert(cpu_cas01, "cpu-less workstation");
97
98     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
99     WorkstationVM2013Ptr ws_vm2013 = dynamic_cast<WorkstationVM2013Ptr>(ws_clm03);
100
101     int is_active = lmm_constraint_used(cpu_cas01->p_model->p_maxminSystem, cpu_cas01->p_constraint);
102     // int is_active_old = constraint_is_active(cpu_cas01);
103
104     // {
105     //   xbt_assert(is_active == is_active_old, "%d %d", is_active, is_active_old);
106     // }
107
108     if (is_active) {
109       /* some tasks exist on this VM */
110       XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
111
112       /* FIXME: we shoud use lmm_update_variable_weight() ? */
113       /* FIXME: If we assgign 1.05 and 0.05, the system makes apparently wrong values. */
114       surf_action_set_priority(ws_vm2013->p_action, 1);
115
116     } else {
117       /* no task exits on this VM */
118       XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
119
120       surf_action_set_priority(ws_vm2013->p_action, 0);
121     }
122   }
123 }
124
125 double WorkstationModel::shareResources(double now){
126   adjustWeightOfDummyCpuActions();
127
128   double min_by_cpu = p_cpuModel->shareResources(now);
129   double min_by_net = surf_network_model->shareResources(now);
130   double min_by_sto = -1;
131   if (p_cpuModel == surf_cpu_model_pm)
132         min_by_sto = surf_storage_model->shareResources(now);
133
134   XBT_DEBUG("model %p, %s min_by_cpu %f, %s min_by_net %f, %s min_by_sto %f",
135       this, surf_cpu_model_pm->m_name.c_str(), min_by_cpu,
136             surf_network_model->m_name.c_str(), min_by_net,
137             surf_storage_model->m_name.c_str(), min_by_sto);
138
139   double res = max(max(min_by_cpu, min_by_net), min_by_sto);
140   if (min_by_cpu >= 0.0 && min_by_cpu < res)
141         res = min_by_cpu;
142   if (min_by_net >= 0.0 && min_by_net < res)
143         res = min_by_net;
144   if (min_by_sto >= 0.0 && min_by_sto < res)
145         res = min_by_sto;
146   return res;
147 }
148
149 void WorkstationModel::updateActionsState(double /*now*/, double /*delta*/){
150   return;
151 }
152
153 ActionPtr WorkstationModel::executeParallelTask(int workstation_nb,
154                                         void **workstation_list,
155                                         double *computation_amount,
156                                         double *communication_amount,
157                                         double rate){
158 #define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0)
159   if ((workstation_nb == 1)
160       && (cost_or_zero(communication_amount, 0) == 0.0))
161     return ((WorkstationCLM03Ptr)workstation_list[0])->execute(computation_amount[0]);
162   else if ((workstation_nb == 1)
163            && (cost_or_zero(computation_amount, 0) == 0.0))
164     return communicate((WorkstationCLM03Ptr)workstation_list[0], (WorkstationCLM03Ptr)workstation_list[0],communication_amount[0], rate);
165   else if ((workstation_nb == 2)
166              && (cost_or_zero(computation_amount, 0) == 0.0)
167              && (cost_or_zero(computation_amount, 1) == 0.0)) {
168     int i,nb = 0;
169     double value = 0.0;
170
171     for (i = 0; i < workstation_nb * workstation_nb; i++) {
172       if (cost_or_zero(communication_amount, i) > 0.0) {
173         nb++;
174         value = cost_or_zero(communication_amount, i);
175       }
176     }
177     if (nb == 1)
178       return communicate((WorkstationCLM03Ptr)workstation_list[0], (WorkstationCLM03Ptr)workstation_list[1],value, rate);
179   }
180 #undef cost_or_zero
181
182   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
183   return NULL;
184 }
185
186 /* returns an array of network_link_CM02_t */
187 xbt_dynar_t WorkstationModel::getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst)
188 {
189   XBT_DEBUG("ws_get_route");
190   return surf_network_model->getRoute(src->p_netElm, dst->p_netElm);
191 }
192
193 ActionPtr WorkstationModel::communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, double size, double rate){
194   return surf_network_model->communicate(src->p_netElm, dst->p_netElm, size, rate);
195 }
196
197
198
199 /************
200  * Resource *
201  ************/
202 WorkstationCLM03::WorkstationCLM03(WorkstationModelPtr model, const char* name, xbt_dict_t properties, xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu)
203   : Resource(model, name, properties), p_storage(storage), p_netElm(netElm), p_cpu(cpu) {}
204
205 bool WorkstationCLM03::isUsed(){
206   THROW_IMPOSSIBLE;             /* This model does not implement parallel tasks */
207   return -1;
208 }
209
210 void WorkstationCLM03::updateState(tmgr_trace_event_t /*event_type*/, double /*value*/, double /*date*/){
211   THROW_IMPOSSIBLE;             /* This model does not implement parallel tasks */
212 }
213
214 ActionPtr WorkstationCLM03::execute(double size) {
215   return p_cpu->execute(size);
216 }
217
218 ActionPtr WorkstationCLM03::sleep(double duration) {
219   return p_cpu->sleep(duration);
220 }
221
222 e_surf_resource_state_t WorkstationCLM03::getState() {
223   return p_cpu->getState();
224 }
225
226 int WorkstationCLM03::getCore(){
227   return p_cpu->getCore();
228 }
229
230 double WorkstationCLM03::getSpeed(double load){
231   return p_cpu->getSpeed(load);
232 }
233
234 double WorkstationCLM03::getAvailableSpeed(){
235   return p_cpu->getAvailableSpeed();
236 }
237
238 double WorkstationCLM03::getCurrentPowerPeak()
239 {
240   return p_cpu->getCurrentPowerPeak();
241 }
242
243 double WorkstationCLM03::getPowerPeakAt(int pstate_index)
244 {
245   return p_cpu->getPowerPeakAt(pstate_index);
246 }
247
248 int WorkstationCLM03::getNbPstates()
249 {
250   return p_cpu->getNbPstates();
251 }
252
253 void WorkstationCLM03::setPowerPeakAt(int pstate_index)
254 {
255         p_cpu->setPowerPeakAt(pstate_index);
256 }
257
258 double WorkstationCLM03::getConsumedEnergy()
259 {
260   return p_cpu->getConsumedEnergy();
261 }
262
263
264 xbt_dict_t WorkstationCLM03::getProperties()
265 {
266   return p_cpu->m_properties;
267 }
268
269
270 StoragePtr WorkstationCLM03::findStorageOnMountList(const char* mount)
271 {
272   StoragePtr st = NULL;
273   s_mount_t mnt;
274   unsigned int cursor;
275
276   XBT_DEBUG("Search for storage name '%s' on '%s'", mount, m_name);
277   xbt_dynar_foreach(p_storage,cursor,mnt)
278   {
279     XBT_DEBUG("See '%s'",mnt.name);
280     if(!strcmp(mount,mnt.name)){
281       st = dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(mnt.storage));
282       break;
283     }
284   }
285   if(!st) xbt_die("Can't find mount '%s' for '%s'", mount, m_name);
286   return st;
287 }
288
289 xbt_dict_t WorkstationCLM03::getStorageList()
290 {
291   s_mount_t mnt;
292   unsigned int i;
293   xbt_dict_t storage_list = xbt_dict_new_homogeneous(NULL);
294   char *storage_name = NULL;
295
296   xbt_dynar_foreach(p_storage,i,mnt){
297     storage_name = (char *)dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(mnt.storage))->m_name;
298     xbt_dict_set(storage_list,mnt.name,storage_name,NULL);
299   }
300   return storage_list;
301 }
302
303 ActionPtr WorkstationCLM03::open(const char* mount, const char* path) {
304   StoragePtr st = findStorageOnMountList(mount);
305   XBT_DEBUG("OPEN on disk '%s'", st->m_name);
306   return st->open(mount, path);
307 }
308
309 ActionPtr WorkstationCLM03::close(surf_file_t fd) {
310   StoragePtr st = findStorageOnMountList(fd->mount);
311   XBT_DEBUG("CLOSE on disk '%s'",st->m_name);
312   return st->close(fd);
313 }
314
315 ActionPtr WorkstationCLM03::read(surf_file_t fd, sg_size_t size) {
316   StoragePtr st = findStorageOnMountList(fd->mount);
317   XBT_DEBUG("READ on disk '%s'",st->m_name);
318   return st->read(fd, size);
319 }
320
321 ActionPtr WorkstationCLM03::write(surf_file_t fd, sg_size_t size) {
322   StoragePtr st = findStorageOnMountList(fd->mount);
323   XBT_DEBUG("WRITE on disk '%s'",st->m_name);
324   return st->write(fd, size);
325 }
326
327 int WorkstationCLM03::unlink(surf_file_t fd) {
328   if (!fd){
329     XBT_WARN("No such file descriptor. Impossible to unlink");
330     return 0;
331   } else {
332 //    XBT_INFO("%s %zu", fd->storage, fd->size);
333     StoragePtr st = findStorageOnMountList(fd->mount);
334     /* Check if the file is on this storage */
335     if (!xbt_dict_get_or_null(st->p_content, fd->name)){
336       XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name,
337           st->m_name);
338       return 0;
339     } else {
340       XBT_DEBUG("UNLINK on disk '%s'",st->m_name);
341       st->m_usedSize -= fd->size;
342
343       // Remove the file from storage
344       xbt_dict_remove(st->p_content, fd->name);
345
346       free(fd->name);
347       free(fd->mount);
348       xbt_free(fd);
349       return 1;
350     }
351   }
352 }
353
354 ActionPtr WorkstationCLM03::ls(const char* mount, const char *path){
355   XBT_DEBUG("LS on mount '%s' and file '%s'", mount, path);
356   StoragePtr st = findStorageOnMountList(mount);
357   return st->ls(path);
358 }
359
360 sg_size_t WorkstationCLM03::getSize(surf_file_t fd){
361   return fd->size;
362 }
363
364 xbt_dynar_t WorkstationCLM03::getInfo( surf_file_t fd)
365 {
366   StoragePtr st = findStorageOnMountList(fd->mount);
367   sg_size_t *psize = xbt_new(sg_size_t, 1);
368   *psize = fd->size;
369   xbt_dynar_t info = xbt_dynar_new(sizeof(void*), NULL);
370   xbt_dynar_push_as(info, sg_size_t *, psize);
371   xbt_dynar_push_as(info, void *, fd->mount);
372   xbt_dynar_push_as(info, void *, (void *)st->m_name);
373   xbt_dynar_push_as(info, void *, st->p_typeId);
374   xbt_dynar_push_as(info, void *, st->p_contentType);
375
376   return info;
377 }
378
379 sg_size_t WorkstationCLM03::getFreeSize(const char* name)
380 {
381   StoragePtr st = findStorageOnMountList(name);
382   return st->m_size - st->m_usedSize;
383 }
384
385 sg_size_t WorkstationCLM03::getUsedSize(const char* name)
386 {
387   StoragePtr st = findStorageOnMountList(name);
388   return st->m_usedSize;
389 }
390
391 e_surf_resource_state_t WorkstationCLM03Lmm::getState() {
392   return WorkstationCLM03::getState();
393 }
394
395 xbt_dynar_t WorkstationCLM03::getVms()
396 {
397   xbt_dynar_t dyn = xbt_dynar_new(sizeof(smx_host_t), NULL);
398
399   /* iterate for all hosts including virtual machines */
400   xbt_lib_cursor_t cursor;
401   char *key;
402   void **ind_host;
403   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
404     WorkstationCLM03Ptr ws_clm03 = dynamic_cast<WorkstationCLM03Ptr>(static_cast<ResourcePtr>(ind_host[SURF_WKS_LEVEL]));
405     if (!ws_clm03)
406       continue;
407     /* skip if it is not a virtual machine */
408     if (ws_clm03->p_model != static_cast<ModelPtr>(surf_vm_workstation_model))
409       continue;
410
411     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
412     WorkstationVM2013Ptr ws_vm2013 = dynamic_cast<WorkstationVM2013Ptr>(ws_clm03);
413     if (this == ws_vm2013-> p_subWs)
414       xbt_dynar_push(dyn, &ws_vm2013->p_subWs);
415   }
416
417   return dyn;
418 }
419
420 void WorkstationCLM03::getParams(ws_params_t params)
421 {
422   memcpy(params, &p_params, sizeof(s_ws_params_t));
423 }
424
425 void WorkstationCLM03::setParams(ws_params_t params)
426 {
427   /* may check something here. */
428   memcpy(&p_params, params, sizeof(s_ws_params_t));
429 }
430 /**********
431  * Action *
432  **********/