#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>
|
|
#include <iostream>
|
|
|
|
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>
|
|
uint64_t total_weight(T& root)
|
|
{
|
|
uint64_t ret=0;
|
|
|
|
for(auto& val : root.content) {
|
|
ret+=total_weight(val);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
template<>
|
|
uint64_t total_weight<daemon>(daemon& root)
|
|
{
|
|
return root.weight;
|
|
}
|
|
|
|
template<class T>
|
|
scatter_key_t update_weights(T& root, uint64_t total, double sub_ratio=1, scatter_key_t begin=0, double ratio=0.5)
|
|
{
|
|
auto b = begin;
|
|
for(auto& elem : root.content) {
|
|
std::cout<<"UP"<<std::endl;
|
|
b = update_weights(
|
|
elem,
|
|
total,
|
|
sub_ratio*root.content.size(),
|
|
b,
|
|
ratio
|
|
)+scatter_key_increment;
|
|
}
|
|
|
|
return begin;
|
|
}
|
|
|
|
template<>
|
|
scatter_key_t update_weights<daemon>(daemon& root, uint64_t total, double sub_ratio, scatter_key_t begin, double ratio)
|
|
{
|
|
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)));
|
|
std::cout<<"Starts: "<<(uint64_t)root.begin.data()<<" Ends: "<<(uint64_t)root.end.data()<<std::endl;
|
|
return root.end;
|
|
}
|
|
|
|
template<class T, typename... Args>
|
|
void add_rule(T& root, uint64_t weight, size_t idx, std::tuple<Args...> Var)
|
|
{
|
|
if(idx<root.content.size())
|
|
add_rule(root.content.at(idx),weight,Var...);
|
|
else if(idx==root.content.size())
|
|
{
|
|
root.content.emplace_back();
|
|
add_rule(root.content.at(idx),weight,Var...);
|
|
}
|
|
else
|
|
throw std::runtime_error("libscatter: Bad rule, are you sure the order is right?");
|
|
}
|
|
|
|
template<>
|
|
void add_rule<daemon,size_t>(daemon& root, uint64_t weight,std::tuple<>)
|
|
{
|
|
root.weight=weight;
|
|
}
|
|
}
|