andromeda 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -36,7 +36,7 @@ module Andromeda
36
36
  end
37
37
  end
38
38
 
39
- class SendError < RuntimeError ; end
39
+ class SendError < RuntimeError ; end
40
40
  class ExecError < RuntimeError ; end
41
41
 
42
42
  end
@@ -2,7 +2,7 @@ module Andromeda
2
2
 
3
3
  module Guides
4
4
 
5
- class Guide
5
+ class Guide
6
6
  def track(spot, key, suggested_track = nil)
7
7
  raise NoMethodError
8
8
  end
@@ -11,7 +11,7 @@ module Andromeda
11
11
  return plan.copy if was_suggested
12
12
  if plan.frozen? then plan else plan.copy end
13
13
  end
14
- end
14
+ end
15
15
 
16
16
  class Track
17
17
  def follow(*args, &thunk) ; thunk.call *args end
@@ -1,8 +1,7 @@
1
1
  module Andromeda
2
-
3
2
  module Guides
4
3
 
5
- class Guide
4
+ class Guide
6
5
  include Andromeda::Impl::To_S
7
6
 
8
7
  def track(spot, label, suggested_track = nil)
@@ -20,7 +19,7 @@ module Andromeda
20
19
  if plan.frozen? then plan else plan.identical_copy end
21
20
  end
22
21
 
23
- end
22
+ end
24
23
 
25
24
  class Track
26
25
  include Andromeda::Impl::To_S
@@ -1,19 +1,19 @@
1
1
  module Andromeda
2
2
 
3
- class Id < Impl::XorId
4
- # Default length of generated ids
5
- DEFAULT_NUM_BYTES = 8
3
+ class Id < Impl::XorId
4
+ # Default length of generated ids
5
+ DEFAULT_NUM_BYTES = 8
6
6
 
7
- # @param [Bool] random
8
- def initialize(random = true)
9
- super DEFAULT_NUM_BYTES, random
10
- end
7
+ # @param [Bool] random
8
+ def initialize(random = true)
9
+ super DEFAULT_NUM_BYTES, random
10
+ end
11
11
 
12
- # @return [Id] empty (zero) id
13
- def self.zero
14
- @id = self.new false unless defined? @id
15
- @id
16
- end
17
- end
12
+ # @return [Id] empty (zero) id
13
+ def self.zero
14
+ @id = self.new false unless defined? @id
15
+ @id
16
+ end
17
+ end
18
18
 
19
19
  end
@@ -2,7 +2,7 @@ module Andromeda
2
2
 
3
3
  module Impl
4
4
 
5
- module ClassAttr
5
+ module ClassAttr
6
6
 
7
7
  protected
8
8
 
@@ -24,7 +24,7 @@ module Andromeda
24
24
  dest_set = get_attr_set var_name, false
25
25
  instance_variable_set var_name, dest_set.union(name_set)
26
26
  end
27
- end
27
+ end
28
28
 
29
29
  end
30
30
 
@@ -0,0 +1,89 @@
1
+ module Andromeda
2
+
3
+ module Impl
4
+
5
+ # Generator for random xorable ids (used for markers)
6
+ class XorId
7
+ include To_S
8
+
9
+ protected
10
+
11
+ def initialize(len, random = true, init_data = nil)
12
+ raise ArgumentError unless len.kind_of?(Fixnum)
13
+ raise ArgumentError unless len >= 0
14
+
15
+ @data = if init_data
16
+ init_data
17
+ else
18
+ if random
19
+ then len.times.map { Id.rnd_byte }
20
+ else len.times.map { 0 } end
21
+ end
22
+ end
23
+
24
+ public
25
+
26
+ def clone_to_copy? ; false end
27
+ def identical_copy ; self end
28
+
29
+ def length ; @data.length end
30
+ def zero? ; each { |b| return false unless b == 0 } ; true end
31
+
32
+ def [](key) ; @data[key] end
33
+
34
+ def same_length?(obj) ; self.length == obj.length end
35
+
36
+ def each ; this = self ; 0.upto(length-1).each { |i| yield this[i] } end
37
+ def each_with_index ; this = self ; 0.upto(length-1).each { |i| yield i, this[i] } end
38
+
39
+ # Compare self to b
40
+ # @param [Id] b
41
+ def ==(b)
42
+ return true if self.equal? b
43
+ return false if b.nil?
44
+ return false unless b.class.equal? self.class
45
+ return false unless same_length? b
46
+ zip_bytes(b) { |i, j| return false if i != j }
47
+ true
48
+ end
49
+
50
+ def hash ; @data.hash end
51
+
52
+ # xor self and b's ids component-wise
53
+ # @param [Array<Fixnum>] b
54
+ # @return [Id]
55
+ def xor(b)
56
+ r = []
57
+ zip_bytes(b) { |i,j| r << (i ^ j) }
58
+ Id.new r.length, false, r
59
+ end
60
+
61
+ def to_short_s
62
+ r = ''
63
+ each { |b| r << Id.two_char_hex_str(b.to_s(16)) }
64
+ r
65
+ end
66
+
67
+ def inspect ; to_s end
68
+
69
+ private
70
+
71
+ def zip_bytes(b)
72
+ a = self
73
+ 0.upto(length-1).each { |i| yield a[i], b[i] }
74
+ end
75
+
76
+ def self.rnd_byte ; Random.rand(256) end
77
+
78
+ def self.two_char_hex_str(s)
79
+ case s.length
80
+ when 0 then '00'
81
+ when 1 then "0#{s}"
82
+ else s
83
+ end
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ end
@@ -8,21 +8,21 @@ module Andromeda
8
8
  extend Impl::ClassAttr
