fairy 0.6.0

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.
Files changed (186) hide show
  1. data/LICENSE +674 -0
  2. data/Makefile +116 -0
  3. data/README +15 -0
  4. data/bin/fairy +582 -0
  5. data/bin/fairy-cat +74 -0
  6. data/bin/fairy-cp +128 -0
  7. data/bin/fairy-rm +122 -0
  8. data/bin/subcmd/controller +41 -0
  9. data/bin/subcmd/inspector +81 -0
  10. data/bin/subcmd/master +43 -0
  11. data/bin/subcmd/node +47 -0
  12. data/bin/subcmd/processor +54 -0
  13. data/doc/programming-interface.html +240 -0
  14. data/doc/programming-interface.rd +300 -0
  15. data/etc/fairy.conf.tmpl +118 -0
  16. data/ext/simple_hash/extconf.rb +4 -0
  17. data/ext/simple_hash/simple_hash.c +42 -0
  18. data/fairy.gemspec +60 -0
  19. data/lib/fairy/client/addins.rb +20 -0
  20. data/lib/fairy/client/barrier.rb +29 -0
  21. data/lib/fairy/client/basic-group-by.rb +52 -0
  22. data/lib/fairy/client/cat.rb +41 -0
  23. data/lib/fairy/client/direct-product.rb +51 -0
  24. data/lib/fairy/client/equijoin.rb +79 -0
  25. data/lib/fairy/client/exec.rb +54 -0
  26. data/lib/fairy/client/filter.rb +62 -0
  27. data/lib/fairy/client/find.rb +35 -0
  28. data/lib/fairy/client/group-by.rb +194 -0
  29. data/lib/fairy/client/here.rb +84 -0
  30. data/lib/fairy/client/inject.rb +70 -0
  31. data/lib/fairy/client/input-file.rb +53 -0
  32. data/lib/fairy/client/input-iota.rb +49 -0
  33. data/lib/fairy/client/input-local-file.rb +188 -0
  34. data/lib/fairy/client/input-varray.rb +30 -0
  35. data/lib/fairy/client/input.rb +42 -0
  36. data/lib/fairy/client/io-filter.rb +26 -0
  37. data/lib/fairy/client/junction.rb +31 -0
  38. data/lib/fairy/client/map.rb +34 -0
  39. data/lib/fairy/client/merge-group-by.rb +71 -0
  40. data/lib/fairy/client/output-file.rb +64 -0
  41. data/lib/fairy/client/output-local-file.rb +60 -0
  42. data/lib/fairy/client/output-null.rb +47 -0
  43. data/lib/fairy/client/output-varray.rb +50 -0
  44. data/lib/fairy/client/output.rb +29 -0
  45. data/lib/fairy/client/roma-put.rb +62 -0
  46. data/lib/fairy/client/roma.rb +156 -0
  47. data/lib/fairy/client/seg-join.rb +61 -0
  48. data/lib/fairy/client/seg-map.rb +78 -0
  49. data/lib/fairy/client/seg-shuffle.rb +35 -0
  50. data/lib/fairy/client/seg-split.rb +27 -0
  51. data/lib/fairy/client/seg-zip.rb +60 -0
  52. data/lib/fairy/client/select.rb +38 -0
  53. data/lib/fairy/client/sort.rb +48 -0
  54. data/lib/fairy/client/sort18.rb +56 -0
  55. data/lib/fairy/client/sort19.rb +61 -0
  56. data/lib/fairy/client/there.rb +47 -0
  57. data/lib/fairy/client/top_n_into_roma.rb +34 -0
  58. data/lib/fairy/client/wc.rb +92 -0
  59. data/lib/fairy/controller.rb +1103 -0
  60. data/lib/fairy/logger.rb +107 -0
  61. data/lib/fairy/master/addins.rb +20 -0
  62. data/lib/fairy/master/atom.rb +17 -0
  63. data/lib/fairy/master/c-barrier.rb +283 -0
  64. data/lib/fairy/master/c-basic-group-by.rb +250 -0
  65. data/lib/fairy/master/c-cat.rb +159 -0
  66. data/lib/fairy/master/c-direct-product.rb +203 -0
  67. data/lib/fairy/master/c-exec.rb +68 -0
  68. data/lib/fairy/master/c-filter.rb +422 -0
  69. data/lib/fairy/master/c-find.rb +138 -0
  70. data/lib/fairy/master/c-group-by.rb +64 -0
  71. data/lib/fairy/master/c-here.rb +80 -0
  72. data/lib/fairy/master/c-inject.rb +119 -0
  73. data/lib/fairy/master/c-input-file.rb +46 -0
  74. data/lib/fairy/master/c-input-iota.rb +66 -0
  75. data/lib/fairy/master/c-input-local-file.rb +117 -0
  76. data/lib/fairy/master/c-input-varray.rb +53 -0
  77. data/lib/fairy/master/c-input.rb +24 -0
  78. data/lib/fairy/master/c-inputtable.rb +31 -0
  79. data/lib/fairy/master/c-inputtable18.rb +36 -0
  80. data/lib/fairy/master/c-inputtable19.rb +35 -0
  81. data/lib/fairy/master/c-io-filter.rb +28 -0
  82. data/lib/fairy/master/c-junction.rb +54 -0
  83. data/lib/fairy/master/c-map.rb +27 -0
  84. data/lib/fairy/master/c-merge-group-by.rb +241 -0
  85. data/lib/fairy/master/c-output-file.rb +84 -0
  86. data/lib/fairy/master/c-output-local-file.rb +19 -0
  87. data/lib/fairy/master/c-output-null.rb +45 -0
  88. data/lib/fairy/master/c-output-varray.rb +57 -0
  89. data/lib/fairy/master/c-output.rb +20 -0
  90. data/lib/fairy/master/c-seg-join.rb +141 -0
  91. data/lib/fairy/master/c-seg-map.rb +26 -0
  92. data/lib/fairy/master/c-seg-shuffle.rb +87 -0
  93. data/lib/fairy/master/c-seg-split.rb +110 -0
  94. data/lib/fairy/master/c-seg-zip.rb +132 -0
  95. data/lib/fairy/master/c-select.rb +27 -0
  96. data/lib/fairy/master/c-sort.rb +108 -0
  97. data/lib/fairy/master/c-there.rb +57 -0
  98. data/lib/fairy/master/c-wc.rb +232 -0
  99. data/lib/fairy/master/job-interpriter.rb +19 -0
  100. data/lib/fairy/master/scheduler.rb +24 -0
  101. data/lib/fairy/master.rb +329 -0
  102. data/lib/fairy/node/addins.rb +19 -0
  103. data/lib/fairy/node/p-barrier.rb +95 -0
  104. data/lib/fairy/node/p-basic-group-by.rb +252 -0
  105. data/lib/fairy/node/p-direct-product.rb +153 -0
  106. data/lib/fairy/node/p-exec.rb +30 -0
  107. data/lib/fairy/node/p-filter.rb +363 -0
  108. data/lib/fairy/node/p-find.rb +111 -0
  109. data/lib/fairy/node/p-group-by.rb +1534 -0
  110. data/lib/fairy/node/p-here.rb +21 -0
  111. data/lib/fairy/node/p-identity.rb +24 -0
  112. data/lib/fairy/node/p-inject.rb +127 -0
  113. data/lib/fairy/node/p-input-file.rb +108 -0
  114. data/lib/fairy/node/p-input-iota.rb +39 -0
  115. data/lib/fairy/node/p-input-local-file.rb +61 -0
  116. data/lib/fairy/node/p-input-varray.rb +26 -0
  117. data/lib/fairy/node/p-io-filter.rb +28 -0
  118. data/lib/fairy/node/p-map.rb +40 -0
  119. data/lib/fairy/node/p-merger-group-by.rb +48 -0
  120. data/lib/fairy/node/p-output-file.rb +104 -0
  121. data/lib/fairy/node/p-output-local-file.rb +14 -0
  122. data/lib/fairy/node/p-output-null.rb +32 -0
  123. data/lib/fairy/node/p-output-varray.rb +41 -0
  124. data/lib/fairy/node/p-seg-join.rb +82 -0
  125. data/lib/fairy/node/p-seg-map.rb +34 -0
  126. data/lib/fairy/node/p-seg-split.rb +61 -0
  127. data/lib/fairy/node/p-seg-zip.rb +79 -0
  128. data/lib/fairy/node/p-select.rb +40 -0
  129. data/lib/fairy/node/p-single-exportable.rb +90 -0
  130. data/lib/fairy/node/p-sort.rb +195 -0
  131. data/lib/fairy/node/p-task.rb +113 -0
  132. data/lib/fairy/node/p-there.rb +44 -0
  133. data/lib/fairy/node/p-wc.rb +266 -0
  134. data/lib/fairy/node.rb +187 -0
  135. data/lib/fairy/processor.rb +510 -0
  136. data/lib/fairy/share/base-app.rb +114 -0
  137. data/lib/fairy/share/block-source.rb +234 -0
  138. data/lib/fairy/share/conf.rb +396 -0
  139. data/lib/fairy/share/debug.rb +21 -0
  140. data/lib/fairy/share/encoding.rb +17 -0
  141. data/lib/fairy/share/fast-tempfile.rb +93 -0
  142. data/lib/fairy/share/file-place.rb +176 -0
  143. data/lib/fairy/share/hash-1.rb +20 -0
  144. data/lib/fairy/share/hash-md5.rb +28 -0
  145. data/lib/fairy/share/hash-murmur.rb +69 -0
  146. data/lib/fairy/share/hash-rb18.rb +20 -0
  147. data/lib/fairy/share/hash-simple-hash.rb +28 -0
  148. data/lib/fairy/share/inspector.rb +16 -0
  149. data/lib/fairy/share/lc/exceptions.rb +82 -0
  150. data/lib/fairy/share/lc/ja/exceptions.rb +81 -0
  151. data/lib/fairy/share/locale.rb +17 -0
  152. data/lib/fairy/share/log.rb +215 -0
  153. data/lib/fairy/share/pool-dictionary.rb +53 -0
  154. data/lib/fairy/share/port-marshaled-queue.rb +347 -0
  155. data/lib/fairy/share/port.rb +1697 -0
  156. data/lib/fairy/share/reference.rb +45 -0
  157. data/lib/fairy/share/stdout.rb +56 -0
  158. data/lib/fairy/share/tr.rb +16 -0
  159. data/lib/fairy/share/varray.rb +147 -0
  160. data/lib/fairy/share/vfile.rb +183 -0
  161. data/lib/fairy/version.rb +8 -0
  162. data/lib/fairy.rb +206 -0
  163. data/sample/grep.rb +46 -0
  164. data/sample/ping.rb +19 -0
  165. data/sample/sort.rb +102 -0
  166. data/sample/wordcount.rb +61 -0
  167. data/spec/README +12 -0
  168. data/spec/fairy1_spec.rb +31 -0
  169. data/spec/fairy2_spec.rb +42 -0
  170. data/spec/fairy3_spec.rb +126 -0
  171. data/spec/fairy4_spec.rb +63 -0
  172. data/spec/fairy5_spec.rb +45 -0
  173. data/spec/fairy6_spec.rb +52 -0
  174. data/spec/fairy7_spec.rb +58 -0
  175. data/spec/fairy8_spec.rb +48 -0
  176. data/spec/mkdat.rb +148 -0
  177. data/spec/run_all.sh +65 -0
  178. data/test/testc.rb +7111 -0
  179. data/tools/cap_recipe/Capfile +144 -0
  180. data/tools/cap_recipe/cluster.yml.sample +14 -0
  181. data/tools/fairy_perf_graph.rb +444 -0
  182. data/tools/git-tag +44 -0
  183. data/tools/log-analysis.rb +62 -0
  184. data/tools/svn-ls-diff +38 -0
  185. data/tools/svn-tags +37 -0
  186. metadata +298 -0
