Logo AND Algorithmique Numérique Distribuée

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