/*
Copyright 2018-2021, Barcelona Supercomputing Center (BSC), Spain
Copyright 2015-2021, Johannes Gutenberg Universitaet Mainz, Germany
This software was partially supported by the
EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).
This software was partially supported by the
ADA-FS project under the SPPEXA project funded by the DFG.
This file is part of GekkoFS.
GekkoFS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GekkoFS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GekkoFS. If not, see .
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include
using namespace std;
namespace gkfs {
namespace rpc {
SimpleHashDistributor::SimpleHashDistributor(host_t localhost,
unsigned int hosts_size)
: localhost_(localhost), hosts_size_(hosts_size), all_hosts_(hosts_size) {
::iota(all_hosts_.begin(), all_hosts_.end(), 0);
}
SimpleHashDistributor::SimpleHashDistributor() {}
host_t
SimpleHashDistributor::localhost() const {
return localhost_;
}
host_t
SimpleHashDistributor::locate_data(const string& path,
const chunkid_t& chnk_id) const {
return str_hash(path + ::to_string(chnk_id)) % hosts_size_;
}
host_t
SimpleHashDistributor::locate_data(const string& path, const chunkid_t& chnk_id,
unsigned int hosts_size) {
if(hosts_size_ != hosts_size) {
hosts_size_ = hosts_size;
all_hosts_ = std::vector(hosts_size);
::iota(all_hosts_.begin(), all_hosts_.end(), 0);
}
return str_hash(path + ::to_string(chnk_id)) % hosts_size_;
}
host_t
SimpleHashDistributor::locate_file_metadata(const string& path) const {
return str_hash(path) % hosts_size_;
}
::vector
SimpleHashDistributor::locate_directory_metadata(const string& path) const {
return all_hosts_;
}
LocalOnlyDistributor::LocalOnlyDistributor(host_t localhost)
: localhost_(localhost) {}
host_t
LocalOnlyDistributor::localhost() const {
return localhost_;
}
host_t
LocalOnlyDistributor::locate_data(const string& path,
const chunkid_t& chnk_id) const {
return localhost_;
}
host_t
LocalOnlyDistributor::locate_file_metadata(const string& path) const {
return localhost_;
}
::vector
LocalOnlyDistributor::locate_directory_metadata(const string& path) const {
return {localhost_};
}
ForwarderDistributor::ForwarderDistributor(host_t fwhost,
unsigned int hosts_size)
: fwd_host_(fwhost), hosts_size_(hosts_size), all_hosts_(hosts_size) {
::iota(all_hosts_.begin(), all_hosts_.end(), 0);
}
host_t
ForwarderDistributor::localhost() const {
return fwd_host_;
}
host_t
ForwarderDistributor::locate_data(const std::string& path,
const chunkid_t& chnk_id) const {
return fwd_host_;
}
host_t
ForwarderDistributor::locate_file_metadata(const std::string& path) const {
return str_hash(path) % hosts_size_;
}
std::vector
ForwarderDistributor::locate_directory_metadata(const std::string& path) const {
return all_hosts_;
}
bool
GuidedDistributor::init_guided() {
unsigned int destination_host;
chunkid_t chunk_id;
string path;
std::ifstream mapfile;
mapfile.open(GKFS_USE_GUIDED_DISTRIBUTION_PATH);
if((mapfile.rdstate() & std::ifstream::failbit) != 0)
return false; // If it fails, the mapping will be as the SimpleHash
while(mapfile >> path >> chunk_id >> destination_host) {
// We need destination+1, as 0 has an special meaning in the interval
// map.
if(path.size() > 0 and path[0] == '#') {
// Path that has this prefix will have metadata and data in the same
// place i.e. #/mdtest-hard/ 10 10 chunk_id and destination_host
// are not used
prefix_list.emplace_back(path.substr(1, path.size()));
continue;
}
auto I = map_interval.find(path);
if(I == map_interval.end())
map_interval[path] += make_pair(
boost::icl::discrete_interval::right_open(
chunk_id, chunk_id + 1),
destination_host + 1);
else if(I->second.find(chunk_id) == I->second.end())
I->second.insert(make_pair(
boost::icl::discrete_interval::right_open(
chunk_id, chunk_id + 1),
destination_host + 1));
}
mapfile.close();
return true;
}
GuidedDistributor::GuidedDistributor() {
init_guided();
}
GuidedDistributor::GuidedDistributor(host_t localhost,
unsigned int hosts_size) {
if(hosts_size_ != hosts_size) {
hosts_size_ = hosts_size;
localhost_ = localhost;
all_hosts_ = std::vector(hosts_size);
::iota(all_hosts_.begin(), all_hosts_.end(), 0);
}
init_guided();
}
host_t
GuidedDistributor::localhost() const {
return localhost_;
}
host_t
GuidedDistributor::locate_data(const string& path, const chunkid_t& chnk_id,
unsigned int hosts_size) {
if(hosts_size_ != hosts_size) {
hosts_size_ = hosts_size;
all_hosts_ = std::vector(hosts_size);
::iota(all_hosts_.begin(), all_hosts_.end(), 0);
}
return (locate_data(path, chnk_id));
}
host_t
GuidedDistributor::locate_data(const string& path,
const chunkid_t& chnk_id) const {
auto it = map_interval.find(path);
if(it != map_interval.end()) {
auto it_f = it->second.find(chnk_id);
if(it_f != it->second.end()) {
return (it_f->second -
1); // Decrement destination host from the interval_map
}
}
for(auto const& it : prefix_list) {
if(0 == path.compare(0, min(it.length(), path.length()), it, 0,
min(it.length(), path.length())))
;
return str_hash(path) % hosts_size_;
}
auto locate = path + ::to_string(chnk_id);
return str_hash(locate) % hosts_size_;
}
host_t
GuidedDistributor::locate_file_metadata(const string& path) const {
return str_hash(path) % hosts_size_;
}
::vector
GuidedDistributor::locate_directory_metadata(const string& path) const {
return all_hosts_;
}
} // namespace rpc
} // namespace gkfs