@@ -0,0 +1,159 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "delegate"
7
+
8
+ require "thread"
9
+
10
+ require "fairy/master/c-filter"
11
+ require "fairy/master/c-io-filter"
12
+
13
+ module Fairy
14
+ class CCat<CIOFilter
15
+ Controller.def_export self
16
+
17
+ DeepConnect.def_single_method_spec(self, "REF new(REF, VAL, VAL)")
18
+
19
+ def initialize(controller, opts, others)
20
+ super
21
+
22
+ @others = others
23
+ @export_node_pairs_queues = nil
24
+ @export_node_pairs_queues_mutex = Mutex.new
25
+ @export_node_pairs_queues_cv = ConditionVariable.new
26
+
27
+ @main_precat = CPreCat.new(controller, opts)
28
+
29
+ @others_precat = @others.map{|o|
30
+ precat = CPreCat.new(controller, opts)
31
+ precat.input = o
32
+ precat
33
+ }
34
+ end
35
+
36
+ def node_class_name
37
+ "PIdentity"
38
+ end
39
+
40
+ def njob_creation_params
41
+ []
42
+ end
43
+
44
+ def input=(input)
45
+ @main_precat.input = input
46
+ # super(@main_precat)
47
+ start_create_nodes
48
+ end
49
+
50
+ def create_nodes
51
+ begin
52
+ no = 0
53
+ [@main_precat, *@others_precat].each do |input|
54
+ @input = input
55
+ input.output = @input
56
+ @controller.assign_ntasks(self, @create_node_mutex) do
57
+ |ntask, mapper, opts={}|
58
+ # njob = create_and_add_node(processor, mapper)
59
+ njob = create_node(ntask) {|node|
60
+ if opts[:init_njob]
61
+ opts[:init_njob].call(node)
62
+ end
63
+ mapper.bind_input(node)
64
+ node.no = no
65
+ }
66
+ no += 1
67
+ njob
68
+ end
69
+ end
70
+ rescue BreakCreateNode
71
+ # do nothing
72
+ Log::debug self, "BREAK CREATE NODE: #{self}"
73
+
74
+ rescue AbortCreateNode
75
+ Log::debug self, "Abort CREATE NODE: #{self}"
76
+ # do nothing
77
+
78
+ rescue ERR::NodeNotArrived
79
+ Log::debug self, "NODE NOT ARRIVED: #{file}"
80
+ begin
81
+ handle_exception($!)
82
+ rescue
83
+ Log::debug_exception(self)
84
+ end
85
+ Log::debug self, "NODE NOT ARRIVED2: #{file}"
86
+ raise
87
+
88
+ rescue ERR::CantExecSubcmd
89
+ begin
90
+ handle_exception($!)
91
+ rescue
92
+ Log::debug_exception(self)
93
+ end
94
+ Log::debug self, "CANT EXEC SUBCOMMAND: #{self}"
95
+ raise
96
+
97
+ rescue ERR::CantExecSubcmd
98
+ begin
99
+ handle_exception($!)
100
+ rescue
101
+ Log::debug_exception(self)
102
+ end
103
+ Log::debug self, "CANT EXEC SUBCOMMAND: #{self}"
104
+ raise
105
+
106
+ rescue Exception
107
+ Log::warn_exception(self)
108
+ raise
109
+ ensure
110
+ Log::debug self, "CREATE_NODES: #{self}.number_of_nodes=#{no}"
111
+ add_node(nil)
112
+ self.number_of_nodes = no
113
+ end
114
+ end
115
+
116
+ # def start_get_exports
117
+ # @export_node_pairs_queues = [@input, *@others].collect{|input|
118
+ # export_node_pairs = Queue.new
119
+ # Thread.start do
120
+ # input.each_export do |*export_node_pair|
121
+ # export_node_pairs.push export_node_pair
122
+ # end
123
+ # export_node_pairs.push nil
124
+ # end
125
+ # export_node_pairs
126
+ # }
127
+ # @export_node_pairs_queues_cv.broadcast
128
+ # end
129
+
130
+ # def each_export(&block)
131
+ # @export_node_pairs_queues_mutex.synchronize do
132
+ # while !@export_node_pairs_queues
133
+ # @export_node_pairs_queues_cv.wait(@export_node_pairs_queues_mutex)
134
+ # end
135
+ # end
136
+
137
+ # for export_node_pairs in @export_node_pairs_queues
138
+ # while pair = export_node_pairs.pop
139
+ # block.call *pair
140
+ # end
141
+ # end
142
+ # end
143
+
144
+ class CPreCat<CIOFilter
145
+ def initialize(controller, opts)
146
+ super
147
+ end
148
+
149
+ def node_class_name
150
+ "PIdentity"
151
+ end
152
+
153
+ def njob_creation_params
154
+ []
155
+ end
156
+ end
157
+
158
+ end
159
+ end
@@ -0,0 +1,203 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "forwardable"
7
+
8
+ require "deep-connect"
9
+
10
+ require "fairy/master/c-io-filter"
11
+
12
+ module Fairy
13
+ class CDirectProduct<CIOFilter
14
+ extend Forwardable
15
+
16
+ Controller.def_export self
17
+
18
+ DeepConnect.def_single_method_spec(self, "REF new(REF, VAL, VAL, REF)")
19
+
20
+ def initialize(controller, opts, others, block_source)
21
+ super
22
+
23
+ @others = others
24
+ @block_source = block_source
25
+
26
+ @main_prefilter = CPreFilter.new(@controller, @opts, block_source)
27
+ @main_prefilter.main = self
28
+ @other_prefilters = []
29
+ @others.each do |other|
30
+ prefilter = CPreFilter.new(@controller, @opts, block_source)
31
+ prefilter.main = self
32
+ @other_prefilters.push prefilter
33
+ end
34
+ @postfilter = CPostFilter.new(@controller, @opts, block_source)
35
+
36
+ @prefilter_no_nodes = {}
37
+ @prefilter_no_nodes_mutex = Mutex.new
38
+ @prefilter_no_nodes_cv = ConditionVariable.new
39
+ end
40
+
41
+ attr_reader :other_prefilters
42
+
43
+ def all_prefilters
44
+ [@main_prefilter, *@other_prefilters]
45
+ end
46
+
47
+ def njob_creation_params
48
+ [@block_source]
49
+ end
50
+
51
+ def each_assigned_filter(&block)
52
+ @postfilter.each_assigned_filter &block
53
+ end
54
+
55
+ def input=(other)
56
+ @main_prefilter.input = other
57
+ @others.zip(@other_prefilters) do |o, prefilter|
58
+ prefilter.input = o
59
+ end
60
+
61
+ @postfilter.input = @main_prefilter
62
+ end
63
+
64
+ def update_prefilter_no_nodes(prefilter)
65
+ @prefilter_no_nodes_mutex.synchronize do
66
+ @prefilter_no_nodes[prefilter] = prefilter.number_of_nodes
67
+ @prefilter_no_nodes_cv.broadcast
68
+ end
69
+ end
70
+
71
+ def no_of_exports_for_prefilter(prefilter)
72
+ all_prefilters.reject{|f| prefilter==f}.inject(1){|dp, f|
73
+ @prefilter_no_nodes_mutex.synchronize do
74
+ while (v = @prefilter_no_nodes[f]).nil?
75
+ @prefilter_no_nodes_cv.wait(@prefilter_no_nodes_mutex)
76
+ end
77
+ dp *= v
78
+ end
79
+ }
80
+ end
81
+
82
+ # 呼ばれない
83
+ # def start_create_nodes
84
+ # @main_prefilter.start_create_nodes
85
+ # end
86
+
87
+ class CPreFilter<CIOFilter
88
+ Controller.def_export self
89
+
90
+ def initialize(controller, opts, block_source)
91
+ super
92
+ @block_source = block_source
93
+
94
+ @no = 0
95
+ @exports = {}
96
+ @exports_mutex = Mutex.new
97
+ # @exports_cv = ConditionVariable.new
98
+
99
+ @products = nil
100
+ @products_mutex = Mutex.new
101
+ @products_cv = ConditionVariable.new
102
+ end
103
+
104
+ def main=(main)
105
+ @main = main
106
+ end
107
+
108
+ def node_class_name
109
+ "PDirectProduct::PPreFilter"
110
+ end
111
+
112
+ def njob_creation_params
113
+ [@block_source]
114
+ end
115
+
116
+ def number_of_nodes=(no)
117
+ super
118
+ @main.update_prefilter_no_nodes(self)
119
+ end
120
+
121
+ def number_of_exports
122
+ @main.no_of_exports_for_prefilter(self)
123
+ end
124
+
125
+ def start_create_nodes
126
+ Log::debug self, "START_CREATE_NODES: #{self}"
127
+ @main.other_prefilters.each do |other|
128
+ Thread.start do
129
+ other.each_assigned_filter do |input_filter|
130
+ exp = input_filter.start_export
131
+ end
132
+ end
133
+ end
134
+ super
135
+ end
136
+
137
+ def each_assigned_filter(&block)
138
+ Thread.start do
139
+ @main.other_prefilters.each do |p|
140
+ p.each_node do |n|
141
+ @exports_mutex.synchronize do
142
+ @exports[n] = n.exports.dc_dup
143
+ # @exports_cv.broadcast
144
+ end
145
+ end
146
+ end
147
+ @products_mutex.synchronize do
148
+ @products = nodes.product(*@main.other_prefilters.collect{|p| p.nodes})
149
+ @products_cv.broadcast
150
+ end
151
+ end
152
+
153
+ super
154
+ end
155
+
156
+ # main prefilter 用
157
+ def each_export_by(njob, mapper, &block)
158
+ @exports_mutex.synchronize do
159
+ @exports[njob] = njob.exports.dc_dup
160
+ # @exports_cv.broadcast
161
+ end
162
+ @products_mutex.synchronize do
163
+ while !@products
164
+ @products_cv.wait(@products_mutex)
165
+ end
166
+
167
+ post_njob_no = -1
168
+ @products.each do |main_njob, *others_njobs|
169
+ post_njob_no += 1
170
+ next if main_njob != njob
171
+ @others_njobs = others_njobs
172
+
173
+ block.call(@exports[main_njob].shift,
174
+ :init_njob => proc{|njob|
175
+ njob.no = post_njob_no
176
+ njob.other_inputs = others_njobs.collect{|n| @exports[n].shift}})
177
+ end
178
+ end
179
+ end
180
+
181
+ def bind_export(exp, imp)
182
+ # do nothing
183
+ end
184
+ end
185
+
186
+ class CPostFilter<CIOFilter
187
+ Controller.def_export self
188
+
189
+ def initialize(controller, opts, block_source)
190
+ super
191
+ @block_source = block_source
192
+ end
193
+
194
+ def node_class_name
195
+ "PDirectProduct::PPostFilter"
196
+ end
197
+
198
+ def njob_creation_params
199
+ [@block_source]
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: UTF-8
2
+
3
+ require "uri"
4
+
5
+ require "fairy/master/c-input"
6
+ require "fairy/share/vfile"
7
+
8
+ module Fairy
9
+
10
+ class CExec<CInput
11
+ Controller.def_export self
12
+
13
+ URI_REGEXP = /:\/\//
14
+
15
+ def node_class_name
16
+ "PExec"
17
+ end
18
+
19
+ def start(vf)
20
+ @vfile = vf
21
+ @cfile_place = CFilePlace.new(@vfile)
22
+
23
+ start_create_nodes
24
+ end
25
+ DeepConnect.def_method_spec(self, "REF start(DVAL)")
26
+
27
+ def input
28
+ @cfile_place
29
+ end
30
+
31
+
32
+ # def create_and_start_nodes
33
+ # begin
34
+ # no = 0
35
+ # for node_spec in @vfile
36
+ # @create_node_mutex.synchronize do
37
+ # no += 1
38
+ # Log::debug self, "NO: #{no}"
39
+ # host = "localhost"
40
+ # path = node_spec
41
+ # if URI_REGEXP =~ node_spec
42
+ # uri = URI(node_spec)
43
+ # host = uri.host
44
+ # if /^\[([0-9a-f.:]*)\]$/ =~ host
45
+ # host = $1
46
+ # end
47
+ # path = uri.path
48
+ # end
49
+
50
+ # @controller.assign_input_processor(self, host) do |processor|
51
+ # njob = create_node(processor)
52
+ # njob.start(node_spec)
53
+ # end
54
+ # end
55
+ # end
56
+ # rescue BreakCreateNode
57
+ # # do nothing
58
+ # Log::debug self, "BREAK CREATE NODE: #{self}"
59
+ # rescue Exception
60
+ # Log::warn_exception(self)
61
+ # raise
62
+ # ensure
63
+ # Log::debug self, "CREATE_NODES: #{self}.number_of_nodes=#{no}"
64
+ # self.number_of_nodes = no
65
+ # end
66
+ # end
67
+ end
68
+ end
@@ -0,0 +1,422 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ module Fairy
7
+ class CFilter
8
+ Controller.def_export self
9
+
10
+ @@watch_status = false
11
+ def self.watch_status
12
+ @@watch_status
13
+ end
14
+
15
+ def self.watch_status=(val)
16
+ @@watch_status=val
17
+ end
18
+
19
+ DeepConnect.def_single_method_spec(self, "REF new(REF, VAL, *DEFAULT)")
20
+
21
+ def initialize(controller, opts, *rests)
22
+ Log::info self, "CREATE BJOB: #{self.class}"
23
+ @controller = controller
24
+
25
+ @opts = opts
26
+ @opts = {} unless @opts
27
+
28
+ @job_pool_dict = PoolDictionary.new
29
+
30
+ @number_of_nodes = nil
31
+ # @number_of_nodes_mutex = Mutex.new
32
+ # @number_of_nodes_cv = ConditionVariable.new
33
+
34
+ @nodes = []
35
+ @nodes_for_next_filters = []
36
+ @nodes_mutex = Mutex.new
37
+ @nodes_cv = ConditionVariable.new
38
+
39
+ @nodes_status = {}
40
+ @nodes_status_mutex = Mutex.new
41
+ @nodes_status_cv = ConditionVariable.new
42
+
43
+ @controller.register_bjob(self)
44
+
45
+ @create_node_thread = nil
46
+ # gbreakのときに安全に@create_node_threadスレッドをとめるため
47
+ @create_node_mutex = Mutex.new
48
+
49
+ @context = Context.new(self)
50
+
51
+ start_watch_node_status if watch_status?
52
+ end
53
+
54
+ def input
55
+ ERR::Raise ERR::INTERNAL::ShouldDefineSubclass
56
+ end
57
+
58
+ def postmapping_policy
59
+ @opts[:postmapping_policy] || CONF.POSTMAPPING_POLICY
60
+ end
61
+
62
+ #
63
+ # Pool Variables:
64
+ # (JP: プール変数)
65
+ #
66
+ def pool_dict
67
+ @controller.pool_dict
68
+ end
69
+
70
+ def job_pool_dict
71
+ @job_pool_dict
72
+ end
73
+
74
+ def def_job_pool_variable(vname, value = nil)
75
+ @job_pool_dict.def_variable(vname, value)
76
+ end
77
+
78
+ def job_pool_variable(vname, *value)
79
+ if value.empty?
80
+ @job_pool_dict[vname]
81
+ else
82
+ @job_pool_dict[vname] = value
83
+ end
84
+ end
85
+
86
+
87
+ #
88
+ # Njob Methods:
89
+ #
90
+ def number_of_nodes=(no)
91
+ #puts "#{self}.number_of_nodes=#{no}"
92
+ # @number_of_nodes_mutex.synchronize do
93
+ @nodes_mutex.synchronize do
94
+ @number_of_nodes = no
95
+ # @number_of_nodes_cv.broadcast
96
+ @nodes_cv.broadcast
97
+ @nodes_status_cv.broadcast
98
+ end
99
+ end
100
+
101
+ def nodes
102
+ @nodes_mutex.synchronize do
103
+ @nodes
104
+ end
105
+ end
106
+
107
+ def add_node(node)
108
+ @nodes_mutex.synchronize do
109
+ unless node
110
+ @nodes_for_next_filters.push nil
111
+ @nodes_cv.broadcast
112
+ return
113
+ end
114
+
115
+ # node.no = node.input.no
116
+ @nodes[node.no] = node
117
+ @nodes_for_next_filters.push node
118
+ @nodes_cv.broadcast
119
+ end
120
+ end
121
+
122
+ def each_node(flag = nil, &block)
123
+ if flag == :exist_only
124
+ return each_node_exist_only &block
125
+ end
126
+ @nodes_mutex.synchronize do
127
+ idx = 0
128
+ while !@number_of_nodes || idx < @number_of_nodes
129
+ unless @nodes[idx]
130
+ @nodes_cv.wait(@nodes_mutex)
131
+ next
132
+ end
133
+ begin
134
+ @nodes_mutex.unlock
135
+ block.call @nodes[idx]
136
+ ensure
137
+ @nodes_mutex.lock
138
+ end
139
+ idx +=1
140
+ end
141
+ end
142
+ end
143
+
144
+ def each_node_exist_only(&block)
145
+ nodes = @nodes_mutex.synchronize{@nodes.dup}
146
+ nodes.each &block
147
+ end
148
+
149
+ # def each_export(&block)
150
+ # each_node do |node|
151
+ # exp = node.export
152
+ # block.call exp, node
153
+ # node.export.output_no_import = 1
154
+ # end
155
+ # end
156
+
157
+ def number_of_nodes
158
+ # @number_of_nodes_mutex.synchronize do
159
+ @nodes_mutex.synchronize do
160
+ while !@number_of_nodes
161
+ # @number_of_nodes_cv.wait(@number_of_nodes_mutex)
162
+ @nodes_cv.wait(@nodes_mutex)
163
+ end
164
+ @number_of_nodes
165
+ end
166
+ end
167
+
168
+ #
169
+ # Njob creation methods
170
+ #
171
+ def start_create_nodes
172
+ @create_node_thread = Thread.start{
173
+ Log::debug self, "START_CREATE_NODES: START #{self}"
174
+ create_nodes
175
+ Log::debug self, "START_CREATE_NODES: END #{self}"
176
+ }
177
+ nil
178
+ end
179
+
180
+ def create_nodes
181
+ begin
182
+ no = 0
183
+ ret = nil
184
+ @controller.assign_ntasks(self, @create_node_mutex) do
185
+ |ntask, mapper, opts={}|
186
+ njob = create_and_add_node(ntask, mapper, opts)
187
+ no += 1
188
+ njob
189
+ end
190
+ add_node(nil)
191
+ Log::debug self, "CREATE_NODES: #{self}.number_of_nodes=#{no}"
192
+ self.number_of_nodes = no
193
+
194
+ rescue BreakCreateNode
195
+ Log::debug self, "BREAK CREATE NODE: #{self}"
196
+ add_node(nil)
197
+ Log::debug self, "CREATE_NODES: #{self}.number_of_nodes=#{no}"
198
+ self.number_of_nodes = no
199
+
200
+ rescue AbortCreateNode
201
+ Log::debug self, "Abort CREATE NODE: #{self}"
202
+ # do nothing
203
+
204
+ rescue ERR::NodeNotArrived
205
+ Log::debug self, "NODE NOT ARRIVED: #{self}"
206
+ begin
207
+ handle_exception($!)
208
+ rescue
209
+ Log::debug_exception(self)
210
+ end
211
+ Log::debug self, "NODE NOT ARRIVED2: #{self}"
212
+ raise
213
+
214
+ rescue ERR::CantExecSubcmd
215
+ begin
216
+ handle_exception($!)
217
+ rescue
218
+ Log::debug_exception(self)
219
+ end
220
+ Log::debug self, "CANT EXEC SUBCOMMAND: #{self}"
221
+ raise
222
+
223
+ rescue Exception
224
+ Log::warn_exception(self)
225
+ raise
226
+ # ensure
227
+ # Log::debug self, "CREATE_NODES: #{self}.number_of_nodes=#{no}"
228
+ #add_node(nil)
229
+ #self.number_of_nodes = no
230
+ end
231
+ end
232
+
233
+ def create_and_add_node(ntask, mapper, opts={})
234
+ node = create_node(ntask) {|node|
235
+ if opts[:init_njob]
236
+ opts[:init_njob].call(node)
237
+ end
238
+ mapper.bind_input(node)
239
+ }
240
+ node
241
+ end
242
+
243
+ def create_node(ntask, *params, &block)
244
+ if params.empty?
245
+ params = njob_creation_params
246
+ end
247
+ njob = ntask.create_njob(node_class_name, self, @opts, *params)
248
+ block.call(njob)
249
+ add_node(njob)
250
+ njob
251
+ end
252
+
253
+ def node_class_name
254
+ ERR::Raise ERR::INTERNAL::NoRegisterService, self.class
255
+ end
256
+
257
+ def njob_creation_params
258
+ []
259
+ end
260
+
261
+ def assgin_number_of_nodes?
262
+ @number_of_nodes
263
+ end
264
+
265
+
266
+ # def next_filter(mapper)
267
+ # @nodes_mutex.synchronize do
268
+ # ret = nil
269
+ # while !ret
270
+ # while @nodes_for_next_filters.empty?
271
+ # @nodes_cv.wait(@nodes_mutex)
272
+ # end
273
+ # ret = @nodes_for_next_filters.shift
274
+ # Log::debug(self, "NEXT_FILTER: #{ret}")
275
+ # end
276
+ # ret = nil if ret == :NIL
277
+ # ret
278
+ # end
279
+ # end
280
+
281
+ # def next_filter(mapper)
282
+ # @nodes_mutex.synchronize do
283
+ # while @nodes_for_next_filters.empty?
284
+ # @nodes_cv.wait(@nodes_mutex)
285
+ # end
286
+ # @nodes_for_next_filters.shift
287
+ # end
288
+ # end
289
+
290
+ def each_assigned_filter(&block)
291
+ loop do
292
+ input_filter = nil
293
+ @nodes_mutex.synchronize do
294
+ while @nodes_for_next_filters.empty?
295
+ @nodes_cv.wait(@nodes_mutex)
296
+ end
297
+ input_filter = @nodes_for_next_filters.shift
298
+ return unless input_filter
299
+ end
300
+ block.call input_filter
301
+ end
302
+ end
303
+
304
+ def start_export(njob)
305
+ export = njob.start_export
306
+ end
307
+
308
+ def create_import(processor)
309
+ processor.create_import(@opts[:prequeuing_policy])
310
+ end
311
+
312
+ def each_export_by(njob, mapper, &block)
313
+ # block.call njob.export, :foo=>:bar
314
+ block.call njob.export
315
+ end
316
+
317
+ def bind_export(exp, imp)
318
+ imp.no_import = 1
319
+ end
320
+
321
+ #
322
+ # job control
323
+ #
324
+ def break_running(njob = nil)
325
+ break_create_node
326
+
327
+ each_node do |tasklet|
328
+ tasklet.break_running unless tasklet.equal?(njob)
329
+ end
330
+ end
331
+
332
+ def break_create_node
333
+ # 作成中のものは完全に作成させるため
334
+ @controller.create_processor_mutex.synchronize do
335
+ if @create_node_thread && @create_node_thread.alive?
336
+ @create_node_thread.raise BreakCreateNode
337
+ end
338
+ end
339
+ end
340
+
341
+ def abort_create_node
342
+ Log::debug(self, "ABORT_CREATE_NODE: S")
343
+ @controller.create_processor_mutex.synchronize do
344
+ Log::debug(self, "ABORT_CREATE_NODE: 1")
345
+ if @create_node_thread && @create_node_thread.alive?
346
+ Log::debug(self, "ABORT_CREATE_NODE: 2 ")
347
+ @create_node_thread.raise AbortCreateNode
348
+ Log::debug(self, "ABORT_CREATE_NODE: 3")
349
+ end
350
+ Log::debug(self, "ABORT_CREATE_NODE: E")
351
+ end
352
+ end
353
+
354
+ def update_status(node, st)
355
+ @nodes_status_mutex.synchronize do
356
+ @nodes_status[node] = st
357
+ @nodes_status_cv.broadcast
358
+ end
359
+ end
360
+
361
+ def watch_status?
362
+ @@watch_status
363
+ end
364
+
365
+ def start_watch_node_status
366
+ Thread.start do
367
+
368
+ all_finished = false
369
+ while !@number_of_nodes || !all_finished
370
+ @nodes_status_mutex.synchronize do
371
+ @nodes_status_cv.wait(@nodes_status_mutex)
372
+ end
373
+
374
+ all_finished = @number_of_nodes
375
+ Log::info(self) do |sio|
376
+ sio.puts "Status Changed: BEGIN #{self}"
377
+ each_node(:exist_only) do |node|
378
+ st = @nodes_status[node]
379
+ sio.puts " node: #{node} status: #{st.id2name}" if st
380
+ all_finished &&= st==:ST_FINISH
381
+ end
382
+ sio.puts "Status Changed: END #{self}"
383
+ end
384
+ end
385
+ Log::info self, "Monitoring finish: ALL NJOB finished"
386
+ end
387
+ nil
388
+ end
389
+
390
+ def handle_exception(exp)
391
+ @controller.handle_exception(exp)
392
+ end
393
+
394
+ class Context
395
+ def initialize(bjob)
396
+ @Pool = bjob.instance_eval{pool_dict}
397
+ @JobPool = bjob.instance_eval{job_pool_dict}
398
+ @__context = context
399
+ end
400
+
401
+ # def create_proc(source)
402
+ # eval("proc{#{source}}", binding)
403
+ # end
404
+
405
+ def context
406
+ __binding
407
+ end
408
+
409
+ class GlobalBreak<Exception;end
410
+ def global_break
411
+ Thread.current.raise GlobalBreak
412
+ end
413
+ alias gbreak global_break
414
+
415
+ alias __binding binding
416
+ def binding
417
+ @__context
418
+ end
419
+ alias bind binding
420
+ end
421
+ end
422
+ end