9
9
 
10
10
  def self.spot_names(inherit = true) ; get_attr_set '@spot_names', inherit end
11
- def self.attr_spot_names(inherit = true) ; get_attr_set '@attr_spot_names', inherit end
12
- def self.meth_spot_names(inherit = true) ; get_attr_set '@meth_spot_names', inherit end
11
+ def self.spot_attr_names(inherit = true) ; get_attr_set '@spot_attr_names', inherit end
12
+ def self.spot_meth_names(inherit = true) ; get_attr_set '@spot_meth_names', inherit end
13
13
  def self.name_spot(*names) ; name_attr_set '@spot_names', *names end
14
14
 
15
- def self.meth_spot(name, opts = {})
15
+ def self.spot_meth(name, opts = {})
16
16
  name_spot name
17
- name_attr_set '@meth_spot_names', name
17
+ name_attr_set '@spot_meth_names', name
18
18
  define_method :"#{name}" do ||
19
19
  mk_spot name, opts = {}
20
20
  end
21
21
  end
22
22
 
23
- def self.attr_spot(*names)
23
+ def self.spot_attr(*names)
24
24
  name_spot *names
25
- name_attr_set '@attr_spot_names', *names
25
+ name_attr_set '@spot_attr_names', *names
26
26
  attr_writer *names
27
27
  names.each do |name|
28
28
  define_method :"#{name}" do ||
@@ -46,7 +46,7 @@ module Andromeda
46
46
  @id = Id.new
47
47
  set_from_config init_from_config, config
48
48
  @tags ||= {}
49
- @guide ||= init_guide
49
+ self.guide=(init_guide) unless @guide
50
50
  end
51
51
 
52
52
  def initialize_copy(other)
@@ -54,36 +54,41 @@ module Andromeda
54
54
  @tags ||= {}
55
55
  end
56
56
 
57
- def init_guide ; Guides::DefaultGuide.instance end
57
+ def init_guide ; Guides.default end
58
58
 
59
59
  def tags ; @tags end
60
60
  def to_short_s ; " id=#{id.to_short_s}t" end
61
61
  alias_method :inspect, :to_s
62
62
 
63
63
  def guide=(new_guide)
64
- new_guide = new_guide.instance if new_guide.is_a?(Class) && new_guide.include?(Singleton)
65
- @guide = new_guide
64
+ @guide = if new_guide.is_a?(Class)
65
+ if new_guide.include?(Singleton)
66
+ then new_guide.instance
67
+ else new_guide.new end
68
+ else
69
+ new_guide
70
+ end
66
71
  end
67
72
 
68
- # Overload to map all incoming data, default to data
69
- def data_map(name, data) ; data end
73
+ # Override to map all incoming data, default to data
74
+ def map_data(name, data) ; data end
70
75
 
71
- # Overload to extract the data key from mapped, incoming data, defaults to name
76
+ # Override to extract the data key from mapped, incoming data, defaults to name
72
77
  def data_key(name, data) ; name end
73
78
 
74
- # Overload to determine the target spot name from the key, defaults to name
79
+ # Override to determine the target spot name from the key, defaults to name
75
80
  def key_spot(name, key) ; name end
76
81
 
77
- # Overload to determine the target track label from the key, defaults to ket
82
+ # Override to determine the target track label from the key, defaults to key
78
83
  def key_label(name, key) ; key end
79
84
 
80
- # Overload to extract the data value from mapped, incoming data, defaults to data
85
+ # Override to extract the data value from mapped, incoming data, defaults to data
81
86
  def data_val(name, data) ; data end
82
87
 
