Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into actor-yield
[simgrid.git] / src / s4u / s4u_file.cpp
1 /* Copyright (c) 2015-2017. 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 "xbt/log.h"
7
8 #include "simgrid/s4u/File.hpp"
9 #include "simgrid/s4u/Host.hpp"
10 #include "simgrid/s4u/Storage.hpp"
11 #include "simgrid/simix.hpp"
12 #include "src/surf/HostImpl.hpp"
13
14 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_file,"S4U files");
15
16 namespace simgrid {
17 namespace s4u {
18
19 File::File(std::string fullpath, void* userdata) : File(fullpath, Host::current(), userdata){};
20
21 File::File(std::string fullpath, sg_host_t host, void* userdata) : fullpath_(fullpath), userdata_(userdata)
22 {
23   // this cannot fail because we get a xbt_die if the mountpoint does not exist
24   Storage* st                  = nullptr;
25   size_t longest_prefix_length = 0;
26   XBT_DEBUG("Search for storage name for '%s' on '%s'", fullpath.c_str(), host->getCname());
27
28   for (auto const& mnt : host->getMountedStorages()) {
29     XBT_DEBUG("See '%s'", mnt.first.c_str());
30     mount_point_ = fullpath.substr(0, mnt.first.length());
31
32     if (mount_point_ == mnt.first && mnt.first.length() > longest_prefix_length) {
33       /* The current mount name is found in the full path and is bigger than the previous*/
34       longest_prefix_length = mnt.first.length();
35       st                    = mnt.second;
36     }
37   }
38   if (longest_prefix_length > 0) { /* Mount point found, split fullpath into mount_name and path+filename*/
39     mount_point_ = fullpath.substr(0, longest_prefix_length);
40     path_        = fullpath.substr(longest_prefix_length, fullpath.length());
41   } else
42     xbt_die("Can't find mount point for '%s' on '%s'", fullpath.c_str(), host->getCname());
43
44   localStorage = st;
45
46   XBT_DEBUG("\tOpen file '%s'", path_.c_str());
47   std::map<std::string, sg_size_t>* content = localStorage->getContent();
48   // if file does not exist create an empty file
49   auto sz = content->find(path_);
50   if (sz != content->end()) {
51     size_ = sz->second;
52   } else {
53     size_ = 0;
54     content->insert({path_, size_});
55     XBT_DEBUG("File '%s' was not found, file created.", path_.c_str());
56   }
57 }
58
59 sg_size_t File::read(sg_size_t size)
60 {
61   XBT_DEBUG("READ %s on disk '%s'", getPath(), localStorage->getCname());
62   // if the current position is close to the end of the file, we may not be able to read the requested size
63   sg_size_t read_size = localStorage->read(std::min(size, size_ - current_position_));
64   current_position_ += read_size;
65   return read_size;
66 }
67
68 sg_size_t File::write(sg_size_t size)
69 {
70   XBT_DEBUG("WRITE %s on disk '%s'. size '%llu/%llu'", getPath(), localStorage->getCname(), size, size_);
71   // If the storage is full before even starting to write
72   if (localStorage->getSizeUsed() >= localStorage->getSize())
73     return 0;
74   /* Substract the part of the file that might disappear from the used sized on the storage element */
75   localStorage->decrUsedSize(size_ - current_position_);
76
77   sg_size_t write_size = localStorage->write(size);
78   current_position_ += write_size;
79   size_ = current_position_;
80
81   localStorage->getContent()->erase(path_);
82   localStorage->getContent()->insert({path_, size_});
83
84   return write_size;
85 }
86
87 sg_size_t File::size()
88 {
89   return size_;
90 }
91
92 void File::seek(sg_offset_t offset)
93 {
94   current_position_ = offset;
95 }
96
97 void File::seek(sg_offset_t offset, int origin)
98 {
99   switch (origin) {
100     case SEEK_SET:
101       current_position_ = offset;
102       break;
103     case SEEK_CUR:
104       current_position_ += offset;
105       break;
106     case SEEK_END:
107       current_position_ = size_ + offset;
108       break;
109     default:
110       break;
111   }
112 }
113
114 sg_size_t File::tell()
115 {
116   return current_position_;
117 }
118
119 void File::move(std::string fullpath)
120 {
121   /* Check if the new full path is on the same mount point */
122   if (not strncmp(mount_point_.c_str(), fullpath.c_str(), mount_point_.length())) {
123     std::map<std::string, sg_size_t>* content = localStorage->getContent();
124     auto sz = content->find(path_);
125     if (sz != content->end()) { // src file exists
126       sg_size_t new_size = sz->second;
127       content->erase(path_);
128       std::string path = fullpath.substr(mount_point_.length(), fullpath.length());
129       content->insert({path.c_str(), new_size});
130       XBT_DEBUG("Move file from %s to %s, size '%llu'", path_.c_str(), fullpath.c_str(), new_size);
131     } else {
132       XBT_WARN("File %s doesn't exist", path_.c_str());
133     }
134   } else {
135     XBT_WARN("New full path %s is not on the same mount point: %s.", fullpath.c_str(), mount_point_.c_str());
136   }
137 }
138
139 int File::unlink()
140 {
141   /* Check if the file is on local storage */
142   if (localStorage->getContent()->find(path_) == localStorage->getContent()->end()) {
143     XBT_WARN("File %s is not on disk %s. Impossible to unlink", path_.c_str(), localStorage->getCname());
144     return -1;
145   } else {
146     XBT_DEBUG("UNLINK %s on disk '%s'", path_.c_str(), localStorage->getCname());
147     localStorage->decrUsedSize(size_);
148
149     // Remove the file from storage
150     localStorage->getContent()->erase(fullpath_);
151
152     return 0;
153   }
154 }
155
156 }} // namespace simgrid::s4u