Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
[simgrid.git] / src / surf / host_interface.cpp
1 /* Copyright (c) 2013-2014. 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 "host_interface.hpp"
8
9 #include "simix/smx_private.h"
10 #include "cpu_cas01.hpp"
11 #include "simgrid/sg_config.h"
12
13 #include "network_interface.hpp"
14 #include "vm_interface.hpp"
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_host, surf,
17                                 "Logging specific to the SURF host module");
18
19 HostModelPtr surf_host_model = NULL;
20
21 /*************
22  * Callbacks *
23  *************/
24
25 surf_callback(void, HostPtr) hostCreatedCallbacks;
26 surf_callback(void, HostPtr) hostDestructedCallbacks;
27 surf_callback(void, HostPtr, e_surf_resource_state_t, e_surf_resource_state_t) hostStateChangedCallbacks;
28 surf_callback(void, HostActionPtr, e_surf_action_state_t, e_surf_action_state_t) hostActionStateChangedCallbacks;
29
30 void host_parse_init(sg_platf_host_cbarg_t host)
31 {
32   surf_host_model->createHost(host->id);
33 }
34
35 void host_add_traces(){
36   surf_host_model->addTraces();
37 }
38
39 /*********
40  * Model *
41  *********/
42 HostModel::HostModel(const char *name)
43  : Model(name)
44 {
45   p_cpuModel = surf_cpu_model_pm;
46 }
47
48 HostModel::HostModel()
49 : Model("Host") {
50   p_cpuModel = surf_cpu_model_pm;
51 }
52
53 HostModel::~HostModel() {
54 }
55
56 /* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
57  * constraint (capacity) of the VM in the PM layer. If the VM does not have any
58  * active task, the dummy CPU action must be deactivated, so that the VM does
59  * not get any CPU share in the PM layer. */
60 void HostModel::adjustWeightOfDummyCpuActions()
61 {
62   /* iterate for all virtual machines */
63   for (VMModel::vm_list_t::iterator iter =
64          VMModel::ws_vms.begin();
65        iter !=  VMModel::ws_vms.end(); ++iter) {
66
67     VMPtr ws_vm = &*iter;
68     CpuCas01Ptr cpu_cas01 = static_cast<CpuCas01Ptr>(ws_vm->p_cpu);
69     xbt_assert(cpu_cas01, "cpu-less host");
70
71     int is_active = lmm_constraint_used(cpu_cas01->getModel()->getMaxminSystem(), cpu_cas01->getConstraint());
72     // int is_active_old = constraint_is_active(cpu_cas01);
73
74     // {
75     //   xbt_assert(is_active == is_active_old, "%d %d", is_active, is_active_old);
76     // }
77
78     if (is_active) {
79       /* some tasks exist on this VM */
80       XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
81
82       /* FIXME: we shoud use lmm_update_variable_weight() ? */
83       /* FIXME: If we assgign 1.05 and 0.05, the system makes apparently wrong values. */
84       ws_vm->p_action->setPriority(1);
85
86     } else {
87       /* no task exits on this VM */
88       XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
89
90       ws_vm->p_action->setPriority(0);
91     }
92   }
93 }
94
95 /************
96  * Resource *
97  ************/
98 Host::Host()
99 {
100   surf_callback_emit(hostCreatedCallbacks, this);
101 }
102
103 Host::Host(ModelPtr model, const char *name, xbt_dict_t props,
104                                  xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu)
105  : Resource(model, name, props)
106  , p_storage(storage), p_netElm(netElm), p_cpu(cpu)
107 {
108   p_params.ramsize = 0;
109   surf_callback_emit(hostCreatedCallbacks, this);
110 }
111
112 Host::Host(ModelPtr model, const char *name, xbt_dict_t props, lmm_constraint_t constraint,
113                                          xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu)
114  : Resource(model, name, props, constraint)
115  , p_storage(storage), p_netElm(netElm), p_cpu(cpu)
116 {
117   p_params.ramsize = 0;
118   surf_callback_emit(hostCreatedCallbacks, this);
119 }
120
121 Host::~Host(){
122   surf_callback_emit(hostDestructedCallbacks, this);
123 }
124
125 void Host::setState(e_surf_resource_state_t state){
126   e_surf_resource_state_t old = Resource::getState();
127   Resource::setState(state);
128   surf_callback_emit(hostStateChangedCallbacks, this, old, state);
129   p_cpu->setState(state);
130 }
131
132 int Host::getCore(){
133   return p_cpu->getCore();
134 }
135
136 double Host::getSpeed(double load){
137   return p_cpu->getSpeed(load);
138 }
139
140 double Host::getAvailableSpeed(){
141   return p_cpu->getAvailableSpeed();
142 }
143
144 double Host::getCurrentPowerPeak()
145 {
146   return p_cpu->getCurrentPowerPeak();
147 }
148
149 double Host::getPowerPeakAt(int pstate_index)
150 {
151   return p_cpu->getPowerPeakAt(pstate_index);
152 }
153
154 int Host::getNbPstates()
155 {
156   return p_cpu->getNbPstates();
157 }
158
159 void Host::setPstate(int pstate_index)
160 {
161         p_cpu->setPstate(pstate_index);
162 }
163 int Host::getPstate()
164 {
165         return p_cpu->getPstate();
166 }
167
168 xbt_dict_t Host::getProperties()
169 {
170   return p_cpu->getProperties();
171 }
172
173 StoragePtr Host::findStorageOnMountList(const char* mount)
174 {
175   StoragePtr st = NULL;
176   s_mount_t mnt;
177   unsigned int cursor;
178
179   XBT_DEBUG("Search for storage name '%s' on '%s'", mount, getName());
180   xbt_dynar_foreach(p_storage,cursor,mnt)
181   {
182     XBT_DEBUG("See '%s'",mnt.name);
183     if(!strcmp(mount,mnt.name)){
184       st = static_cast<StoragePtr>(mnt.storage);
185       break;
186     }
187   }
188   if(!st) xbt_die("Can't find mount '%s' for '%s'", mount, getName());
189   return st;
190 }
191
192 xbt_dict_t Host::getMountedStorageList()
193 {
194   s_mount_t mnt;
195   unsigned int i;
196   xbt_dict_t storage_list = xbt_dict_new_homogeneous(NULL);
197   char *storage_name = NULL;
198
199   xbt_dynar_foreach(p_storage,i,mnt){
200     storage_name = (char *)static_cast<StoragePtr>(mnt.storage)->getName();
201     xbt_dict_set(storage_list,mnt.name,storage_name,NULL);
202   }
203   return storage_list;
204 }
205
206 xbt_dynar_t Host::getAttachedStorageList()
207 {
208   xbt_lib_cursor_t cursor;
209   char *key;
210   void **data;
211   xbt_dynar_t result = xbt_dynar_new(sizeof(void*), NULL);
212   xbt_lib_foreach(storage_lib, cursor, key, data) {
213     if(xbt_lib_get_level(xbt_lib_get_elm_or_null(storage_lib, key), SURF_STORAGE_LEVEL) != NULL) {
214           StoragePtr storage = static_cast<StoragePtr>(xbt_lib_get_level(xbt_lib_get_elm_or_null(storage_lib, key), SURF_STORAGE_LEVEL));
215           if(!strcmp((const char*)storage->p_attach,this->getName())){
216             xbt_dynar_push_as(result, void *, (void*)storage->getName());
217           }
218         }
219   }
220   return result;
221 }
222
223 ActionPtr Host::open(const char* fullpath) {
224
225   StoragePtr st = NULL;
226   s_mount_t mnt;
227   unsigned int cursor;
228   size_t longest_prefix_length = 0;
229   char *path = NULL;
230   char *file_mount_name = NULL;
231   char *mount_name = NULL;
232
233   XBT_DEBUG("Search for storage name for '%s' on '%s'", fullpath, getName());
234   xbt_dynar_foreach(p_storage,cursor,mnt)
235   {
236     XBT_DEBUG("See '%s'",mnt.name);
237     file_mount_name = (char *) xbt_malloc ((strlen(mnt.name)+1));
238     strncpy(file_mount_name,fullpath,strlen(mnt.name)+1);
239     file_mount_name[strlen(mnt.name)] = '\0';
240
241     if(!strcmp(file_mount_name,mnt.name) && strlen(mnt.name)>longest_prefix_length)
242     {/* The current mount name is found in the full path and is bigger than the previous*/
243       longest_prefix_length = strlen(mnt.name);
244       st = static_cast<StoragePtr>(mnt.storage);
245     }
246     free(file_mount_name);
247   }
248   if(longest_prefix_length>0)
249   { /* Mount point found, split fullpath into mount_name and path+filename*/
250         path = (char *) xbt_malloc ((strlen(fullpath)-longest_prefix_length+1));
251         mount_name = (char *) xbt_malloc ((longest_prefix_length+1));
252         strncpy(mount_name, fullpath, longest_prefix_length+1);
253         strncpy(path, fullpath+longest_prefix_length, strlen(fullpath)-longest_prefix_length+1);
254         path[strlen(fullpath)-longest_prefix_length] = '\0';
255         mount_name[longest_prefix_length] = '\0';
256   }
257   else
258     xbt_die("Can't find mount point for '%s' on '%s'", fullpath, getName());
259
260   XBT_DEBUG("OPEN %s on disk '%s'",path, st->getName());
261   ActionPtr action = st->open((const char*)mount_name, (const char*)path);
262   free((char*)path);
263   free((char*)mount_name);
264   return action;
265 }
266
267 ActionPtr Host::close(surf_file_t fd) {
268   StoragePtr st = findStorageOnMountList(fd->mount);
269   XBT_DEBUG("CLOSE %s on disk '%s'",fd->name, st->getName());
270   return st->close(fd);
271 }
272
273 ActionPtr Host::read(surf_file_t fd, sg_size_t size) {
274   StoragePtr st = findStorageOnMountList(fd->mount);
275   XBT_DEBUG("READ %s on disk '%s'",fd->name, st->getName());
276   return st->read(fd, size);
277 }
278
279 ActionPtr Host::write(surf_file_t fd, sg_size_t size) {
280   StoragePtr st = findStorageOnMountList(fd->mount);
281   XBT_DEBUG("WRITE %s on disk '%s'",fd->name, st->getName());
282   return st->write(fd, size);
283 }
284
285 int Host::unlink(surf_file_t fd) {
286   if (!fd){
287     XBT_WARN("No such file descriptor. Impossible to unlink");
288     return -1;
289   } else {
290
291     StoragePtr st = findStorageOnMountList(fd->mount);
292     /* Check if the file is on this storage */
293     if (!xbt_dict_get_or_null(st->p_content, fd->name)){
294       XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name,
295           st->getName());
296       return -1;
297     } else {
298       XBT_DEBUG("UNLINK %s on disk '%s'",fd->name, st->getName());
299       st->m_usedSize -= fd->size;
300
301       // Remove the file from storage
302       xbt_dict_remove(st->p_content, fd->name);
303
304       xbt_free(fd->name);
305       xbt_free(fd->mount);
306       xbt_free(fd);
307       return 0;
308     }
309   }
310 }
311
312 sg_size_t Host::getSize(surf_file_t fd){
313   return fd->size;
314 }
315
316 xbt_dynar_t Host::getInfo( surf_file_t fd)
317 {
318   StoragePtr st = findStorageOnMountList(fd->mount);
319   sg_size_t *psize = xbt_new(sg_size_t, 1);
320   *psize = fd->size;
321   xbt_dynar_t info = xbt_dynar_new(sizeof(void*), NULL);
322   xbt_dynar_push_as(info, sg_size_t *, psize);
323   xbt_dynar_push_as(info, void *, fd->mount);
324   xbt_dynar_push_as(info, void *, (void *)st->getName());
325   xbt_dynar_push_as(info, void *, st->p_typeId);
326   xbt_dynar_push_as(info, void *, st->p_contentType);
327
328   return info;
329 }
330
331 sg_size_t Host::fileTell(surf_file_t fd){
332   return fd->current_position;
333 }
334
335 int Host::fileSeek(surf_file_t fd, sg_offset_t offset, int origin){
336
337   switch (origin) {
338   case SEEK_SET:
339     fd->current_position = offset;
340     return 0;
341   case SEEK_CUR:
342     fd->current_position += offset;
343     return 0;
344   case SEEK_END:
345     fd->current_position = fd->size + offset;
346     return 0;
347   default:
348     return -1;
349   }
350 }
351
352 int Host::fileMove(surf_file_t fd, const char* fullpath){
353   /* Check if the new full path is on the same mount point */
354   if(!strncmp((const char*)fd->mount, fullpath, strlen(fd->mount))) {
355     sg_size_t *psize, *new_psize;
356     psize = (sg_size_t*)
357         xbt_dict_get_or_null(findStorageOnMountList(fd->mount)->p_content,
358                              fd->name);
359     new_psize = xbt_new(sg_size_t, 1);
360     *new_psize = *psize;
361     if (psize){// src file exists
362       xbt_dict_remove(findStorageOnMountList(fd->mount)->p_content, fd->name);
363       char *path = (char *) xbt_malloc ((strlen(fullpath)-strlen(fd->mount)+1));
364       strncpy(path, fullpath+strlen(fd->mount),
365               strlen(fullpath)-strlen(fd->mount)+1);
366       xbt_dict_set(findStorageOnMountList(fd->mount)->p_content, path,
367                    new_psize,NULL);
368       XBT_DEBUG("Move file from %s to %s, size '%llu'",fd->name, fullpath, *psize);
369       free(path);
370       return 0;
371     } else {
372       XBT_WARN("File %s doesn't exist", fd->name);
373       return -1;
374     }
375   } else {
376     XBT_WARN("New full path %s is not on the same mount point: %s. Action has been canceled.",
377              fullpath, fd->mount);
378     return -1;
379   }
380 }
381
382 xbt_dynar_t Host::getVms()
383 {
384   xbt_dynar_t dyn = xbt_dynar_new(sizeof(VMPtr), NULL);
385
386   /* iterate for all virtual machines */
387   for (VMModel::vm_list_t::iterator iter =
388          VMModel::ws_vms.begin();
389        iter !=  VMModel::ws_vms.end(); ++iter) {
390
391     VMPtr ws_vm = &*iter;
392     if (this == ws_vm->p_subWs)
393       xbt_dynar_push(dyn, &ws_vm);
394   }
395
396   return dyn;
397 }
398
399 void Host::getParams(ws_params_t params)
400 {
401   *params = p_params;
402 }
403
404 void Host::setParams(ws_params_t params)
405 {
406   /* may check something here. */
407   p_params = *params;
408 }
409
410 /**********
411  * Action *
412  **********/
413
414 void HostAction::setState(e_surf_action_state_t state){
415   e_surf_action_state_t old = getState();
416   Action::setState(state);
417   surf_callback_emit(hostActionStateChangedCallbacks, this, old, state);
418 }