Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
store the VMs by their interface, not by their implementation
[simgrid.git] / src / surf / HostImpl.cpp
1 /* Copyright (c) 2013-2016. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include <simgrid/s4u/host.hpp>
7
8 #include "src/simix/smx_private.h"
9 #include "cpu_cas01.hpp"
10 #include "src/surf/HostImpl.hpp"
11 #include "simgrid/sg_config.h"
12
13 #include "network_interface.hpp"
14 #include "src/plugins/vm/VirtualMachineImpl.hpp"
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_host, surf, "Logging specific to the SURF host module");
17
18 simgrid::surf::HostModel *surf_host_model = nullptr;
19
20 /*************
21  * Callbacks *
22  *************/
23
24 namespace simgrid {
25 namespace surf {
26
27 /*********
28  * Model *
29  *********/
30
31 /* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
32  * constraint (capacity) of the VM in the PM layer. If the VM does not have any
33  * active task, the dummy CPU action must be deactivated, so that the VM does
34  * not get any CPU share in the PM layer. */
35 void HostModel::adjustWeightOfDummyCpuActions()
36 {
37   /* iterate for all virtual machines */
38   for (s4u::VirtualMachine* ws_vm : VirtualMachineImpl::allVms_) {
39
40     Cpu* cpu = ws_vm->pimpl_cpu;
41
42     int is_active = lmm_constraint_used(cpu->getModel()->getMaxminSystem(), cpu->getConstraint());
43
44     if (is_active) {
45       /* some tasks exist on this VM */
46       XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
47
48       /* FIXME: we should use lmm_update_variable_weight() ? */
49       /* FIXME: If we assign 1.05 and 0.05, the system makes apparently wrong values. */
50       ws_vm->pimpl_vm_->action_->setPriority(1);
51
52     } else {
53       /* no task exits on this VM */
54       XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
55
56       ws_vm->pimpl_vm_->action_->setPriority(0);
57     }
58   }
59 }
60
61 Action* HostModel::executeParallelTask(int host_nb, simgrid::s4u::Host** host_list, double* flops_amount,
62                                        double* bytes_amount, double rate)
63 {
64 #define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0)
65   Action* action = nullptr;
66   if ((host_nb == 1) && (cost_or_zero(bytes_amount, 0) == 0.0)) {
67     action = host_list[0]->pimpl_cpu->execution_start(flops_amount[0]);
68   } else if ((host_nb == 1) && (cost_or_zero(flops_amount, 0) == 0.0)) {
69     action = surf_network_model->communicate(host_list[0], host_list[0], bytes_amount[0], rate);
70   } else if ((host_nb == 2) && (cost_or_zero(flops_amount, 0) == 0.0) && (cost_or_zero(flops_amount, 1) == 0.0)) {
71     int i, nb = 0;
72     double value = 0.0;
73
74     for (i = 0; i < host_nb * host_nb; i++) {
75       if (cost_or_zero(bytes_amount, i) > 0.0) {
76         nb++;
77         value = cost_or_zero(bytes_amount, i);
78       }
79     }
80     if (nb == 1) {
81       action = surf_network_model->communicate(host_list[0], host_list[1], value, rate);
82     } else if (nb == 0) {
83       xbt_die("Cannot have a communication with no flop to exchange in this model. You should consider using the "
84               "ptask model");
85     } else {
86       xbt_die("Cannot have a communication that is not a simple point-to-point in this model. You should consider "
87               "using the ptask model");
88     }
89   } else
90     xbt_die("This model only accepts one of the following. You should consider using the ptask model for the other "
91             "cases.\n - execution with one host only and no communication\n - Self-comms with one host only\n - "
92             "Communications with two hosts and no computation");
93 #undef cost_or_zero
94   xbt_free(host_list);
95   return action;
96 }
97
98 /************
99  * Resource *
100  ************/
101 HostImpl::HostImpl(s4u::Host* host, xbt_dynar_t storage) : storage_(storage), piface_(host)
102 {
103   piface_->pimpl_ = this;
104 }
105
106 /** @brief use destroy() instead of this destructor */
107 HostImpl::~HostImpl() = default;
108
109 simgrid::surf::Storage* HostImpl::findStorageOnMountList(const char* mount)
110 {
111   simgrid::surf::Storage* st = nullptr;
112   s_mount_t mnt;
113   unsigned int cursor;
114
115   XBT_DEBUG("Search for storage name '%s' on '%s'", mount, piface_->name().c_str());
116   xbt_dynar_foreach (storage_, cursor, mnt) {
117     XBT_DEBUG("See '%s'", mnt.name);
118     if (!strcmp(mount, mnt.name)) {
119       st = static_cast<simgrid::surf::Storage*>(mnt.storage);
120       break;
121     }
122   }
123   if (!st)
124     xbt_die("Can't find mount '%s' for '%s'", mount, piface_->name().c_str());
125   return st;
126 }
127
128 xbt_dict_t HostImpl::getMountedStorageList()
129 {
130   s_mount_t mnt;
131   unsigned int i;
132   xbt_dict_t storage_list = xbt_dict_new_homogeneous(nullptr);
133   char* storage_name      = nullptr;
134
135   xbt_dynar_foreach (storage_, i, mnt) {
136     storage_name = (char*)static_cast<simgrid::surf::Storage*>(mnt.storage)->getName();
137     xbt_dict_set(storage_list, mnt.name, storage_name, nullptr);
138   }
139   return storage_list;
140 }
141
142 xbt_dynar_t HostImpl::getAttachedStorageList()
143 {
144   xbt_lib_cursor_t cursor;
145   char* key;
146   void** data;
147   xbt_dynar_t result = xbt_dynar_new(sizeof(void*), nullptr);
148   xbt_lib_foreach(storage_lib, cursor, key, data)
149   {
150     if (xbt_lib_get_level(xbt_lib_get_elm_or_null(storage_lib, key), SURF_STORAGE_LEVEL) != nullptr) {
151       simgrid::surf::Storage* storage = static_cast<simgrid::surf::Storage*>(
152           xbt_lib_get_level(xbt_lib_get_elm_or_null(storage_lib, key), SURF_STORAGE_LEVEL));
153       if (!strcmp((const char*)storage->attach_, piface_->name().c_str())) {
154         xbt_dynar_push_as(result, void*, (void*)storage->getName());
155       }
156     }
157   }
158   return result;
159     }
160
161     Action* HostImpl::open(const char* fullpath)
162     {
163
164       simgrid::surf::Storage* st = nullptr;
165       s_mount_t mnt;
166       unsigned int cursor;
167       size_t longest_prefix_length = 0;
168       char* path                   = nullptr;
169       char* file_mount_name        = nullptr;
170       char* mount_name             = nullptr;
171
172       XBT_DEBUG("Search for storage name for '%s' on '%s'", fullpath, piface_->name().c_str());
173       xbt_dynar_foreach (storage_, cursor, mnt) {
174         XBT_DEBUG("See '%s'", mnt.name);
175         file_mount_name = (char*)xbt_malloc((strlen(mnt.name) + 1));
176         strncpy(file_mount_name, fullpath, strlen(mnt.name) + 1);
177         file_mount_name[strlen(mnt.name)] = '\0';
178
179         if (!strcmp(file_mount_name, mnt.name) &&
180             strlen(mnt.name) > longest_prefix_length) { /* The current mount name is found in the full path and is
181                                                            bigger than the previous*/
182           longest_prefix_length = strlen(mnt.name);
183           st                    = static_cast<simgrid::surf::Storage*>(mnt.storage);
184         }
185         free(file_mount_name);
186       }
187       if (longest_prefix_length > 0) { /* Mount point found, split fullpath into mount_name and path+filename*/
188         path       = (char*)xbt_malloc((strlen(fullpath) - longest_prefix_length + 1));
189         mount_name = (char*)xbt_malloc((longest_prefix_length + 1));
190         strncpy(mount_name, fullpath, longest_prefix_length + 1);
191         strncpy(path, fullpath + longest_prefix_length, strlen(fullpath) - longest_prefix_length + 1);
192         path[strlen(fullpath) - longest_prefix_length] = '\0';
193         mount_name[longest_prefix_length]              = '\0';
194       } else
195         xbt_die("Can't find mount point for '%s' on '%s'", fullpath, piface_->name().c_str());
196
197       XBT_DEBUG("OPEN %s on disk '%s'", path, st->getName());
198       Action* action = st->open((const char*)mount_name, (const char*)path);
199       free((char*)path);
200       free((char*)mount_name);
201       return action;
202     }
203
204     Action* HostImpl::close(surf_file_t fd)
205     {
206       simgrid::surf::Storage* st = findStorageOnMountList(fd->mount);
207       XBT_DEBUG("CLOSE %s on disk '%s'", fd->name, st->getName());
208       return st->close(fd);
209     }
210
211     Action* HostImpl::read(surf_file_t fd, sg_size_t size)
212     {
213       simgrid::surf::Storage* st = findStorageOnMountList(fd->mount);
214       XBT_DEBUG("READ %s on disk '%s'", fd->name, st->getName());
215       return st->read(fd, size);
216     }
217
218     Action* HostImpl::write(surf_file_t fd, sg_size_t size)
219     {
220       simgrid::surf::Storage* st = findStorageOnMountList(fd->mount);
221       XBT_DEBUG("WRITE %s on disk '%s'", fd->name, st->getName());
222       return st->write(fd, size);
223     }
224
225     int HostImpl::unlink(surf_file_t fd)
226     {
227       if (!fd) {
228         XBT_WARN("No such file descriptor. Impossible to unlink");
229         return -1;
230       } else {
231
232         simgrid::surf::Storage* st = findStorageOnMountList(fd->mount);
233         /* Check if the file is on this storage */
234         if (!xbt_dict_get_or_null(st->content_, fd->name)) {
235           XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name, st->getName());
236           return -1;
237         } else {
238           XBT_DEBUG("UNLINK %s on disk '%s'", fd->name, st->getName());
239           st->usedSize_ -= fd->size;
240
241           // Remove the file from storage
242           xbt_dict_remove(st->content_, fd->name);
243
244           xbt_free(fd->name);
245           xbt_free(fd->mount);
246           xbt_free(fd);
247           return 0;
248         }
249       }
250     }
251
252     sg_size_t HostImpl::getSize(surf_file_t fd)
253     {
254       return fd->size;
255     }
256
257     xbt_dynar_t HostImpl::getInfo(surf_file_t fd)
258     {
259       simgrid::surf::Storage* st = findStorageOnMountList(fd->mount);
260       sg_size_t* psize           = xbt_new(sg_size_t, 1);
261       *psize                     = fd->size;
262       xbt_dynar_t info           = xbt_dynar_new(sizeof(void*), nullptr);
263       xbt_dynar_push_as(info, sg_size_t*, psize);
264       xbt_dynar_push_as(info, void*, fd->mount);
265       xbt_dynar_push_as(info, void*, (void*)st->getName());
266       xbt_dynar_push_as(info, void*, st->typeId_);
267       xbt_dynar_push_as(info, void*, st->contentType_);
268
269       return info;
270     }
271
272     sg_size_t HostImpl::fileTell(surf_file_t fd)
273     {
274       return fd->current_position;
275     }
276
277     int HostImpl::fileSeek(surf_file_t fd, sg_offset_t offset, int origin)
278     {
279
280       switch (origin) {
281         case SEEK_SET:
282           fd->current_position = offset;
283           return 0;
284         case SEEK_CUR:
285           fd->current_position += offset;
286           return 0;
287         case SEEK_END:
288           fd->current_position = fd->size + offset;
289           return 0;
290         default:
291           return -1;
292       }
293     }
294
295     int HostImpl::fileMove(surf_file_t fd, const char* fullpath)
296     {
297       /* Check if the new full path is on the same mount point */
298       if (!strncmp((const char*)fd->mount, fullpath, strlen(fd->mount))) {
299         sg_size_t *psize, *new_psize;
300         psize      = (sg_size_t*)xbt_dict_get_or_null(findStorageOnMountList(fd->mount)->content_, fd->name);
301         new_psize  = xbt_new(sg_size_t, 1);
302         *new_psize = *psize;
303         if (psize) { // src file exists
304           xbt_dict_remove(findStorageOnMountList(fd->mount)->content_, fd->name);
305           char* path = (char*)xbt_malloc((strlen(fullpath) - strlen(fd->mount) + 1));
306           strncpy(path, fullpath + strlen(fd->mount), strlen(fullpath) - strlen(fd->mount) + 1);
307           xbt_dict_set(findStorageOnMountList(fd->mount)->content_, path, new_psize, nullptr);
308           XBT_DEBUG("Move file from %s to %s, size '%llu'", fd->name, fullpath, *psize);
309           free(path);
310           return 0;
311         } else {
312           XBT_WARN("File %s doesn't exist", fd->name);
313           return -1;
314         }
315       } else {
316         XBT_WARN("New full path %s is not on the same mount point: %s. Action has been canceled.", fullpath, fd->mount);
317         return -1;
318       }
319     }
320
321     }
322     }