diff options
| author | Jérémy Zurcher <jeremy@asynk.ch> | 2012-05-03 22:27:16 +0200 | 
|---|---|---|
| committer | Jérémy Zurcher <jeremy@asynk.ch> | 2012-05-03 22:27:16 +0200 | 
| commit | 2ee48c4f18470e733f244c659221e243ff998416 (patch) | |
| tree | 62949886912b3dc5eb9e000b211e7f45f17ed978 /lib/evendoors | |
| download | edoors-ruby-2ee48c4f18470e733f244c659221e243ff998416.zip edoors-ruby-2ee48c4f18470e733f244c659221e243ff998416.tar.gz  | |
initial commit
Diffstat (limited to 'lib/evendoors')
| -rw-r--r-- | lib/evendoors/door.rb | 54 | ||||
| -rw-r--r-- | lib/evendoors/link.rb | 31 | ||||
| -rw-r--r-- | lib/evendoors/particle.rb | 138 | ||||
| -rw-r--r-- | lib/evendoors/room.rb | 123 | ||||
| -rw-r--r-- | lib/evendoors/space.rb | 24 | ||||
| -rw-r--r-- | lib/evendoors/spot.rb | 28 | ||||
| -rw-r--r-- | lib/evendoors/twirl.rb | 59 | 
7 files changed, 457 insertions, 0 deletions
diff --git a/lib/evendoors/door.rb b/lib/evendoors/door.rb new file mode 100644 index 0000000..9807d46 --- /dev/null +++ b/lib/evendoors/door.rb @@ -0,0 +1,54 @@ +#! /usr/bin/env ruby +# -*- coding: UTF-8 -*- + +# +module EvenDoors +    # +    class Door < Spot +        # +        def initialize n, p=nil +            super n, p +            @saved = nil +            @parent.add_spot self if @parent +        end +        # +        def require_p p_kls +            p = EvenDoors::Twirl.require_p p_kls +            p.src = self +            p +        end +        # +        def release_p p +            @saved=nil if @saved==p     # particle is released, all is good +            EvenDoors::Twirl.release_p p +        end +        # +        def process p +            @viewer.receive p if @viewer +            @saved = p +            receive p +            if not @saved.nil? +                puts "application didn't give that particle back #{p}" if EvenDoors::Twirl.debug +                puts "\t#{p.data EvenDoors::ERROR_FIELD}" if p.action==EvenDoors::ACT_ERROR +                release_p @saved +                @saved = nil +            end +        end +        # +        def send_p p +            p.src = self +            @saved=nil if @saved==p # particle is sent back the data, all is good +            @parent.send_p p        # daddy will know what to do +        end +        # +        def send_sys_p p +            p.src = self +            @saved=nil if @saved==p # particle is sent back the data, all is good +            @parent.send_sys_p p    # daddy will know what to do +        end +        # +    end +    # +end +# +# EOF diff --git a/lib/evendoors/link.rb b/lib/evendoors/link.rb new file mode 100644 index 0000000..b2a9bba --- /dev/null +++ b/lib/evendoors/link.rb @@ -0,0 +1,31 @@ +#! /usr/bin/env ruby +# -*- coding: UTF-8 -*- + +# +module EvenDoors +    # +    class Link +        # +        def initialize src, dsts, fields, cond_fields, cond_value +            @src = src                      # link source name +            @dsts = dsts                    # , separated destinations to apply to the particle on linking success +            @fields = fields                # , separated fields to apply to the particle on linking success +            @cond_fields = cond_fields      # , separated fields used to generate the link value with particle payload +            @cond_value = cond_value        # value which will be compared to the particle link value to link or not +            @door = nil                     # pointer to the source +        end +        # +        def self.from_particle_data p +            EvenDoors::Link.new(p.get_data(EvenDoors::LNK_SRC), p.get_data(EvenDoors::LNK_DSTS), +                                p.get_data(EvenDoors::LNK_FIELDS), p.get_data(EvenDoors::LNK_CONDF), +                                p.get_data(EvenDoors::LNK_CONDV)) +        end +        # +        attr_accessor :door +        attr_reader :src, :dsts, :fields, :cond_fields, :cond_value +        # +    end +    # +end +# +# EOF diff --git a/lib/evendoors/particle.rb b/lib/evendoors/particle.rb new file mode 100644 index 0000000..7b951f9 --- /dev/null +++ b/lib/evendoors/particle.rb @@ -0,0 +1,138 @@ +#! /usr/bin/env ruby +# -*- coding: UTF-8 -*- + +# +module EvenDoors +    # +    class Particle +        # +        def initialize +            reset! +        end +        # +        def reset! +            @ts = Time.now      # creation time +            @src = nil          # Spot.path where it's originated from +            @room = nil +            @door = nil         # Door where it's currently heading to +            @action = nil       # action to perform on the Door +            @dsts = []          # fifo of Spot.path where to travel to +            @link_fields = []   # the fields used to generate the link value +            @link_value = nil   # the value computed with the link_fields values extracted from the payload +                                # used for pearing in Door and linking in routing process +            @payload = {}       # the actual data carried by this particle +            @merged = []        # list of merged particles +        end +        # +        attr_accessor :src +        attr_reader :ts, :room, :door, :action, :link_value +        # +        # routing +        # +        def dst +            @dsts[0] +        end +        # +        def split_dst! +            p, @action = @dsts[0].split EvenDoors::ACT_SEP +            i = p.rindex EvenDoors::PATH_SEP +            if i.nil? +                @room = nil +                door_name = p +            else +                @room = p[0..i-1] +                door_name = p[i+1..-1] +            end +            door_name +        end +        # +        def dst_done! door +            @dsts.shift +            @door = door +        end +        # +        def error! e +            @action = EvenDoors::ACT_ERROR +            @door = @src +            @payload[EvenDoors::ERROR_FIELD]=e +        end +        # +        def clear_dsts! +            @dsts.clear +        end +        # +        def add_dsts paths +            paths.split(EvenDoors::LINK_SEP).each do |path| +                @dsts << path +            end +        end +        # +        def set_dst a, l=nil +            @room = nil +            @door = nil +            @action = nil +            clear_dsts! +            @dsts << ( l ? l.to_str : '' )+EvenDoors::ACT_SEP+a.to_str +        end +        # +        # data manipulation +        # +        def set_data k, v +            @payload[k] = v +            compute_link_value! if @link_fields.include? k +        end +        # +        def get_data k +            @payload[k] +        end +        alias :data :get_data +        # +        def data k +            @payload[k] +        end +        # +        def clone_data p +            @payload = p.payload.clone +        end +        # +        # link value and fields +        # +        def clear_link_fields! +            @link_fields.clear +            compute_link_value! +        end +        # +        def set_link_fields *args +            @link_fields.clear if not @link_fields.empty? +            args.compact! +            args.each do |lfs| +                lfs.split(',').each do |lf| +                    @link_fields << lf +                end +            end +            compute_link_value! +        end +        # +        def compute_link_value! +            @link_value = @link_fields.inject('') { |s,lf| s+=@payload[lf].to_s if @payload[lf]; s } +        end +        # +        # merge particles management +        # +        def merged_count +            @merged.length +        end +        # +        def merge p +            @merged << p +        end +        # +        def merged i +            @merged[i] +        end +        # +    end +    # +end +# +# EOF diff --git a/lib/evendoors/room.rb b/lib/evendoors/room.rb new file mode 100644 index 0000000..671b529 --- /dev/null +++ b/lib/evendoors/room.rb @@ -0,0 +1,123 @@ +#! /usr/bin/env ruby +# -*- coding: UTF-8 -*- + +# +module EvenDoors +    # +    class Room < Spot +        # +        def initialize n, p=nil +            super n, p +            @spots = {} +            @links = {} +            @cache = {} +            @parent.add_spot self if @parent +        end +        # +        def add_spot s +            raise EvenDoors::Exception.new "Spot #{s.name} already has #{s.parent.name} as parent" if not s.parent.nil? and s.parent!=self +            raise EvenDoors::Exception.new "Spot #{s.name} already exists in #{path}" if @spots.has_key? s.name +            s.parent = self if s.parent.nil? +            @spots[s.name]=s +        end +        # +        def add_link l +            l.door = @spots[l.src] +            raise EvenDoors::Exception.new "Link source #{l.src} does not exist in #{path}" if l.door.nil? +            (@links[l.src] ||= [])<< l +        end +        # +        def start! +            puts " * start #{path}" if EvenDoors::Twirl.debug +            @spots.values.each do |spot| spot.start! if spot.respond_to? :start! end +        end +        # +        def stop! +            puts " * stop #{path}" if EvenDoors::Twirl.debug +            @spots.values.each do |spot| spot.stop! if spot.respond_to? :stop! end +        end +        # +        def try_links p +            pending_link = nil +            apply_link = false +            links = @links[p.src.name] +            return false if links.nil? +            links.each do |link| +                apply_link = link.cond_fields.nil?  # unconditional link +                p.set_link_fields link.cond_fields if not apply_link +                if apply_link or (p.link_value==link.cond_value) +                    # link matches ! +                    if not pending_link.nil? +                        p2 = require_p p.class +                        p2.clone_data p +                        p2.src = link.door +                        p2.clear_dsts! +                        p2.add_dsts link.dsts +                        p2.set_link_fields link.fields +                        send_p p2 +                    end +                    pending_link = link +                end +            end +            if pending_link +                p.src = pending_link.door +                p.clear_dsts! +                p.add_dsts pending_link.dsts +                p.set_link_fields pending_link.fields +                send_p p +            end +            (not pending_link.nil?) +        end +        # +        def route_p p, door_name +            if p.room.nil? or p.room==path +                if door = @spots[door_name] +                    p.dst_done! door +                else +                    p.error! EvenDoors::ERROR_ROUTE_RRWD +                end +            elsif @parent +                @parent.route_p p, door_name +            else +                p.error! EvenDoors::ERROR_ROUTE_TRWR +            end +        end +        # +        def send_p p +            if d = p.dst +                puts " * send #{d.to_str} ..." if EvenDoors::Twirl.debug +                route_p p, p.split_dst! +                puts "  -> #{p.door.path}:#{p.action}" if EvenDoors::Twirl.debug +                EvenDoors::Twirl.send_p p +            elsif not try_links p +                p.error! EvenDoors::ERROR_ROUTE_NDNL +                puts "  -> #{p.door.path}:#{p.action}" if EvenDoors::Twirl.debug +                EvenDoors::Twirl.send_p p +            end +        end +        # +        def send_sys_p p +            if d = p.dst +                puts " * send_sys #{d.to_str} ..." if EvenDoors::Twirl.debug +                route_p p, p.split_dst! +                puts "  -> #{p.door.path}:#{p.action}" if EvenDoors::Twirl.debug +                EvenDoors::Twirl.send_sys_p p +            else +                p.error! EvenDoors::ERROR_ROUTE_SND +                puts "  -> #{p.door.path}:#{p.action}" if EvenDoors::Twirl.debug +                EvenDoors::Twirl.send_sys_p p +            end +        end +        # +        def process_sys p +            if p.action==ACT_ADD_LINK +                add_link EvenDoors::Link.from_particle_data p +            end +            EvenDoors::Twirl.release_p p +        end +        # +    end +    # +end +# +# EOF diff --git a/lib/evendoors/space.rb b/lib/evendoors/space.rb new file mode 100644 index 0000000..6579003 --- /dev/null +++ b/lib/evendoors/space.rb @@ -0,0 +1,24 @@ +#! /usr/bin/env ruby +# -*- coding: UTF-8 -*- + +# +module EvenDoors +    # +    class Space < Room +        # +        def initialize n, args={} +            super n, nil +            EvenDoors::Twirl.debug = args[:debug] || false +        end +        # +        def twirl! +            @spots.values.each do |spot| spot.start! end +            EvenDoors::Twirl.twirl! +            @spots.values.each do |spot| spot.stop! end +        end +        # +    end +    # +end +# +# EOF diff --git a/lib/evendoors/spot.rb b/lib/evendoors/spot.rb new file mode 100644 index 0000000..e88bac7 --- /dev/null +++ b/lib/evendoors/spot.rb @@ -0,0 +1,28 @@ +#! /usr/bin/env ruby +# -*- coding: UTF-8 -*- + +# +module EvenDoors +    # +    class Spot +        # +        def initialize n, p +            @name   = n     # unique in it's room +            @parent = p     # single direct parent +            @viewer = nil   # particle going through that position will be sent there readonly +        end +        # +        attr_reader :name +        attr_accessor :viewer, :parent +        # +        def path +            return @path if @path +            p = ( @parent ? @parent.path+'/' : '') + name +            @path = p.sub(/^\/+/,'').gsub(/\/{2,}/,'/').sub(/\/+$/,'') +        end +        # +    end +    # +end +# +# EOF diff --git a/lib/evendoors/twirl.rb b/lib/evendoors/twirl.rb new file mode 100644 index 0000000..30ef169 --- /dev/null +++ b/lib/evendoors/twirl.rb @@ -0,0 +1,59 @@ +#! /usr/bin/env ruby +# -*- coding: UTF-8 -*- + +# +module EvenDoors +    # +    class Twirl +        # +        @debug = false +        @pool = {}          # per particle class free list +        @sys_fifo = []      # system particles fifo list +        @app_fifo = []      # application particles fifo list +        # +        # +        class << self +            # +            attr_accessor :debug +            # +            def release_p p +                ( @pool[p.class] ||= [] ) << p +            end +            # +            def require_p p_kls +                l = @pool[p_kls] +                return p_kls.new if l.nil? +                p = l.pop +                return p_kls.new if p.nil? +                p.reset! +                p +            end +            # +            def send_p p +                @app_fifo << p +            end +            # +            def send_sys_p p +                @sys_fifo << p +            end +            # +            def twirl! +                while @sys_fifo.length>0 or @app_fifo.length>0 +                    while @sys_fifo.length>0 +                        p = @sys_fifo.shift +                        p.door.process_sys p +                    end +                    while @app_fifo.length>0 +                        p = @app_fifo.shift +                        p.door.process p +                    end +                end +            end +            # +        end +        # +    end +    # +end +# +# EOF  | 
