diff --git a/spec/crystal-scatter_spec.cr b/spec/crystal-scatter_spec.cr index 52f4997..1916f59 100644 --- a/spec/crystal-scatter_spec.cr +++ b/spec/crystal-scatter_spec.cr @@ -4,7 +4,7 @@ describe Crystal::Scatter do # TODO: Write tests it "add elements" do - rg = Crystal::Scatter::RingGraph(String).new + rg = Crystal::Scatter::RingGraph.new rg.add(UInt64.new(1),[0,0,0,0,0,0],"OSD0") rg.add(UInt64.new(1),[0,0,0,0,0,1],"OSD1") rg.add(UInt64.new(1),[0,0,0,0,1,0],"OSD2") diff --git a/src/crystal-scatter/metaring.cr b/src/crystal-scatter/metaring.cr index 16690ed..34ba732 100644 --- a/src/crystal-scatter/metaring.cr +++ b/src/crystal-scatter/metaring.cr @@ -1,9 +1,54 @@ require "./ring.cr" +require "mutex" module Crystal::Scatter + class Daemon + getter weight : UInt64 + getter location : Array(Int32) + getter url : String + def initialize(@weight : UInt64, @location : Array(Int32), @url : String) + end + end + class MetaRing + getter rings : Array(Ring) + getter ring_graph : RingGraph + + def initialize + @rings = Array(Ring).new + @ring_graph = Array(RingGraph).new + @lock = Mutex.new + end + + private def add_impl(element : Daemon) + @ring_graph.add(element.weight, element.location, element.url) + end + + private def update_impl + @ring_graph.generate_ring + ring = Ring.new + @ring_graph.snapshot do |daemon| + ring.push RingSlice.new(daemon.range_effector.not_nil!.[0],daemon.range_effector.not_nil!.[1],daemon.react_at) + end + @rings.push ring + end + + def add(element : Daemon) + @lock.synchronize do + add_impl element + update_impl + end + end + def add(elements : Array(Daemon)) + @lock.synchronize do + elements.each do |element| + add_impl element + end + update_impl + end + end end end \ No newline at end of file diff --git a/src/crystal-scatter/ring.cr b/src/crystal-scatter/ring.cr index b76140e..b24b4c5 100644 --- a/src/crystal-scatter/ring.cr +++ b/src/crystal-scatter/ring.cr @@ -1,10 +1,15 @@ module Crystal::Scatter class Slice + property s_begin : UInt64 + property s_end : UInt64 + property url : String + def initialize(@s_begin,@s_end,@url) + end end - class Ring + class Ring < Array(Slice) end diff --git a/src/crystal-scatter/ring_graph.cr b/src/crystal-scatter/ring_graph.cr index e580508..f97402c 100644 --- a/src/crystal-scatter/ring_graph.cr +++ b/src/crystal-scatter/ring_graph.cr @@ -9,6 +9,7 @@ module Crystal::Scatter class Daemon(Ign,T) getter range_effector : Nil | Tuple(UInt64,UInt64) + getter reach_at : T def initialize(@weight : UInt64 = 1) @reach_at = T.new @@ -32,6 +33,10 @@ module Crystal::Scatter 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) < Array(T) @@ -63,6 +68,14 @@ module Crystal::Scatter end at(elems[0]).add(nweight, elems.skip(1), reach_at) end + + def snapshot + each do |elem| + elem.snapshot do |x| + yield x + end + end + end end class Server(U) < Container(Daemon(U,U),U) end @@ -78,7 +91,7 @@ module Crystal::Scatter class Root(U) < Container(Datacenter(U),U) end end - class RingGraph(T) < Servers::Root(T) + class RingGraph < Servers::Root(String) def generate_ring(split_ratio : BigRational) set_effectors(UInt64::MAX, BigRational.new(1), get_weight, split_ratio) set_end