83
- # Overload to compute additional tags
88
+ # Override to compute additional tags
84
89
  def data_tag(name, key, val, tags_in) ; { name: name } end
85
90
 
86
- # Overload to filter the data events that should be processed, defaults to true
91
+ # Override to filter the data events that should be processed, defaults to true
87
92
  def selects?(name, key, val, tags_in) ; true end
88
93
 
89
94
  def post_data(spot_, track_in, data, tags_in = {})
@@ -93,7 +98,7 @@ module Andromeda
93
98
  name = spot_.name
94
99
  details = { name: name, data: data, tags_in: tags_in, spot: spot_ }
95
100
  begin
96
- data = data_map name, data
101
+ data = map_data name, data
97
102
  key = data_key name, data
98
103
  name = key_spot name, key
99
104
 
@@ -133,19 +138,23 @@ module Andromeda
133
138
  end
134
139
 
135
140
  def spot_name?(name) ; spot_names.include? name end
136
- def attr_spot_name?(name) ; attr_spot_names.include? name end
137
- def meth_spot_name?(name) ; meth_spot_names.include? name end
141
+ def spot_attr_name?(name) ; spot_attr_names.include? name end
142
+ def spot_meth_name?(name) ; spot_meth_names.include? name end
138
143
  def signal_name?(name) ; signal_names.include? name end
139
144
 
140
145
  def spot_names ; self.class.spot_names end
141
- def attr_spot_names ; self.class.attr_spot_names end
142
- def meth_spot_names ; self.class.meth_spot_names end
146
+ def spot_attr_names ; self.class.spot_attr_names end
147
+ def spot_meth_names ; self.class.spot_meth_names end
143
148
  def signal_names ; self.class.signal_names end
144
149
 
145
150
  def current_scope ; tags[:scope] end
146
151
  def current_name ; tags[:name] end
147
152
 
148
- def >>(spot) ; @emit = spot.entry ; spot.dest end
153
+ def >>(spot)
154
+ @emit = spot.entry
155
+ d = spot.dest
156
+ if d then d else spot end
157
+ end
149
158
 
150
159
  def entry ; enter end
151
160
  def dest ; emit end
@@ -156,7 +165,7 @@ module Andromeda
156
165
 
157
166
  protected
158
167
 
159
- attr_spot :emit
168
+ spot_attr :emit
160
169
 
161
170
  def exit ; emit end
162
171
 
@@ -0,0 +1,48 @@
1
+ module Andromeda
2
+
3
+ module Impl
4
+
5
+ module To_S
6
+
7
+ def to_s(short = false)
8
+ if short
9
+ to_short_s
10
+ else
11
+ super_str = super()
12
+ class_name = self.class.name.split('::')[-1]
13
+ obj_id = object_id.to_s(16)
14
+ "\#<#{class_name}:0x#{obj_id}#{to_s(true)}>"
15
+ end
16
+ end
17
+
18
+ def to_short_s ; '' end
19
+
20
+ def self.short_s(v = value)
21
+ return ":#{v}" if v.is_a?(Symbol)
22
+ return "'#{v}'" if v.is_a?(String)
23
+ return 'nil' unless v
24
+ "#{v}"
25
+ end
26
+
27
+ end
28
+
29
+ # Shared base class of Spot and Impl::PrePlan
30
+ class ConnectorBase
31
+ # @return [Spot] entry.intern nil
32
+ def start ; entry.intern(nil) end
33
+
34
+ # post_to nil, data, tags_in
35
+ #
36
+ # @return [self]
37
+ def post(data, tags_in = {}) ; post_to nil, data, tags_in end
38
+
39
+ alias_method :<<, :post
40
+
41
+ # post_to LocalTrack.instance, data, tags_in
42
+ #
43
+ # @return [self]
44
+ def post_local(data, tags_in = {}) ; post_to Guides::LocalTrack.instance, data, tags_in end
45
+ end
46
+
47
+ end
48
+ end
@@ -1,172 +1,172 @@
1
1
  module Andromeda
2
2
 
