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,252 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "fairy/node/p-io-filter"
7
+
8
+ module Fairy
9
+ class PBasicGroupBy<PIOFilter
10
+ Processor.def_export self
11
+
12
+ ST_ALL_IMPORTED = :ST_ALL_IMPORTED
13
+ ST_WAIT_EXPORT_FINISH = :ST_WAIT_EXPORT_FINISH
14
+ ST_EXPORT_FINISH = :ST_EXPORT_FINISH
15
+
16
+ def initialize(id, ntask, bjob, opts, block_source)
17
+ super
18
+ @block_source = block_source
19
+
20
+ @exports = {}
21
+ @exports_queue = Queue.new
22
+
23
+ @counter = {}
24
+
25
+ #start_watch_exports
26
+ end
27
+
28
+ def add_export(key, export)
29
+ @exports[key] = export
30
+ # @exports_queue.push [key, export]
31
+ # [BUG#171]同期処理でないとまずい.
32
+ @bjob.add_exports(key, export, self)
33
+ end
34
+
35
+ def start_export
36
+ Log::debug(self, "START_EXPORT")
37
+
38
+ start do
39
+ hash_opt = @opts[:grouping_optimize]
40
+ hash_opt = CONF.GROUP_BY_GROUPING_OPTIMIZE if hash_opt.nil?
41
+
42
+ if hash_opt
43
+ @key_proc = eval("proc{#{@block_source.source}}", @context.binding)
44
+ else
45
+ @key_proc = BBlock.new(@block_source, @context, self)
46
+ end
47
+
48
+ policy = @opts[:postqueuing_policy]
49
+ begin
50
+ @input.each do |e|
51
+ key = hash_key(e)
52
+ if Import::CTLTOKEN_NULLVALUE === key
53
+ next
54
+ end
55
+ export = @exports[key]
56
+ unless export
57
+ export = Export.new(policy)
58
+ export.njob_id = @id
59
+ export.add_key(key)
60
+ add_export(key, export)
61
+ @counter[key] = 0
62
+ end
63
+ export.push e
64
+ @counter[key] += 1
65
+ end
66
+ rescue
67
+ Log::debug_exception(self)
68
+ raise
69
+ ensure
70
+ @exports_queue.push nil
71
+ @exports.each_pair{|key, export|
72
+ Log::debug(self, "G0 #{key} => #{@counter[key]}")
73
+ export.push END_OF_STREAM}
74
+ end
75
+ end
76
+ end
77
+
78
+ def terminate
79
+ @wait_cv = @terminate_mon.new_cv
80
+ wait_export_finish
81
+ super
82
+ end
83
+
84
+ def hash_key(e)
85
+ @key_proc.yield(e)
86
+ end
87
+
88
+ def wait_export_finish
89
+
90
+ Log::debug(self, "G1")
91
+
92
+ self.status = ST_ALL_IMPORTED
93
+
94
+ Log::debug(self, "G2")
95
+ # ここの位置が重要
96
+ self.status = ST_WAIT_EXPORT_FINISH
97
+ # ここもいまいち
98
+ Log::debug(self, "G3")
99
+ @exports.each_pair do |key, export|
100
+ Log::debug(self, "G3.WAIT #{key}")
101
+ export.fib_wait_finish(@wait_cv)
102
+ end
103
+ Log::debug(self, "G4")
104
+ self.status = ST_EXPORT_FINISH
105
+ end
106
+
107
+ end
108
+
109
+ class PBasicMGroupBy<PIOFilter
110
+ Processor.def_export self
111
+
112
+ ST_ALL_IMPORTED = :ST_ALL_IMPORTED
113
+ ST_WAIT_EXPORT_FINISH = :ST_WAIT_EXPORT_FINISH
114
+ ST_EXPORT_FINISH = :ST_EXPORT_FINISH
115
+
116
+ def initialize(id, ntask, bjob, opts, block_source)
117
+ super
118
+ @block_source = block_source
119
+ # @key_proc = eval("proc{#{@block_source}}", TOPLEVEL_BINDING)
120
+ # @key_proc = @context.create_proc(@block_source)
121
+ @key_proc = BBlock.new(@block_source, @context, self)
122
+
123
+ @exports = {}
124
+ @exports_queue = Queue.new
125
+
126
+ # start_watch_exports
127
+ end
128
+
129
+ def add_export(key, export)
130
+ @exports[key] = export
131
+ # @exports_queue.push [key, export]
132
+ # [BUG#171]同期処理でないとまずい.
133
+ @bjob.add_exports(key, export, self)
134
+ end
135
+
136
+ def start_export
137
+ Log::debug(self, "START_EXPORT")
138
+
139
+ start do
140
+ hash_opt = @opts[:grouping_optimize]
141
+ hash_opt = CONF.GROUP_BY_GROUPING_OPTIMIZE if hash_opt.nil?
142
+
143
+ if hash_opt
144
+ @key_proc = eval("proc{#{@block_source.source}}", @context.binding)
145
+ else
146
+ @key_proc = BBlock.new(@block_source, @context, self)
147
+ end
148
+
149
+ policy = @opts[:postqueuing_policy]
150
+ begin
151
+ @input.each do |e|
152
+ keys = @key_proc.yield(e)
153
+ keys = [keys] unless keys.kind_of?(Array)
154
+
155
+ for key in keys
156
+ if Import::CTLTOKEN_NULLVALUE === key
157
+ next
158
+ end
159
+ export = @exports[key]
160
+ unless export
161
+ export = Export.new(policy)
162
+ export.njob_id = @id
163
+ export.add_key(key)
164
+ add_export(key, export)
165
+ end
166
+ export.push e
167
+ end
168
+ end
169
+ rescue
170
+ Log::debug_exception(self)
171
+ raise
172
+ ensure
173
+ @exports_queue.push nil
174
+ @exports.each_pair do |key, export|
175
+ next unless export
176
+ export.push END_OF_STREAM
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ def terminate
183
+ @wait_cv = @terminate_mon.new_cv
184
+ wait_export_finish
185
+ super
186
+ end
187
+
188
+
189
+ # def start
190
+ # super do
191
+ # policy = @opts[:postqueuing_policy]
192
+ # @import.each do |e|
193
+ # keys = @key_proc.yield(e)
194
+ # keys = [keys] unless keys.kind_of?(Array)
195
+
196
+ # for key in keys
197
+ # export = @exports[key]
198
+ # unless export
199
+ # export = Export.new(policy)
200
+ # export.add_key(key)
201
+ # add_export(key, export)
202
+ # end
203
+ # export.push e
204
+ # end
205
+ # end
206
+ # @exports.each{|key, export| export.push END_OF_STREAM}
207
+ # wait_export_finish
208
+ # end
209
+ # end
210
+
211
+ def wait_export_finish
212
+
213
+ Log::debug(self, "G1")
214
+ self.status = ST_ALL_IMPORTED
215
+
216
+ Log::debug(self, "G2")
217
+ # すべての, exportのoutputが設定されるまで待っている
218
+ # かなりイマイチ
219
+ # for key, export in @exports
220
+ # export.output
221
+ # end
222
+
223
+ # ここの位置が重要
224
+ self.status = ST_WAIT_EXPORT_FINISH
225
+ # ここもいまいち
226
+ Log::debug(self, "G3")
227
+ @exports.each_pair do |key, export|
228
+ next unless export
229
+ Log::debug(self, "G4.WAIT #{key}")
230
+ export.fib_wait_finish(@wait_cv)
231
+ end
232
+ Log::debug(self, "G5")
233
+ self.status = ST_EXPORT_FINISH
234
+ end
235
+
236
+ # def start_watch_exports
237
+ # Thread.start do
238
+ # loop do
239
+ # key, export = @exports_queue.pop
240
+ # notice_exports(key, export)
241
+ # end
242
+ # end
243
+ # nil
244
+ # end
245
+
246
+ # def notice_exports(key, export)
247
+ # @bjob.update_exports(key, export, self)
248
+ # end
249
+ end
250
+ end
251
+
252
+
@@ -0,0 +1,153 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "fairy/node/p-io-filter"
7
+ require "fairy/node/p-single-exportable"
8
+
9
+ module Fairy
10
+ module PDirectProduct
11
+ class PPreFilter<PIOFilter
12
+ Processor.def_export self
13
+
14
+ def initialize(id, ntask, bjob, opts, block_source)
15
+ super
16
+ @block_source = block_source
17
+
18
+ @exports = nil
19
+ @exports_mutex = Mutex.new
20
+ @exports_cv = ConditionVariable.new
21
+ end
22
+
23
+ def input=(input)
24
+ super
25
+ start_watch_exports
26
+ end
27
+
28
+ # def number_of_exports=(n)
29
+ # @exports_mutex.synchronize do
30
+ # @exports = []
31
+ # n.times{@exports.push Export.new}
32
+ # end
33
+ # @exports_cv.broadcast
34
+ # end
35
+
36
+ def start_watch_exports
37
+ Thread.start do
38
+ n = @bjob.number_of_exports
39
+ @exports_mutex.synchronize do
40
+ @exports = []
41
+ n.times do
42
+
43
+ # 後で検討する
44
+ # policy = @opts[:postqueuing_policy]
45
+ # exp = Export.new(policy)
46
+ exp = Export.new
47
+ exp.njob_id = @id
48
+ exp.no = @input.no
49
+ exp.add_key(@input.key)
50
+ exp.output_no_import = 1
51
+ @exports.push exp
52
+ end
53
+ end
54
+ @exports_cv.broadcast
55
+ end
56
+ end
57
+
58
+ def exports
59
+ @exports_mutex.synchronize do
60
+ while @exports.nil?
61
+ @exports_cv.wait(@exports_mutex)
62
+ end
63
+ end
64
+ @exports
65
+ end
66
+
67
+ def start_export
68
+ start do
69
+ begin
70
+ @input.each do |e|
71
+ exports.each{|exp| exp.push e}
72
+ end
73
+ ensure
74
+ exports.each{|exp| exp.push :END_OF_STREAM}
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ class PPostFilter<PSingleExportFilter
81
+ Processor.def_export self
82
+
83
+ def initialize(id, processor, bjob, opts, block_source)
84
+ super
85
+ @block_source = block_source
86
+
87
+ @other_imports = nil
88
+ @other_imports_mutex = Mutex.new
89
+ @other_imports_cv = ConditionVariable.new
90
+ end
91
+
92
+ def input=(input)
93
+ @input = input
94
+ # self.no = input.no
95
+ self.key = input.key
96
+ end
97
+
98
+ def other_inputs=(exports)
99
+ @other_imports_mutex.synchronize do
100
+ @other_imports = exports.collect{|exp|
101
+ # 後で検討する
102
+ # policy = @opts[:prequeuing_policy]
103
+ # imp = Import.new(policy)
104
+ imp = Import.new
105
+ imp.no = exp.no
106
+ imp.add_key(exp.key)
107
+ imp.no_import = 1
108
+ imp.set_log_callback do |n, key|
109
+ Log::verbose(self, "IMPORT POP key=#{key}: #{n}")
110
+ end
111
+
112
+ exp.output = imp
113
+ imp
114
+ }
115
+ @other_imports_cv.broadcast
116
+ end
117
+ end
118
+
119
+ def other_imports
120
+ @other_imports_mutex.synchronize do
121
+ while !@other_imports
122
+ @other_imports_cv.wait(@other_imports_mutex)
123
+ end
124
+ @other_imports
125
+ end
126
+ end
127
+
128
+ def basic_each(&block)
129
+ @map_proc = BBlock.new(@block_source, @context, self)
130
+
131
+ elements = []
132
+ elements.push @input.to_a
133
+ elements.push *other_imports.collect{|i| i.to_a}
134
+
135
+ idxs = elements.collect{|e| 0}
136
+ max_idxs = elements.collect{|e| e.size}
137
+
138
+ cont = true
139
+ while cont
140
+ e = elements.zip(idxs).collect{|ary, idx| ary[idx]}
141
+ block.call @map_proc.yield *e
142
+
143
+ (idxs.size-1).downto(0) do |idx|
144
+ idxs[idx] += 1
145
+ break if idxs[idx] < max_idxs[idx]
146
+ idxs[idx] = 0
147
+ cont = false if idx == 0 && idxs[idx] == 0
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "fairy/node/p-filter"
7
+ require "fairy/node/p-single-exportable"
8
+
9
+ module Fairy
10
+ class PExec<PSingleExportInput
11
+ Processor.def_export self
12
+
13
+ def initialize(id, ntask, bjob, opts=nil)
14
+ super
15
+ end
16
+
17
+ def start(nfileplace)
18
+ @nfileplace = nfileplace
19
+ self.no = nfileplace.no
20
+ self
21
+ end
22
+ alias open start
23
+ DeepConnect::def_method_spec(self, "REF start(VAL)")
24
+ DeepConnect::def_method_spec(self, "REF open(VAL)")
25
+
26
+ def basic_each(&block)
27
+ block.call @nfileplace.url
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,363 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "thread"
7
+
8
+ require "fairy/node/p-task"
9
+
10
+ require "fairy/share/block-source"
11
+ require "fairy/share/port"
12
+
13
+ module Fairy
14
+
15
+ class PFilter
16
+ Processor.def_export self
17
+
18
+ END_OF_STREAM = :END_OF_STREAM
19
+
20
+ ST_INIT = :ST_INIT
21
+ ST_ACTIVATE = :ST_ACTIVATE
22
+ ST_FINISH = :ST_FINISH
23
+
24
+ DeepConnect.def_single_method_spec(self, "REF new(DEFAULT, REF, REF, VAL, *DEFAULT)")
25
+
26
+ def initialize(id, ntask, bjob, opts={}, *rests)
27
+ @id = id
28
+ @log_id = format("%s[%s]", self.class.name.sub(/Fairy::/, ''), @id)
29
+
30
+ Log::info self, "CREATE NJOB: #{self.class}"
31
+ @ntask = ntask
32
+ @bjob = bjob
33
+ @opts = opts
34
+
35
+ @IGNORE_EXCEPTION = CONF.IGNORE_EXCEPTION_ON_FILTER
36
+ @IGNORE_EXCEPTION = @opts[:ignore_exception] if @opts.key?(:ignore_exception)
37
+
38
+ @main_thread = nil
39
+
40
+ @context = Context.new(self)
41
+ # @begin_block = nil
42
+ # if @opts[:BEGIN]
43
+ # @begin_block = BBlock.new(@opts[:BEGIN], @context, self)
44
+ # end
45
+ # @end_block = nil
46
+ # if @opts[:END]
47
+ # @end_block = BBlock.new(@opts[:END], @context, self)
48
+ # end
49
+
50
+ @begin_block_source = nil
51
+ if @opts[:BEGIN]
52
+ @begin_block_source = @opts[:BEGIN]
53
+ @begin_block_exec_p = false
54
+ end
55
+ @end_block_source = nil
56
+ if @opts[:END]
57
+ @end_block_source = @opts[:END]
58
+ end
59
+
60
+ @no = nil
61
+ @no_mutex = Mutex.new
62
+ @no_cv = ConditionVariable.new
63
+
64
+ @key = nil
65
+ @key_mutex = Mutex.new
66
+ @key_cv = ConditionVariable.new
67
+
68
+ @status = ST_INIT
69
+ @status_mon = processor.njob_mon
70
+ @status_cv = @status_mon.new_cv
71
+ notice_status(@status)
72
+
73
+ @terminate_mon = processor.njob_mon
74
+
75
+ @in_each = nil
76
+ @in_each_mutex = Mutex.new
77
+
78
+ # start_watch_status
79
+ end
80
+
81
+ attr_reader :id
82
+ attr_reader :log_id
83
+
84
+ attr_reader :IGNORE_EXCEPTION
85
+
86
+ attr_reader :ntask
87
+ def processor
88
+ @ntask.processor
89
+ end
90
+
91
+ def no
92
+ #Log::debug(self, "XXXXXXXXXXXXXXXXXXXXXXXX")
93
+ #Log::debug_backtrace
94
+ @no_mutex.synchronize do
95
+ while !@no
96
+ @no_cv.wait(@no_mutex)
97
+ end
98
+ @no
99
+ end
100
+ end
101
+
102
+ def no=(no)
103
+ @no_mutex.synchronize do
104
+ @no = no
105
+ @no_cv.broadcast
106
+ @no
107
+ end
108
+ end
109
+
110
+ def key
111
+ # @key_mutex.synchronize do
112
+ # while !@key
113
+ # @key_cv.wait(@key_mutex)
114
+ # end
115
+ # @key
116
+ # end
117
+ @key
118
+ end
119
+
120
+ def key=(key)
121
+ # @key_mutex.synchronize do
122
+ # @key = key
123
+ # @key_cv.broadcast
124
+ # @key
125
+ # end
126
+ @key=key
127
+ end
128
+
129
+ def start_export
130
+ ERR::Raise ERR::INTERNAL::ShouldDefineSubclass
131
+ end
132
+
133
+ def start(&block)
134
+ Log::info self, "START PROCESSING: #{self.class}"
135
+
136
+ start_watch_status
137
+
138
+ @main_thread = Thread.start{
139
+ begin
140
+ self.status = ST_ACTIVATE
141
+ if @begin_block_source
142
+ bsource = BSource.new(@begin_block_source, @context, self)
143
+ bsource.evaluate
144
+ end
145
+ begin
146
+ basic_start &block
147
+ ensure
148
+ if @end_block_source
149
+ bsource = BSource.new(@end_block_source, @context, self)
150
+ bsource.evaluate
151
+ end
152
+
153
+ @main_thread = nil
154
+ @terminate_mon.entry terminate_proc
155
+ Log::info self, "FINISH PROCESSING: #{self.class}"
156
+ end
157
+ rescue Exception
158
+ Log::error_exception(self)
159
+ handle_exception($!)
160
+ raise
161
+ end
162
+ }
163
+ nil
164
+ end
165
+
166
+ def terminate_proc
167
+ proc{|*dummy| terminate}
168
+ end
169
+
170
+ def terminate
171
+ self.status = ST_FINISH
172
+ end
173
+
174
+ def basic_start(&block)
175
+ block.call
176
+ end
177
+
178
+ def each(&block)
179
+ begin
180
+ @in_each = true
181
+
182
+ if @begin_block_source
183
+ bsource = BSource.new(@begin_block_source, @context, self)
184
+ bsource.evaluate
185
+ @begin_block_exec_p = true
186
+ end
187
+ begin
188
+ basic_each do |e|
189
+ case e
190
+ when Import::CTLTOKEN_NULLVALUE
191
+ next
192
+ else
193
+ begin
194
+ block.call e
195
+ rescue
196
+ if @IGNORE_EXCEPTION
197
+ Log::warn(self, "IGNORE_EXCEPTON!!")
198
+ Log::warn(self, "Entity: #{e.inspect}")
199
+ Log::error_exception(self)
200
+ next
201
+ else
202
+ raise
203
+ end
204
+ end
205
+ end
206
+ end
207
+ ensure
208
+ if @end_block_source
209
+ bsource = BSource.new(@end_block_source, @context, self)
210
+ bsource.evaluate
211
+ end
212
+ end
213
+ rescue @context.class::GlobalBreakFromOther
214
+ Log::debug(self, "CAUGHT GlobalBreak From Other")
215
+ global_break_from_other
216
+
217
+ rescue LocalJumpError, @context.class::GlobalBreak
218
+ Log::debug(self, "CAUGHT GlobalBreak")
219
+ global_break
220
+
221
+ rescue Exception
222
+ Log::error_exception(self)
223
+ handle_exception($!)
224
+ raise
225
+ ensure
226
+ @in_each = false
227
+ end
228
+ nil
229
+ end
230
+
231
+ def next
232
+ if @begin_block_source && @begin_block_exec_p
233
+ bsource = BSource.new(@begin_block_source, @context, self)
234
+ bsource.evaluate
235
+ @begin_block_exec_p = true
236
+ end
237
+ begin
238
+ ret = basic_next
239
+ ensure
240
+ if ret == :END_OF_STREAM
241
+ if @end_block_source
242
+ bsource = BSource.new(@end_block_source, @context, self)
243
+ bsource.evaluate
244
+ end
245
+ end
246
+ end
247
+ end
248
+
249
+ def global_break
250
+ Thread.start{@bjob.break_running(self)}
251
+ # Thread.current.exit
252
+ self.status = ST_FINISH
253
+ # 他のスレッドはとめていない
254
+ end
255
+
256
+ def global_break_from_other
257
+ self.status = ST_FINISH
258
+ end
259
+
260
+ def break_running
261
+ if @in_each
262
+ @main_thread.raise @context.class::GlobalBreakFromOther
263
+ # @main_thread.exit if @main_thread
264
+ self.status = ST_FINISH
265
+ end
266
+ # 他のスレッドはとめていない
267
+ end
268
+
269
+ def abort_running
270
+ @main_thread.exit if @main_thread
271
+ end
272
+
273
+ def status=(val)
274
+ #Log::debugf(self, "STATUS_CHANGE: %s", val)
275
+ @status_mon.synchronize do
276
+ @status = val
277
+ @status_cv.broadcast
278
+ end
279
+ end
280
+
281
+ def start_watch_status
282
+ # 初期状態通知
283
+ notice_status(@status)
284
+
285
+ @status_mon.entry do
286
+ @status_mon.synchronize do
287
+ old_status = nil
288
+ loop do
289
+ @status_cv.wait_while{old_status == @status}
290
+ old_status = @status
291
+ notice_status(@status)
292
+ break if @status == ST_FINISH
293
+ end
294
+ end
295
+ end
296
+ nil
297
+ end
298
+
299
+ def notice_status(st)
300
+ @status_mon.entry do
301
+ @bjob.update_status(self, st)
302
+ @ntask.update_status(self, st)
303
+ end
304
+ end
305
+
306
+ # # block create
307
+ # def create_block(source)
308
+ # unless Fairy.const_defined?(:Pool)
309
+ # pool_dict = @bjob.pool_dict
310
+ # Fairy.const_set(:Pool, pool_dict)
311
+ # end
312
+ # eval("def Pool = Fairy::Pool", TOPLEVEL_BINDING)
313
+
314
+ # binding = eval("def fairy_binding; binding; end; fairy_binding",
315
+ # TOPLEVEL_BINDING,
316
+ # __FILE__,
317
+ # __LINE__ - 3)
318
+ # end
319
+
320
+ def handle_exception(exp)
321
+ @bjob.handle_exception(exp)
322
+ end
323
+
324
+ class Context
325
+ def initialize(njob)
326
+ @Pool = njob.instance_eval{@bjob.pool_dict}
327
+ #Log::debug(self, @Pool.peer_inspect)
328
+ @JobPool = njob.instance_eval{@bjob.job_pool_dict}
329
+ # @Import = njob.instance_eval{@import}
330
+ # @Export = njob.instance_eval{@export}
331
+ @__context = context
332
+
333
+ @IGNORE_EXCEPTION = njob.IGNORE_EXCEPTION
334
+
335
+ # Log::debugf(self, "CONTEXT: %s", eval("@Pool", self.binding))
336
+ end
337
+
338
+ attr_reader :IGNORE_EXCEPTION
339
+
340
+ def context
341
+ __binding
342
+ end
343
+
344
+ class GlobalBreak<Exception;end
345
+ class GlobalBreakFromOther<Exception;end
346
+ # class LocalBreak<Exception;end
347
+ def global_break
348
+ Thread.current.raise GlobalBreak
349
+ end
350
+ alias gbreak global_break
351
+
352
+ # def local_break
353
+ # Thread.current.raise LocalBreak
354
+ # end
355
+
356
+ alias __binding binding
357
+ def binding
358
+ @__context
359
+ end
360
+ alias bind binding
361
+ end
362
+ end
363
+ end