blob: 3348cd77333ac3a177f26d95dbabf076c5af58ca [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <ignite/common/ignite_error.h>
#include <algorithm>
#include <random>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
namespace ignite::network::detail {
/**
* Fibonacci sequence iterator.
*
* @tparam S Sequence length. Should be >= 2.
*/
template<size_t S, typename T = size_t>
class fibonacci_sequence {
public:
/** Size. */
static constexpr size_t size = S > 2 ? S : 2;
/**
* Constructor.
*/
constexpr fibonacci_sequence() {
for (size_t i = 2; i < size; ++i)
sequence[i] = sequence[i - 1] + sequence[i - 2];
}
/**
* Get n-th or max member of sequence.
*
* @param n Member position.
* @return N-th member of sequence if n < size, or max member.
*/
[[nodiscard]] constexpr T get_value(size_t n) const { return n < size ? sequence[n] : sequence[size - 1]; }
private:
/** Sequence of fibonacci numbers */
T sequence[size]{0, 1};
};
/**
* Format error message.
*
* @param description Error description.
* @param description Error details.
* @param advice User advice.
*/
inline std::string format_error_message(
std::string_view description, std::string_view details, std::string_view advice) {
std::stringstream messageBuilder;
messageBuilder << description;
if (!details.empty())
messageBuilder << ": " << details;
if (!advice.empty())
messageBuilder << ". " << advice;
return messageBuilder.str();
}
/**
* Try extract from system error stack, and return platform-specific error.
*
* @return Error in human-readable format.
*/
std::string get_last_system_error();
/**
* Try extract from system error stack, format and return platform-specific error.
*
* @param description Error description.
* @return Error in human-readable format.
*/
inline std::string get_last_system_error(std::string_view description, std::string_view advice) {
return format_error_message(description, get_last_system_error(), advice);
}
/**
* Try extract from system error stack and throw platform-specific error.
*
* @param description Error description.
* @param advice User advice.
*/
inline void throw_last_system_error(std::string_view description, std::string_view advice = {}) {
throw ignite_error(error::code::INTERNAL, get_last_system_error(description, advice));
}
/**
* Shuffle addresses randomly.
*
* @param addrsIn Addresses.
* @return Randomly shuffled addresses.
*/
template<typename Addrinfo>
std::vector<Addrinfo *> shuffle_addresses(Addrinfo *addrsIn) {
std::vector<Addrinfo *> res;
for (Addrinfo *it = addrsIn; it != NULL; it = it->ai_next)
res.push_back(it);
std::random_device device;
std::mt19937 generator(device());
std::shuffle(res.begin(), res.end(), generator);
return res;
}
} // namespace ignite::network::detail