fairy 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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