X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/645f1e0306b5a190f60d52f3b49525941569f0aa..5cb2cfc8e7e651bb5f96ceb0b4ccc40683c16126:/src/s4u/s4u_file.cpp?ds=sidebyside diff --git a/src/s4u/s4u_file.cpp b/src/s4u/s4u_file.cpp index db1c5b2c3a..f66b6812d7 100644 --- a/src/s4u/s4u_file.cpp +++ b/src/s4u/s4u_file.cpp @@ -9,94 +9,242 @@ #include "simgrid/s4u/Host.hpp" #include "simgrid/s4u/Storage.hpp" #include "simgrid/simix.hpp" -#include "src/surf/FileImpl.hpp" #include "src/surf/HostImpl.hpp" +#include +#include +#include +#include +#include + XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_file,"S4U files"); namespace simgrid { namespace s4u { +simgrid::xbt::Extension FileSystemStorageExt::EXTENSION_ID; -File::File(const char* fullpath, void* userdata) : File(fullpath, Host::current(), userdata){}; +File::File(std::string fullpath, void* userdata) : File(fullpath, Host::current(), userdata){}; -File::File(const char* fullpath, sg_host_t host, void* userdata) : path_(fullpath), userdata_(userdata) +File::File(std::string fullpath, sg_host_t host, void* userdata) : fullpath_(fullpath), userdata_(userdata) { // this cannot fail because we get a xbt_die if the mountpoint does not exist Storage* st = nullptr; size_t longest_prefix_length = 0; - std::string path; - XBT_DEBUG("Search for storage name for '%s' on '%s'", fullpath, host->getCname()); + XBT_DEBUG("Search for storage name for '%s' on '%s'", fullpath.c_str(), host->getCname()); - for (auto mnt : host->getMountedStorages()) { + for (auto const& mnt : host->getMountedStorages()) { XBT_DEBUG("See '%s'", mnt.first.c_str()); - mount_point = std::string(fullpath).substr(0, mnt.first.size()); + mount_point_ = fullpath.substr(0, mnt.first.length()); - if (mount_point == mnt.first && mnt.first.length() > longest_prefix_length) { + if (mount_point_ == mnt.first && mnt.first.length() > longest_prefix_length) { /* The current mount name is found in the full path and is bigger than the previous*/ longest_prefix_length = mnt.first.length(); st = mnt.second; } } if (longest_prefix_length > 0) { /* Mount point found, split fullpath into mount_name and path+filename*/ - mount_point = std::string(fullpath).substr(0, longest_prefix_length); - path = std::string(fullpath).substr(longest_prefix_length, strlen(fullpath)); + mount_point_ = fullpath.substr(0, longest_prefix_length); + path_ = fullpath.substr(longest_prefix_length, fullpath.length()); } else - xbt_die("Can't find mount point for '%s' on '%s'", fullpath, host->getCname()); + xbt_die("Can't find mount point for '%s' on '%s'", fullpath.c_str(), host->getCname()); + + localStorage = st; + + XBT_DEBUG("\tOpen file '%s'", path_.c_str()); + std::map* content = localStorage->extension()->getContent(); + // if file does not exist create an empty file + auto sz = content->find(path_); + if (sz != content->end()) { + size_ = sz->second; + } else { + size_ = 0; + content->insert({path_, size_}); + XBT_DEBUG("File '%s' was not found, file created.", path_.c_str()); + } +} - pimpl_ = - simgrid::simix::kernelImmediate([this, st, path] { return new simgrid::surf::FileImpl(st, path, mount_point); }); - storage_type = st->getType(); - storageId = st->getName(); +sg_size_t File::read(sg_size_t size) +{ + XBT_DEBUG("READ %s on disk '%s'", getPath(), localStorage->getCname()); + // if the current position is close to the end of the file, we may not be able to read the requested size + sg_size_t read_size = localStorage->read(std::min(size, size_ - current_position_)); + current_position_ += read_size; + return read_size; } -File::~File() +sg_size_t File::write(sg_size_t size) { - simgrid::simix::kernelImmediate([this] { delete pimpl_; }); + XBT_DEBUG("WRITE %s on disk '%s'. size '%llu/%llu'", getPath(), localStorage->getCname(), size, size_); + // If the storage is full before even starting to write + if (sg_storage_get_size_used(localStorage) >= sg_storage_get_size(localStorage)) + return 0; + /* Substract the part of the file that might disappear from the used sized on the storage element */ + localStorage->extension()->decrUsedSize(size_ - current_position_); + + sg_size_t write_size = localStorage->write(size); + localStorage->extension()->incrUsedSize(write_size); + + current_position_ += write_size; + size_ = current_position_; + std::map* content = localStorage->extension()->getContent(); + + content->erase(path_); + content->insert({path_, size_}); + + return write_size; } -sg_size_t File::read(sg_size_t size) +sg_size_t File::size() { - return simcall_file_read(pimpl_, size, Host::current()); + return size_; } -sg_size_t File::write(sg_size_t size) +void File::seek(sg_offset_t offset) { - return simcall_file_write(pimpl_,size, Host::current()); + current_position_ = offset; } -sg_size_t File::write(sg_size_t size, sg_host_t host) +void File::seek(sg_offset_t offset, int origin) { - return simcall_file_write(pimpl_, size, host); + switch (origin) { + case SEEK_SET: + current_position_ = offset; + break; + case SEEK_CUR: + current_position_ += offset; + break; + case SEEK_END: + current_position_ = size_ + offset; + break; + default: + break; + } } -sg_size_t File::size() +sg_size_t File::tell() { - return simgrid::simix::kernelImmediate([this] { return pimpl_->size(); }); + return current_position_; } -void File::seek(sg_offset_t pos) +void File::move(std::string fullpath) { - simgrid::simix::kernelImmediate([this, pos] { pimpl_->seek(pos, SEEK_SET); }); + /* Check if the new full path is on the same mount point */ + if (not strncmp(mount_point_.c_str(), fullpath.c_str(), mount_point_.length())) { + std::map* content = localStorage->extension()->getContent(); + auto sz = content->find(path_); + if (sz != content->end()) { // src file exists + sg_size_t new_size = sz->second; + content->erase(path_); + std::string path = fullpath.substr(mount_point_.length(), fullpath.length()); + content->insert({path.c_str(), new_size}); + XBT_DEBUG("Move file from %s to %s, size '%llu'", path_.c_str(), fullpath.c_str(), new_size); + } else { + XBT_WARN("File %s doesn't exist", path_.c_str()); + } + } else { + XBT_WARN("New full path %s is not on the same mount point: %s.", fullpath.c_str(), mount_point_.c_str()); + } } -void File::seek(sg_offset_t pos, int origin) +int File::unlink() { - simgrid::simix::kernelImmediate([this, pos, origin] { pimpl_->seek(pos, origin); }); + /* Check if the file is on local storage */ + std::map* content = localStorage->extension()->getContent(); + + if (content->find(path_) == content->end()) { + XBT_WARN("File %s is not on disk %s. Impossible to unlink", path_.c_str(), localStorage->getCname()); + return -1; + } else { + XBT_DEBUG("UNLINK %s on disk '%s'", path_.c_str(), localStorage->getCname()); + localStorage->extension()->decrUsedSize(size_); + + // Remove the file from storage + content->erase(fullpath_); + + return 0; + } } -sg_size_t File::tell() +FileSystemStorageExt::FileSystemStorageExt(simgrid::s4u::Storage* ptr) { - return simgrid::simix::kernelImmediate([this] { return pimpl_->tell(); }); + content_ = parseContent(ptr->getImpl()->content_name); + size_ = ptr->getImpl()->size_; } -void File::move(const char* fullpath) +FileSystemStorageExt::~FileSystemStorageExt() { - simgrid::simix::kernelImmediate([this, fullpath] { pimpl_->move(fullpath); }); + delete content_; } -int File::unlink() +std::map* FileSystemStorageExt::parseContent(std::string filename) +{ + if (filename.empty()) + return nullptr; + + std::map* parse_content = new std::map(); + + std::ifstream* fs = surf_ifsopen(filename); + + std::string line; + std::vector tokens; + do { + std::getline(*fs, line); + boost::trim(line); + if (line.length() > 0) { + boost::split(tokens, line, boost::is_any_of(" \t"), boost::token_compress_on); + xbt_assert(tokens.size() == 2, "Parse error in %s: %s", filename.c_str(), line.c_str()); + sg_size_t size = std::stoull(tokens.at(1)); + + usedSize_ += size; + parse_content->insert({tokens.front(), size}); + } + } while (not fs->eof()); + delete fs; + return parse_content; +} +} +} + +using simgrid::s4u::FileSystemStorageExt; + +static void onStorageCreation(simgrid::s4u::Storage& st) +{ + st.extension_set(new FileSystemStorageExt(&st)); +} + +static void onStorageDestruction(simgrid::s4u::Storage& st) +{ + delete st.extension(); +} + +/* **************************** Public interface *************************** */ +SG_BEGIN_DECL() + +void sg_storage_file_system_init() +{ + + if (FileSystemStorageExt::EXTENSION_ID.valid()) + return; + + FileSystemStorageExt::EXTENSION_ID = simgrid::s4u::Storage::extension_create(); + + simgrid::s4u::Storage::onCreation.connect(&onStorageCreation); + simgrid::s4u::Storage::onDestruction.connect(&onStorageDestruction); +} + +sg_size_t sg_storage_get_size_free(sg_storage_t st) +{ + return st->extension()->getSize() - st->extension()->getUsedSize(); +} + +sg_size_t sg_storage_get_size_used(sg_storage_t st) +{ + return st->extension()->getUsedSize(); +} + +sg_size_t sg_storage_get_size(sg_storage_t st) { - return simgrid::simix::kernelImmediate([this] { return pimpl_->unlink(); }); + return st->extension()->getSize(); } -}} // namespace simgrid::s4u +SG_END_DECL()