|
|
@ -1,80 +1,91 @@ |
|
|
|
#pragma once |
|
|
|
#include <stdint.h> |
|
|
|
#include "9float.hpp" |
|
|
|
using scatter_key_t = ninefloat::Q<uint64_t,64>; |
|
|
|
static const scatter_key_t scatter_key_increment = ninefloat::Q<uint64_t,64>::min_increment(); |
|
|
|
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 StorageTree { |
|
|
|
|
|
|
|
namespace _impl{ |
|
|
|
namespace _impl { |
|
|
|
|
|
|
|
template<class childs> |
|
|
|
struct subdivision |
|
|
|
{ |
|
|
|
uint64_t weight; |
|
|
|
std::vector<childs> content; |
|
|
|
scatter_key_t begin; |
|
|
|
scatter_key_t end; |
|
|
|
static const bool divisible = true; |
|
|
|
}; |
|
|
|
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 const 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); |
|
|
|
} |
|
|
|
} |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
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>; |
|
|
|
return max(any+scatter_key_increment); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
template<class T, std::enable_if_t<T::divisible>> |
|
|
|
uint64_t total_weight(T& root) |
|
|
|
{ |
|
|
|
return std::reduce( |
|
|
|
root.content.begin(), |
|
|
|
root.content.end(), |
|
|
|
0UL, |
|
|
|
[](auto val, uint64_t acc) |
|
|
|
{ |
|
|
|
return acc+total_weight(val); |
|
|
|
} |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
template<class T, std::enable_if_t<!T::divisible>> |
|
|
|
uint64_t total_weight(T& root) |
|
|
|
{ |
|
|
|
return root.weight; |
|
|
|
} |
|
|
|
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, std::enable_if_t<T::divisible>> |
|
|
|
scatter_key_t update_weights(T& root, uint64_t sub_ratio=1, uint64_t total, scatter_key_t begin=0, scatter_key_t ratio=0.5) |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
template<class T, std::enable_if_t<!T::divisible>> |
|
|
|
scatter_key_t update_weights(T& root, uint64_t sub_ratio=1, uint64_t total, scatter_key_t begin, scatter_key_t end) |
|
|
|
{ |
|
|
|
this->begin = begin; |
|
|
|
this->end = end; |
|
|
|
} |
|
|
|
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; |
|
|
|
} |
|
|
|
} |