3
- module Kit
4
-
5
- module Transf
6
- attr_accessor :filter
7
- attr_accessor :mapper
8
-
9
- def deliver_data(name, meth, key, val, tags_in)
10
- if signal_name?(name)
11
- super name, meth, key, val, tags_in
12
- else
13
- filter_ = filter
14
- mapper_ = mapper
15
- if !(filter_ && filter_.call(val))
16
- super name, meth, key, (if mapper_ then mapper_.call(val) else val end), tags_in
17
- end
18
- end
19
- end
20
- end
21
-
22
- class Tee < Plan
23
- attr_accessor :level
24
- attr_accessor :other
25
- attr_accessor :delay
26
-
27
- def initialize(config = {})
28
- config = { nick: config } unless config.is_a? Hash || config.is_a?(Spot)
29
- config = { other: config } unless config.is_a? Hash
30
- super config
31
-
32
- @level ||= :info
33
- end
34
-
35
- def initialize_copy(other)
36
- @level = other.level.identical_copy
37
- @delay = other.delay.identical_copy
38
- end
39
-
40
- def on_enter(key, val)
41
- log_ = log
42
- level_ = level
43
- sleep delay.to_i if delay
44
- if log_ && level_
45
- cur_name = current_name
46
- key_str = Andromeda::Impl::To_S.short_s key
47
- val_str = Andromeda::Impl::To_S.short_s val
48
- log_str = "#{to_s}.#{cur_name}(#{key_str}, #{val_str})"
49
- tags.each_pair { |k, v| log_str << " #{k}=#{Andromeda::Impl::To_S.short_s(v)}" }
50
- log_str << " tid=0x#{Thread.current.object_id.to_s(16)}"
51
- log_.send level, log_str
52
- end
53
- other_ = other
54
- other_ << val if other_
55
- super key, val
56
- end
57
- end
58
-
59
- class Targeting < Plan
60
- attr_accessor :targets
61
-
62
- def initialize(config = {})
63
- super config
64
- @targets ||= {}
65
- end
66
-
67
- def target_values ; t = targets ; t.values rescue t end
68
- end
69
-
70
- class Broadc < Targeting
71
- def on_enter(key, val)
72
- target_values { |t| intern(t) << val rescue nil }
73
- end
74
- end
75
-
76
- class Switch < Targeting
77
- def on_enter(key, val)
78
- (intern(key) rescue exit) << val rescue nil
79
- end
80
- end
81
-
82
- class SinglePlan < Plan
83
- def init_guide ; Guides::SinglePoolGuide.new end
84
- end
85
-
86
- class InlineKeyRouter < SinglePlan
87
- def key_spot(name, key) ; key end
88
- end
89
-
90
- class Gatherer < SinglePlan
91
- include Transf
92
- end
93
-
94
- class Reducer < Gatherer
95
- attr_accessor :state
96
- attr_accessor :reducer
97
-
98
- attr_spot :new_state
99
-
100
- def on_enter(key, val)
101
- reducer_ = reducer
102
-
103
- state_ = state
104
- new_ = reducer_.call state_, key, val
105
- unless new_ == state_
106
- state = new_
107
- new_state << state if new_state
108
- end
109
- end
110
- end
111
-
112
- class FileReader < Plan
113
- attr_reader :path
114
- attr_reader :mode
115
-
116
- def initialize(config = {})
117
- super config
118
- @mode ||= init_mode
119
- end
120
-
121
- def data_tag(name, key, val, tags_in)
122
- tags_out = super
123
- tags_out[:first] = val.first rescue 0
124
- tags_out[:last] = val.last rescue -1
125
- tags_out
126
- end
127
-
128
- def init_mode ; 'r' end
129
-
130
- protected
131
-
132
- def on_enter(key, val)
133
- file = File.open path, mode
134
- begin
135
- file.seek tags[:first]
136
- tags[:last] = file.size - 1 if tags[:last] < 0
137
- tags[:num] = tags[:last] - tags[:first]
138
- if block_given? then yield file else super key, val end
139
- ensure
140
- file.close
141
- end
142
- end
143
-
144
- end
145
-
146
- class FileChunker < FileReader
147
- attr_reader :num_chunks
148
-
149
- def initialize(config = {})
150
- super config
151
- @num_chunks ||= Guides::PoolGuide.num_procs
152
- end
153
-
154
- def on_enter(key, val)
155
- num_c = num_chunks
156
- super key, val do |f|
157
- fst = tags[:first]
158
- lst = tags[:last]
159
- sz = tags[:num] / num_c rescue 1
160
- sz = 1 if sz < 0
161
- while fst <= lst
162
- nxt = fst + sz
163
- nxt = lst if nxt > lst
164
- exit << Range.new(fst, nxt)
165
- fst = nxt + 1
166
- end
167
- end
168
- end
169
- end
170
-
171
- end
3
+ module Kit
4
+
5
+ module Transf
6
+ attr_accessor :filter
7
+ attr_accessor :mapper
8
+
9
+ def deliver_data(name, meth, key, val, tags_in)
10
+ if signal_name?(name)
11
+ super name, meth, key, val, tags_in
12
+ else
13
+ filter_ = filter
14
+ mapper_ = mapper
15
+ if !(filter_ && filter_.call(val))
16
+ super name, meth, key, (if mapper_ then mapper_.call(val) else val end), tags_in
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ class Tee < Plan
23
+ attr_accessor :level
24
+ spot_attr :other
25
+ attr_accessor :delay
26
+
27
+ def initialize(config = {})
28
+ config = { nick: config } unless config.is_a? Hash || config.is_a?(Spot)
29
+ config = { other: config } unless config.is_a? Hash
30
+ super config
31
+
32
+ @level ||= :info
33
+ end
34
+
35
+ def initialize_copy(other)
36
+ @level = other.level.identical_copy
37
+ @delay = other.delay.identical_copy
38
+ end
39
+
40
+ def on_enter(key, val)
41
+ log_ = log
42
+ level_ = level
43
+ sleep delay.to_i if delay
44
+ if log_ && level_
45
+ cur_name = current_name
46
+ key_str = Andromeda::Impl::To_S.short_s key
47
+ val_str = Andromeda::Impl::To_S.short_s val
48
+ log_str = "#{to_s}.#{cur_name}(#{key_str}, #{val_str})"
49
+ tags.each_pair { |k, v| log_str << " #{k}=#{Andromeda::Impl::To_S.short_s(v)}" }
50
+ log_str << " tid=0x#{Thread.current.object_id.to_s(16)}"
51
+ log_.send level, log_str
52
+ end
53
+ other_ = other
54
+ other_ << val if other_
55
+ super key, val
56
+ end
57
+ end
58
+
59
+ class Targeting < Plan
60
+ attr_accessor :targets
61
+
62
+ def initialize(config = {})
63
+ super config
64
+ @targets ||= {}
65
+ end
66
+
67
+ def target_values ; t = targets ; t.values rescue t end
68
+ end
69
+
70
+ class Broadc < Targeting
71
+ def on_enter(key, val)
72
+ target_values { |t| intern(t) << val rescue nil }
73
+ end
74
+ end
75
+
76
+ class Switch < Targeting
77
+ def on_enter(key, val)
78
+ (intern(key) rescue exit) << val rescue nil
79
+ end
80
+ end
81
+
82
+ class SinglePlan < Plan
83
+ def init_guide ; Guides::SinglePoolGuide.new end
84
+ end
85
+
86
+ class InlineKeyRouter < SinglePlan
87
+ def key_spot(name, key) ; key end
88
+ end
89
+
90
+ class Gatherer < SinglePlan
91
+ include Transf
92
+ end
93
+
94
+ class Reducer < Gatherer
95
+ attr_accessor :state
96
+ attr_accessor :reducer
97
+
98
+ spot_attr :new_state
99
+
100
+ def on_enter(key, val)
101
+ reducer_ = reducer
102
+
103
+ state_ = state
104
+ new_ = reducer_.call state_, key, val
105
+ unless new_ == state_
106
+ state = new_
107
+ new_state << state if new_state
108
+ end
109
+ end
110
+ end
111
+
112
+ class FileReader < Plan
113
+ attr_reader :path
114
+ attr_reader :mode
115
+
116
+ def initialize(config = {})
117
+ super config
118
+ @mode ||= init_mode
119
+ end
120
+
121
+ def data_tag(name, key, val, tags_in)
122
+ tags_out = super
123
+ tags_out[:first] = val.first rescue 0
124
+ tags_out[:last] = val.last rescue -1
125
+ tags_out
126
+ end
127
+
128
+ def init_mode ; 'r' end
129
+
130
+ protected
131
+
132
+ def on_enter(key, val)
133
+ file = File.open path, mode
134
+ begin
135
+ file.seek tags[:first]
136
+ tags[:last] = file.size - 1 if tags[:last] < 0
137
+ tags[:num] = tags[:last] - tags[:first]
138
+ if block_given? then yield file else super key, val end
139
+ ensure
140
+ file.close
141
+ end
142
+ end
143
+
144
+ end
145
+
146
+ class FileChunker < FileReader
147
+ attr_reader :num_chunks
148
+
149
+ def initialize(config = {})
150
+ super config
151
+ @num_chunks ||= Guides::PoolGuide.num_procs
152
+ end
153
+
154
+ def on_enter(key, val)
155
+ num_c = num_chunks
156
+ super key, val do |f|
157
+ fst = tags[:first]
158
+ lst = tags[:last]
159
+ sz = tags[:num] / num_c rescue 1
160
+ sz = 1 if sz < 0
161
+ while fst <= lst
162
+ nxt = fst + sz
163
+ nxt = lst if nxt > lst
164
+ exit << Range.new(fst, nxt)
165
+ fst = nxt + 1
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ end
172
172
  end