require "big"
|
|
require "crystalline"
|
|
|
|
module Crystal::Scatter
|
|
|
|
module Servers
|
|
def last_effector_end : UInt64
|
|
UInt64.MAX
|
|
end
|
|
|
|
class Daemon(Ign,T)
|
|
getter range_effector : Nil | Tuple(UInt64,UInt64)
|
|
getter reach_at : T
|
|
getter self_id : Int32
|
|
|
|
def initialize(@self_id, @weight : UInt64 = 1)
|
|
@reach_at = T.new
|
|
end
|
|
|
|
def set_effectors(last_set : UInt64, split_rate : BigRational, total_weight : UInt64,split_ratio : BigRational) : UInt64
|
|
@range_effector = Tuple.new(
|
|
last_set+1,
|
|
(last_set+1+UInt64::MAX*(split_rate.inv*split_ratio + (@weight*(1-split_ratio))/total_weight)).round.to_big_f.to_u64
|
|
)
|
|
return @range_effector.not_nil!.[1]
|
|
end
|
|
|
|
def get_weight : UInt64
|
|
@weight
|
|
end
|
|
|
|
def <=>(other : Daemon(Ign,T))
|
|
@self_id<=>other.self_id
|
|
end
|
|
|
|
def add(@weight,elems,@reach_at)
|
|
end
|
|
|
|
def set_end
|
|
@range_effector=Tuple.new(@range_effector.not_nil!.[0],UInt64::MAX)
|
|
end
|
|
|
|
def snapshot
|
|
yield self
|
|
end
|
|
end
|
|
|
|
class Container(T,U,SelfT)
|
|
@contents : Crystalline::Containers::RBTreeSet(T)
|
|
getter self_id : Int32
|
|
|
|
def initialize(@self_id : Int32)
|
|
@contents = SelfT.new
|
|
end
|
|
|
|
def <=>(other : Container(T,U,SelfT))
|
|
@self_id<=>other.self_id
|
|
end
|
|
|
|
def set_effectors(last_set : UInt64, split_rate : BigRational, total_weight : UInt64, split_ratio : BigRational) : UInt64
|
|
split_rate *= @contents.size
|
|
@contents.each do |elem|
|
|
last_set = elem.set_effectors(last_set, split_rate,total_weight,split_ratio)
|
|
end
|
|
return last_set
|
|
end
|
|
|
|
def first
|
|
@contents.first.not_nil!
|
|
end
|
|
|
|
def last
|
|
@contents.last.not_nil!
|
|
end
|
|
|
|
def set_end
|
|
@contents.last.not_nil!.set_end
|
|
end
|
|
|
|
def get_weight : UInt64
|
|
total : UInt64 = 0
|
|
@contents.each do |elem|
|
|
total += elem.get_weight
|
|
end
|
|
return total
|
|
end
|
|
|
|
def add(nweight, elems, reach_at)
|
|
if(!(@contents.has_key?(T.new(elems[0]))))
|
|
@contents << T.new(elems[0])
|
|
end
|
|
@contents.get(T.new(elems[0])).not_nil!.add(nweight, elems.skip(1), reach_at)
|
|
end
|
|
|
|
def snapshot
|
|
@contents.each do |elem|
|
|
elem.snapshot do |x|
|
|
yield x
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
class Server(U) < Container(Daemon(U,U),U,Crystalline::Containers::RBTreeSet(Daemon(U,U))) end
|
|
|
|
class PSU(U) < Container(Server(U),U,Crystalline::Containers::RBTreeSet(Server(U))) end
|
|
|
|
class Rack(U) < Container(PSU(U),U,Crystalline::Containers::RBTreeSet(PSU(U))) end
|
|
|
|
class Room(U) < Container(Rack(U),U,Crystalline::Containers::RBTreeSet(Rack(U))) end
|
|
|
|
class Datacenter(U) < Container(Room(U),U,Crystalline::Containers::RBTreeSet(Room(U))) end
|
|
|
|
class Root(U) < Container(Datacenter(U),U,Crystalline::Containers::RBTreeSet(Datacenter(U))) end
|
|
end
|
|
|
|
class RingGraph < Servers::Root(String)
|
|
def generate_ring(split_ratio : BigRational)
|
|
set_effectors(UInt64::MAX, BigRational.new(1), get_weight, split_ratio)
|
|
set_end
|
|
end
|
|
end
|
|
end
|