andromeda 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -29
- data/Gemfile.lock +27 -71
- data/README.md +4 -4
- data/ROADMAP.md +7 -8
- data/andromeda.gemspec +17 -1
- data/lib/andromeda.rb +34 -34
- data/lib/andromeda/atom.rb +76 -76
- data/lib/andromeda/cmd.rb +239 -239
- data/lib/andromeda/error.rb +1 -1
- data/lib/andromeda/guide.rb +2 -2
- data/lib/andromeda/guide_track.rb +2 -3
- data/lib/andromeda/id.rb +13 -13
- data/lib/andromeda/impl/class_attr.rb +2 -2
- data/lib/andromeda/impl/id.rb +89 -0
- data/lib/andromeda/impl/proto_plan.rb +34 -25
- data/lib/andromeda/impl_base.rb +48 -0
- data/lib/andromeda/kit.rb +169 -169
- data/lib/andromeda/map_reduce.rb +1 -1
- data/lib/andromeda/patch/array_bin_search.rb +83 -0
- data/lib/andromeda/plan.rb +4 -4
- data/lib/andromeda/spot.rb +3 -3
- data/lib/andromeda/sugar.rb +13 -13
- data/lib/andromeda/sync.rb +5 -3
- data/lib/andromeda/version.rb +1 -1
- data/yard_extensions/andromeda.rb +2 -2
- metadata +119 -6
data/lib/andromeda/error.rb
CHANGED
data/lib/andromeda/guide.rb
CHANGED
@@ -2,7 +2,7 @@ module Andromeda
|
|
2
2
|
|
3
3
|
module Guides
|
4
4
|
|
5
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
22
|
+
end
|
24
23
|
|
25
24
|
class Track
|
26
25
|
include Andromeda::Impl::To_S
|
data/lib/andromeda/id.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
module Andromeda
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
class Id < Impl::XorId
|
4
|
+
# Default length of generated ids
|
5
|
+
DEFAULT_NUM_BYTES = 8
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
# @param [Bool] random
|
8
|
+
def initialize(random = true)
|
9
|
+
super DEFAULT_NUM_BYTES, random
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
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
|
-
|
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.
|
12
|
-
def self.
|
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.
|
15
|
+
def self.spot_meth(name, opts = {})
|
16
16
|
name_spot name
|
17
|
-
name_attr_set '@
|
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.
|
23
|
+
def self.spot_attr(*names)
|
24
24
|
name_spot *names
|
25
|
-
name_attr_set '@
|
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
|
-
|
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
|
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
|
-
|
65
|
-
|
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
|
-
#
|
69
|
-
def
|
73
|
+
# Override to map all incoming data, default to data
|
74
|
+
def map_data(name, data) ; data end
|
70
75
|
|
71
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
88
|
+
# Override to compute additional tags
|
84
89
|
def data_tag(name, key, val, tags_in) ; { name: name } end
|
85
90
|
|
86
|
-
#
|
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 =
|
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
|
137
|
-
def
|
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
|
142
|
-
def
|
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)
|
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
|
-
|
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
|
data/lib/andromeda/kit.rb
CHANGED
@@ -1,172 +1,172 @@
|
|
1
1
|
module Andromeda
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|