A library to scatter things accross a cluster depending on weights
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

91 lines
2.2 KiB

#pragma once
#include <stdint.h>
#include "9float.hpp"
using scatter_key_t = ninefloat::Q<__int128,64>;
static const scatter_key_t scatter_key_increment = ninefloat::Q<__int128,64>::min_increment();
#include <vector>
#include <numeric>
#include <type_traits>
namespace StorageTree {
namespace _impl {
template<class childs>
struct subdivision {
uint64_t weight;
std::vector<childs> content;
scatter_key_t begin;
scatter_key_t end;
static constexpr bool divisible = true;
};
struct daemon_impl {
uint64_t weight;
scatter_key_t begin;
scatter_key_t end;
static constexpr bool divisible = false;
};
template<class T>
constexpr T max(T any = 0)
{
if(any>any+scatter_key_increment) {
return any;
}
return max(any+scatter_key_increment);
}
}
using daemon = _impl::daemon_impl;
using server = _impl::subdivision<daemon>;
using subrack = _impl::subdivision<server>;
using rack = _impl::subdivision<subrack>;
using room = _impl::subdivision<rack>;
using datacenter = _impl::subdivision<room>;
using root = _impl::subdivision<datacenter>;
template<class T,class = void>
uint64_t total_weight(T& root)
{
return root.weight;
}
template<class T,std::enable_if_t<T::divisible>>
uint64_t total_weight(T& root)
{
uint64_t ret=0;
for(auto& val : root.content) {
ret+=total_weight(val);
}
return ret;
}
template<class T, class = void>
scatter_key_t update_weights(T& root, uint64_t total, double sub_ratio=1, scatter_key_t begin=0, double ratio=0.5)
{
root.begin = begin;
root.end = begin+scatter_key_t(0.5)*((scatter_key_t(1/sub_ratio)*scatter_key_t(ratio)+scatter_key_t((double)root.weight/(double)total)*scatter_key_t(1-ratio)));
return root.end;
}
template<class T,std::enable_if_t<T::divisible>>
scatter_key_t update_weights(T& root, uint64_t total, double sub_ratio=1, scatter_key_t begin=0, scatter_key_t ratio=0.5)
{
for(auto& elem : root.content) {
begin = update_weights(
elem,
total,
sub_ratio*root.content.size(),
begin,
ratio
)+scatter_key_increment;
}
return begin;
}
}