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,47 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "fairy/client/filter"
7
+
8
+ module Fairy
9
+ class There < Filter
10
+ module Interface
11
+
12
+ # Usage:
13
+ # ○ fairy.there(enumeratable)....
14
+ # ○ enumerable.there(fairy)....
15
+ # enumerable | fairy.there
16
+ def there(enumerable = nil, opts={})
17
+ There.input(self, opts, enumerable)
18
+ end
19
+ end
20
+ Fairy::def_fairy_interface Interface
21
+
22
+ Enumerable.module_eval %{def there(fairy); fairy.there(self); end}
23
+
24
+ def self.input(fairy, opts, enumerable)
25
+ self.start(fairy, opts, enumerable)
26
+ end
27
+
28
+ def self.start(fairy, opts, enumerable)
29
+ there = new(fairy, opts, enumerable)
30
+ there.start
31
+ there
32
+ end
33
+
34
+ def initialize(fairy, opts, enumerable)
35
+ super
36
+ @enumerable = enumerable
37
+ end
38
+
39
+ def backend_class_name
40
+ "CThere"
41
+ end
42
+
43
+ def start
44
+ backend.start
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require 'rbconfig'
7
+
8
+ module Fairy
9
+ module TopNIntoRomaInterface
10
+ def top_n_into_roma(ap, key, n, sep=',')
11
+ ap = [ap] if ap.kind_of?(String)
12
+
13
+ buf = []
14
+ cnt = 0
15
+ if Config::CONFIG['RUBY_INSTALL_NAME'] =~ /jruby/
16
+ here.each{|s|
17
+ cnt += 1
18
+ buf << s if cnt <= n
19
+ }
20
+ else
21
+ here.each{|s|
22
+ cnt += 1
23
+ buf << s
24
+ break if cnt == n
25
+ }
26
+ end
27
+ roma = Roma::Client::RomaClient.new(ap)
28
+ roma[key] = buf.join(sep)
29
+ end
30
+ end
31
+ def_filter_interface TopNIntoRomaInterface
32
+ end
33
+
34
+
@@ -0,0 +1,92 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "fairy/client/io-filter"
7
+
8
+ module Fairy
9
+ class WC<IOFilter
10
+ module Interface
11
+ def wc(from_desc, to_desc, opts = {})
12
+ wc = WC.open(self, opts, from_desc)
13
+ wc.post_wc(to_desc, opts)
14
+ end
15
+ end
16
+ Fairy::def_fairy_interface Interface
17
+
18
+ def self.open(fairy, opts, from_desc)
19
+ wc = new(fairy, opts)
20
+ wc.open(from_desc)
21
+ wc
22
+ end
23
+
24
+ def initialize(fairy, opts=nil)
25
+ super
26
+ end
27
+
28
+ def backend_class_name
29
+ "CWC"
30
+ end
31
+
32
+ def open(from_desc)
33
+ @descripter = from_desc
34
+
35
+ case from_desc
36
+ when Array
37
+ vf = VFile.real_files(from_desc)
38
+ when VFile
39
+ vf = from_desc
40
+ when String
41
+ if VFile.vfile?(from_desc)
42
+ vf = VFile.vfile(from_desc)
43
+ else
44
+ vf = VFile.real_files([from_desc])
45
+ end
46
+ else
47
+ ERR::Raise ERR::IllegalVFile
48
+ end
49
+ backend.open(vf)
50
+ self
51
+ end
52
+
53
+ class PostFilter<IOFilter
54
+ module Interface
55
+ def post_wc(to_desc, opts = nil)
56
+ post_wc = PostFilter.new(@fairy, opts)
57
+ post_wc.output(to_desc)
58
+ post_wc.input = self
59
+ post_wc
60
+ end
61
+ Fairy::def_filter_interface Interface
62
+ end
63
+
64
+ def initialize(fairy, opts = nil)
65
+ super
66
+ @to_desc = nil
67
+ end
68
+
69
+ def backend_class_name
70
+ "CWC::CPostFilter"
71
+ end
72
+
73
+ def output(vfn)
74
+ @descripter = vfn
75
+ @vfile = VFile.new
76
+ @vfile.vfile_name = vfn
77
+ backend.output(@vfile)
78
+ end
79
+
80
+ def input=(job)
81
+ @input = job
82
+ backend.input=job.backend
83
+
84
+ backend.wait_all_output_finished
85
+ @vfile.create_vfile
86
+ end
87
+
88
+ end
89
+ end
90
+ end
91
+
92
+
@@ -0,0 +1,1103 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "thread"
7
+ require "forwardable"
8
+
9
+ require "deep-connect.rb"
10
+
11
+ require "fairy/version"
12
+ require "fairy/share/conf"
13
+ require "fairy/share/pool-dictionary"
14
+ require "fairy/share/stdout"
15
+
16
+ module Fairy
17
+
18
+ class Controller
19
+
20
+ EXPORTS = []
21
+ def Controller.def_export(obj, name = nil)
22
+ unless name
23
+ if obj.kind_of?(Class)
24
+ if /Fairy::(.*)$/ =~ obj.name
25
+ name = $1
26
+ else
27
+ name = obj.name
28
+ end
29
+ else
30
+ ERR::Raise ERR::INTERNAL::CantDefExport, obj.to_s
31
+ end
32
+ end
33
+
34
+ EXPORTS.push [name, obj]
35
+ end
36
+
37
+ def Controller.start(id, master_port)
38
+ controller = Controller.new(id)
39
+ controller.start(master_port)
40
+ end
41
+
42
+ def initialize(id)
43
+ @id = id
44
+
45
+ @deepconnect = nil
46
+
47
+ @master_deepspace = nil
48
+ @master = nil
49
+
50
+ @client = nil
51
+
52
+ @stdout_mutex = Mutex.new
53
+
54
+ @services = {}
55
+
56
+ @create_processor_mutex = Mutex.new
57
+
58
+ # processor -> no of reserve
59
+ @reserves = {}
60
+ @reserves_mutex = Mutex.new
61
+ @reserves_cv = ConditionVariable.new
62
+
63
+ # bjob -> [processor, ...]
64
+ @bjob2processors = {}
65
+ @bjob2processors_mutex = Mutex.new
66
+ @bjob2processors_cv = ConditionVariable.new
67
+
68
+ # processor -> no of active ntasks
69
+ @no_active_ntasks = {}
70
+ @no_active_ntasks_mutex = Mutex.new
71
+ @no_active_ntasks_cv = ConditionVariable.new
72
+
73
+ @pool_dict = PoolDictionary.new
74
+ end
75
+
76
+ attr_reader :id
77
+ attr_reader :create_processor_mutex
78
+
79
+ attr_reader :hash_seed
80
+
81
+ def log_id
82
+ "Controller[#{id}]"
83
+ end
84
+
85
+ def start(master_port, service=0)
86
+ @deepconnect = DeepConnect.start(service)
87
+ @deepconnect.export("Controller", self)
88
+
89
+ @deepconnect.when_disconnected do |deepspace, opts|
90
+ when_disconnected(deepspace, opts)
91
+ end
92
+
93
+ for name, obj in EXPORTS
94
+ export(name, obj)
95
+ end
96
+
97
+ require "fairy/share/inspector"
98
+ @deepconnect.export("Inspector", Inspector.new(self))
99
+
100
+ require "fairy/share/log"
101
+ @master_deepspace = @deepconnect.open_deepspace("localhost", master_port)
102
+ @master = @master_deepspace.import("Master")
103
+ @logger = @master.logger
104
+ Log.type = "[C]"
105
+ Log.pid = id
106
+ Log.logger = @logger
107
+ Log::info(self, "Controller Service Start")
108
+ Log::info(self, "\tfairy version: #{Version}")
109
+ Log::info(self, "\t[Powered by #{RUBY_DESCRIPTION}")
110
+
111
+ @master.register_controller(self)
112
+
113
+ end
114
+
115
+ def connect(client, conf)
116
+ @client = client
117
+
118
+ conf.base_conf = CONF
119
+ Fairy::REPLACE_CONF(conf)
120
+
121
+ mod = CONF.GROUP_BY_HASH_MODULE
122
+ require mod
123
+ @hash_seed = Fairy::HValueGenerator.create_seed
124
+ def_pool_variable(:HASH_SEED, @hash_seed)
125
+
126
+ @PROCESS_LIFE_MANAGE_INTERVAL = CONF.PROCESS_LIFE_MANAGE_INTERVAL
127
+
128
+ if @PROCESS_LIFE_MANAGE_INTERVAL
129
+ Thread.start do
130
+ start_process_life_manage
131
+ end
132
+ nil
133
+ end
134
+
135
+ $stdout = Stdout.new(@client)
136
+
137
+ end
138
+ DeepConnect.def_method_spec(self, "REF connext(REF, DVAL)")
139
+
140
+ def terminate
141
+ # clientが終了したときの終了処理
142
+ # master から呼ばれる
143
+
144
+ Log::debug(self, "TERMINATE: #1")
145
+ # デッドロックするのでNG
146
+ # @reserves_mutex.synchronize do
147
+ @bjob2processors.keys.each do |bjob|
148
+ begin
149
+ Log::debug(self, "TERMINATE: #1.1")
150
+ bjob.abort_create_node
151
+ rescue
152
+ Log::debug(self, "TERMINATE: #1.1.1")
153
+ Log::debug_exception($!)
154
+ end
155
+ end
156
+ # end
157
+
158
+ Log::debug(self, "TERMINATE: #2")
159
+ cond = true
160
+ while cond
161
+ Log::debug(self, "TERMINATE: #2.1")
162
+ @reserves_mutex.synchronize do
163
+ Log::debug(self, "TERMINATE: #2.2")
164
+ cond = false if @reserves.empty?
165
+ @reserves.keys.each do |p|
166
+ Log::debug(self, "TERMINATE: #2.3")
167
+ if @reserves[p] == 0
168
+ Log::debug(self, "TERMINATE: #2.4")
169
+ begin
170
+ p.terminate_all_ntasks
171
+ rescue
172
+ Log::debug(self, "TERMINATE: #2.4.1")
173
+ Log::debug_exception($!)
174
+ end
175
+ Log::debug(self, "TERMINATE: #2.5")
176
+ begin
177
+ @reserves.delete(p)
178
+ rescue
179
+ Log::debug(self, "TERMINATE: #2.5.1")
180
+ Log::debug_exception($!)
181
+ end
182
+ Log::debug(self, "TERMINATE: #2.5.1")
183
+ begin
184
+ Log::debug(self, "TERMINATE: #2.5.2")
185
+ p.node.terminate_processor(p)
186
+ Log::debug(self, "TERMINATE: #2.5.3")
187
+ rescue
188
+ Log::debug(self, "TERMINATE: #2.5.4")
189
+ Log::debug_exception($!)
190
+ end
191
+ Log::debug(self, "TERMINATE: #2.6")
192
+ end
193
+ end
194
+ Log::debug(self, "TERMINATE: #2.7")
195
+ end
196
+ Log::debug(self, "TERMINATE: #2.8")
197
+ end
198
+
199
+ Log::debug(self, "TERMINATE: #3")
200
+ @reserves.keys.each do |p|
201
+ begin
202
+ p.node.terminate_processor(p)
203
+ rescue
204
+ # p $!, $@
205
+ end
206
+ end
207
+
208
+ Log::debug(self, "TERMINATE: #4")
209
+ Thread.start do
210
+ sleep 0.2
211
+ begin
212
+ @deepconnect.stop
213
+ ensure
214
+ Process.exit!(0)
215
+ end
216
+ end
217
+ Log::debug(self, "TERMINATE: #5")
218
+ nil
219
+ end
220
+
221
+ def terminate_rev0
222
+ # clientが終了したときの終了処理
223
+ # master から呼ばれる
224
+
225
+ Log::debug(self, "TERMINATE: #1")
226
+ @reserves_mutex.synchronize do
227
+ @bjob2processors.keys.each do |bjob|
228
+ bjob.abort_create_node
229
+ end
230
+ end
231
+
232
+ Log::debug(self, "TERMINATE: #2")
233
+ @reserves.keys.each do |p|
234
+ begin
235
+ Log::debug(self, "TERMINATE: #2.1")
236
+ p.terminate_all_njobs
237
+ Log::debug(self, "TERMINATE: #2.2")
238
+ rescue
239
+ LOG::debug_exception(self)
240
+ end
241
+ end
242
+
243
+ Log::debug(self, "TERMINATE: #2.5")
244
+ @reserves.keys.each do |p|
245
+ begin
246
+ p.terminate_all_njobs
247
+ rescue
248
+ LOG::debug_exception(self)
249
+ end
250
+ end
251
+
252
+ Log::debug(self, "TERMINATE: #3")
253
+ @reserves.keys.each do |p|
254
+ begin
255
+ p.node.terminate_processor(p)
256
+ rescue
257
+ # p $!, $@
258
+ end
259
+ end
260
+
261
+ Log::debug(self, "TERMINATE: #4")
262
+ Thread.start do
263
+ sleep 0.1
264
+ @deepconnect.stop
265
+ Process.exit(0)
266
+ end
267
+ Log::debug(self, "TERMINATE: #5")
268
+ nil
269
+ end
270
+
271
+ def when_disconnected(deepspace, opts)
272
+ if deepspace == @client.deep_space
273
+ Log::info(self, "CONTROLLER: client disconnected: Start termination")
274
+ # クライアントがおなくなりになったら, こっちも死ぬよ
275
+ @master.terminate_controller(self)
276
+ end
277
+ end
278
+
279
+ #
280
+ # clent interface
281
+ #
282
+ def export(service, obj)
283
+ @services[service] = obj
284
+ end
285
+
286
+ def import(service)
287
+ @services[service]
288
+ end
289
+
290
+ #
291
+ # bjob methods
292
+ #
293
+ def register_bjob(bjob)
294
+ @bjob2processors_mutex.synchronize do
295
+ @bjob2processors[bjob] = []
296
+ end
297
+ end
298
+
299
+ #
300
+ # ntask methods
301
+ #
302
+ def no_active_ntasks_in_processor(processor)
303
+ @no_active_ntasks_mutex.synchronize do
304
+ @no_active_ntasks[processor] || 0
305
+ end
306
+ end
307
+
308
+ def update_active_ntasks(processor, no_active_ntasks)
309
+ Log::debug(self, "Processor[#{processor.id}] => #{no_active_ntasks}")
310
+ @no_active_ntasks_mutex.synchronize do
311
+ @no_active_ntasks[processor] = no_active_ntasks
312
+ @no_active_ntasks_cv.broadcast
313
+ end
314
+ end
315
+
316
+ #
317
+ # processor methods
318
+ #
319
+ # reserve してから njob 割り当てを行う
320
+ def reserve_processor(processor, &block)
321
+ @reserves_mutex.synchronize do
322
+ begin
323
+ return nil unless @reserves[processor]
324
+ rescue DeepConnect::SessionServiceStopped
325
+ # processor は 終了している可能性がある
326
+ return nil
327
+ end
328
+ @reserves[processor] += 1
329
+ end
330
+ begin
331
+ yield processor
332
+ processor
333
+ ensure
334
+ @reserves_mutex.synchronize do
335
+ @reserves[processor] -= 1
336
+ end
337
+ end
338
+ end
339
+
340
+ def create_processor(node, bjob, &block)
341
+ @create_processor_mutex.synchronize do
342
+ processor = node.create_processor
343
+ processor.connect_controller(self, CONF)
344
+ @reserves_mutex.synchronize do
345
+ @reserves[processor] = 1
346
+ end
347
+ begin
348
+ register_processor(bjob, processor)
349
+ yield processor
350
+ processor
351
+ ensure
352
+ @reserves_mutex.synchronize do
353
+ @reserves[processor] -= 1
354
+ end
355
+ end
356
+ end
357
+ end
358
+
359
+ def register_processor(bjob, processor)
360
+ @bjob2processors_mutex.synchronize do
361
+ @bjob2processors[bjob] = [] unless @bjob2processors[bjob]
362
+ unless @bjob2processors[bjob].include?(processor)
363
+ @bjob2processors[bjob].push processor
364
+ end
365
+ @bjob2processors_cv.broadcast
366
+ @no_active_ntasks_cv.broadcast
367
+ end
368
+ processor
369
+ end
370
+
371
+ # def assign_inputtable_processor(bjob, input_bjob, input_njob, input_export, &block)
372
+ # case input_bjob
373
+ # when BGroupBy
374
+ # assign_processor(bjob, :NEW_PROCESSOR_N, input_bjob, &block)
375
+ # # assign_processor(bjob, :NEW_PROCESSOR, &block)
376
+ # # assign_processor(bjob, :SAME_PROCESSOR, input_njob.processor, &block)
377
+ # when BSplitter
378
+ # assign_processor(bjob, :NEW_PROCESSOR, &block)
379
+ # # assign_processor(bjob, :NEW_PROCESSOR_N, input_bjob, &block)
380
+ # # assign_processor(bjob, :SAME_PROCESSOR, input_njob.processor, &block)
381
+ # else
382
+ # assign_processor(bjob, :SAME_PROCESSOR, input_njob.processor, &block)
383
+ # end
384
+ # end
385
+
386
+ # # Processor 関連メソッド
387
+ # # Policy: :SAME_PROCESSOR, :NEW_PROCESSOR, :INPUT, MUST_BE_SAME_PROCESSOR
388
+ # def assign_processor(bjob, policy, *opts, &block)
389
+ # case policy
390
+ # when :INPUT
391
+ # assign_input_processor(bjob, opts[0], &block)
392
+ # when :SAME_PROCESSOR_OBJ
393
+ # assign_same_obj_processor(bjob, opts[0], &block)
394
+ # when :SAME_PROCESSOR, :MUST_BE_SAME_PROCESSOR
395
+ # processor = opts[0]
396
+ # assign_same_processor(bjob, processor, &block)
397
+ # when :NEW_PROCESSOR
398
+ # assign_new_processor(bjob, &block)
399
+ # when :NEW_PROCESSOR_N
400
+ # input_bjob = opts[0]
401
+ # assign_new_processor_n(bjob, input_bjob, &block)
402
+ # else
403
+ # ERR::Raise ERR::INTERNAL::UndefinedPolicy, policy.to_s
404
+ # end
405
+ # end
406
+
407
+ #
408
+ # methods of assgin processor.
409
+ #
410
+ def assign_input_processor(bjob, host, &block)
411
+ node = @master.node_in_reisured(host)
412
+ unless node
413
+ begin
414
+ ERR::Raise ERR::NodeNotArrived, host
415
+ rescue
416
+ handle_exception($!)
417
+ raise AbortCreateNode
418
+ end
419
+ end
420
+ create_processor(node, bjob, &block)
421
+ end
422
+
423
+ def assign_input_processor_n(bjob, host, &block)
424
+ max_no = CONF.CONTROLLER_INPUT_PROCESSOR_N
425
+ max_ntasks = CONF.CONTROLLER_MAX_ACTIVE_TASKS_IN_PROCESSOR
426
+
427
+ loop do
428
+ node = @master.node_in_reisured(host)
429
+ unless node
430
+ begin
431
+ ERR::Raise ERR::NodeNotArrived, host
432
+ rescue
433
+ handle_exception($!)
434
+ raise AbortCreateNode
435
+ end
436
+ end
437
+
438
+ no_of_processors = 0
439
+ leisured_processor = nil
440
+ min = nil
441
+ for processor in @bjob2processors[bjob].dup
442
+ next if processor.node != node
443
+ no_of_processors += 1
444
+
445
+ n = no_active_ntasks_in_processor(processor)
446
+ if !min or min > n
447
+ min = n
448
+ leisured_processor = processor
449
+ end
450
+ end
451
+
452
+ if max_no.nil? || max_no >= no_of_processors
453
+ create_processor(node, bjob, &block)
454
+ return
455
+ elsif min > max_ntasks
456
+ @no_active_ntasks_mutex.synchronize do
457
+ Log::debug(self, "NO_ACTIVE_NTASKS: WAIT")
458
+ @no_active_ntasks_cv.wait(@no_active_ntasks_mutex)
459
+ Log::debug(self, "NO_ACTIVE_NTASKS: WAIT END")
460
+ end
461
+ else
462
+ ret = reserve_processor(leisured_processor) {|processor|
463
+ register_processor(bjob, processor)
464
+ yield processor
465
+ }
466
+ unless ret
467
+ # プロセッサが終了していたとき. もうちょっとどうにかしたい気もする
468
+ assign_new_processor(bjob, &block)
469
+ end
470
+ return
471
+ end
472
+ end
473
+ end
474
+
475
+ # def assign_input_processor_n(bjob, host, &block)
476
+ # Log::debug(self, "HHHHHHHHHHHHHHHHHHHHH: #{host}")
477
+ # no = 0
478
+ # if processors = @bjob2processors[bjob]
479
+ # no += processors.size
480
+ # end
481
+
482
+ # max_no = CONF.CONTROLLER_INPUT_PROCESSOR_N
483
+ # if max_no.nil? || max_no > no
484
+ # node = @master.node_in_reisured(host)
485
+ # ERR::Raise ERR::NodeNotArrived, host unless node
486
+
487
+ # create_processor(node, bjob, &block)
488
+ # else
489
+ # node = @master.node_in_reisured(host)
490
+ # ERR::Raise ERR::NodeNotArrived, host unless node
491
+
492
+ # leisured_processor = nil
493
+ # min = nil
494
+ # for processor in @bjob2processors[bjob].dup
495
+ # next if processor.node != node
496
+
497
+ # n = processor.no_ntasks
498
+ # if !min or min > n
499
+ # min = n
500
+ # leisured_processor = processor
501
+ # end
502
+ # end
503
+ # ret = reserve_processor(leisured_processor) {|processor|
504
+ # register_processor(bjob, processor)
505
+ # yield processor
506
+ # }
507
+ # unless ret
508
+ # # プロセッサが終了していたとき. もうちょっとどうにかしたい気もする
509
+ # assign_new_processor(bjob, &block)
510
+ # end
511
+ # end
512
+ # end
513
+
514
+
515
+ def assign_same_processor(bjob, processor, &block)
516
+ # このメソッドは, 基本的にはreserve しているだけ
517
+ ret = reserve_processor(processor) {|processor|
518
+ register_processor(bjob, processor)
519
+ yield processor
520
+ processor}
521
+
522
+ unless ret
523
+ # プロセッサが終了していたとき(ほとんどあり得ないけど)
524
+ # この時のassgin_processor側の処理がイマイチ
525
+ assign_new_processor(bjob, &block)
526
+ end
527
+ end
528
+
529
+ def assign_same_obj_processor(bjob, obj, &block)
530
+ processor = nil
531
+ @reserves_mutex.synchronize do
532
+ @reserves.each_key do |p|
533
+ if p.deep_space == obj.deep_space
534
+ processor = p
535
+ break
536
+ end
537
+ end
538
+ end
539
+ ERR::Raise ERR::NoExistProcesorWithObject obj.to_s unless processor
540
+
541
+ ret = reserve_processor(processor) {
542
+ register_processor(bjob, processor)
543
+ yield processor
544
+ }
545
+
546
+ ERR::Raise ERR::NoExistProcesorWithObject obj.to_s unless ret
547
+ end
548
+
549
+ def assign_new_processor(bjob, &block)
550
+ node = @master.leisured_node
551
+ create_processor(node, bjob, &block)
552
+ end
553
+
554
+ # まあ, 大体n個になるかなぁ...
555
+ # input_bjobのプロセスも動的に割り当てられるので...
556
+ # 最終的には 大体そうなるということで....
557
+ def assign_new_processor_n(bjob, input_bjob, &block)
558
+
559
+ if input_bjob
560
+ factor = CONF.CONTROLLER_ASSIGN_NEW_PROCESSOR_N_FACTOR
561
+ else
562
+ # ここバグっている? CONTROLLER_INPUT_PROCESSOR_N は1-node辺りの数
563
+ max_no = CONF.CONTROLLER_INPUT_PROCESSOR_N
564
+ end
565
+ max_ntasks = CONF.CONTROLLER_MAX_ACTIVE_TASKS_IN_PROCESSOR
566
+
567
+ loop do
568
+ if input_bjob
569
+ no_i = 0
570
+ @bjob2processors_mutex.synchronize do
571
+ while !@bjob2processors[input_bjob]
572
+ Log::debug(self, "ASSIGN NEW PROCESSOR WAIT: #{bjob.class}")
573
+ @bjob2processors_cv.wait(@bjob2processors_mutex)
574
+ Log::debug(self, "ASSIGN NEW PROCESSOR RESUME: #{bjob.class}")
575
+ end
576
+ if i_processors = @bjob2processors[input_bjob]
577
+ no_i += i_processors.size
578
+ end
579
+ end
580
+ max_no = no_i * factor
581
+ end
582
+
583
+ no = 0
584
+ if processors = @bjob2processors[bjob]
585
+ no += processors.size
586
+ end
587
+
588
+ if max_no > no
589
+ node = @master.leisured_node
590
+ create_processor(node, bjob, &block)
591
+ return
592
+ else
593
+ leisured_processor = nil
594
+ min = nil
595
+ for processor in @bjob2processors[bjob].dup
596
+ # これだと頭から割り当てられる...
597
+ # けど取りあえずということで.
598
+
599
+ n = no_active_ntasks_in_processor(processor)
600
+ if !min or min > n
601
+ min = n
602
+ leisured_processor = processor
603
+ end
604
+ end
605
+
606
+ if min > max_ntasks
607
+ @no_active_ntasks_mutex.synchronize do
608
+ Log::debug(self, "NO_ACTIVE_NTASKS: WAIT")
609
+ @no_active_ntasks_cv.wait(@no_active_ntasks_mutex)
610
+ Log::debug(self, "NO_ACTIVE_NTASKS: WAIT END")
611
+ end
612
+ else
613
+ ret = reserve_processor(leisured_processor) {|processor|
614
+ register_processor(bjob, processor)
615
+ yield processor
616
+ }
617
+ unless ret
618
+ # プロセッサが終了していたとき. もうちょっとどうにかしたい気もする
619
+ assign_new_processor(bjob, &block)
620
+ end
621
+ return
622
+ end
623
+ end
624
+ end
625
+ end
626
+
627
+ def assign_new_processor_n_for_local_io(bjob, &block)
628
+
629
+ nodes = {}
630
+ # for p in @bjob2processors[bjob].dup
631
+ for p in bjob.nodes.collect{|njob| njob.processor}
632
+ if nodes[p.node]
633
+ nodes[p.node].push p
634
+ else
635
+ nodes[p.node] = [p]
636
+ end
637
+ end
638
+
639
+ node = nil
640
+ assign_level = 0
641
+ while !node
642
+ assign_level += 1
643
+ except_nodes = nodes.select{|n, ps| ps.size >= assign_level}
644
+ node = @master.leisured_node_except_nodes(except_nodes, false)
645
+ end
646
+
647
+ max_no = CONF.CONTROLLER_INPUT_PROCESSOR_N
648
+ if nodes[node]
649
+ leisured_processor = nil
650
+ min = nil
651
+ for processor in nodes[node]
652
+ n = processor.no_ntasks
653
+ if !min or min > n
654
+ min = n
655
+ leisured_processor = processor
656
+ end
657
+ end
658
+ no_of_processors = nodes[node].size
659
+ else
660
+ no_of_processors = 0
661
+ end
662
+
663
+ if max_no.nil? || max_no >= no_of_processors
664
+ create_processor(node, bjob, &block)
665
+ else
666
+ ret = reserve_processor(leisured_processor) {|processor|
667
+ register_processor(bjob, processor)
668
+ yield processor
669
+ }
670
+ unless ret
671
+ # プロセッサが終了していたとき. もうちょっとどうにかしたい気もする
672
+ assign_new_processor(bjob, &block)
673
+ end
674
+ end
675
+ end
676
+
677
+ def terminate_processor
678
+ deresister_processor(processor)
679
+ @master.deregister_processor(processor)
680
+ @node.deregister_processor(processor)
681
+ @node.terminate_processor
682
+ end
683
+
684
+ def start_process_life_manage
685
+ loop do
686
+ sleep PROCESS_LIFE_MANAGE_INTERVAL
687
+ Log::debug(self, "START_PROCESS_LIFE_MANAGE: S")
688
+ processors = @reserves_mutex.synchronize{@reserves.keys}
689
+ for p in processors
690
+ Log::debugf(self, "START_PROCESS_LIFE_MANAGE: 1 %{p}")
691
+ kill = false
692
+ @reserves_mutex.synchronize do
693
+ # for q, r in @reserves
694
+ # puts "#{q.id} =>#{r}"
695
+ # end
696
+ Log::debug(self, "START_PROCESS_LIFE_MANAGE: 2 ")
697
+ if @reserves[p] == 0 && p.life_out_life_span?
698
+ Log::info self, "Kill #{p.inspectx}"
699
+ kill = true
700
+ @reserves.delete(p)
701
+ @bjob2processors_mutex.synchronize do
702
+ # @bjob2processors から p を削除する必要あるか?
703
+ end
704
+ end
705
+ end
706
+ Log::debug(self, "START_PROCESS_LIFE_MANAGE: 3 ")
707
+ if kill
708
+ Log::debug(self, "START_PROCESS_LIFE_MANAGE: 4 ")
709
+ p.node.terminate_processor(p)
710
+ end
711
+ Log::debug(self, "START_PROCESS_LIFE_MANAGE: 5 ")
712
+ end
713
+ Log::debug(self, "START_PROCESS_LIFE_MANAGE: E ")
714
+ end
715
+ end
716
+
717
+ # exception handling
718
+ def handle_exception(exp)
719
+ Thread.start do
720
+ begin
721
+ @client.handle_exception(exp)
722
+ rescue
723
+ end
724
+ end
725
+ nil
726
+ end
727
+
728
+ # stdout
729
+ def stdout_write(str)
730
+ $stdout.replace_stdout do
731
+ $stdout.write(str)
732
+ end
733
+ end
734
+
735
+ # pool variable
736
+ def pool_dict
737
+ @pool_dict
738
+ end
739
+
740
+ def def_pool_variable(vname, value = nil)
741
+ # value が Hash で キー :block をもっていたら block と見なす.
742
+ if value.__deep_connect_reference? && value.kind_of?(Hash) && value[:block]
743
+ p = Context.create_proc(self, value[:block])
744
+ value = p.call
745
+ end
746
+ @pool_dict.def_variable(vname, value)
747
+ end
748
+
749
+ def pool_variable(vname, *value)
750
+ if value.empty?
751
+ @pool_dict[vname]
752
+ else
753
+ @pool_dict[vname] = value.first
754
+ end
755
+ end
756
+
757
+ class Context
758
+ def self.create_proc(controller, source)
759
+ context = new(controller)
760
+ context.create_proc(source)
761
+ end
762
+
763
+ def initialize(controller)
764
+ @Pool = controller.pool_dict
765
+ end
766
+
767
+ def create_proc(source)
768
+ eval("proc{#{source}}", binding)
769
+ end
770
+ end
771
+
772
+ #-- new fairy
773
+
774
+
775
+ # def assign_processor(target_bjob, &block)
776
+ # mapper = NjobMapper.new(self, target_bjob)
777
+ # mapper.assign_processor(&block)
778
+ # end
779
+
780
+ def assign_ntasks(target_bjob, create_node_mutex, &block)
781
+ target_bjob.input.each_assigned_filter do |input_filter|
782
+ mapper = NjobMapper.new(self, target_bjob, input_filter)
783
+ # create_node_mutex.synchronize do
784
+ mapper.assign_ntask(&block)
785
+ # end
786
+ end
787
+ end
788
+
789
+ class NjobMapper
790
+
791
+ def initialize(cont, target_bjob, input_filter)
792
+ @controller = cont
793
+ @target_bjob = target_bjob
794
+
795
+ @pre_bjob = @target_bjob.input
796
+ @input_filter = input_filter
797
+
798
+ init_policy
799
+
800
+ Log::debug(self, "Mapping Policy: #{@pre_bjob.class} -(#{@policy.class})-> #{@target_bjob.class}")
801
+
802
+ end
803
+
804
+ attr_reader :controller
805
+ attr_reader :pre_bjob
806
+ attr_reader :target_bjob
807
+ attr_reader :input_filter
808
+ attr_reader :policy
809
+
810
+ def init_policy
811
+ if @pre_bjob.respond_to?(:postmapping_policy) &&
812
+ @pre_bjob.postmapping_policy
813
+ @policy = eval(@pre_bjob.postmapping_policy.to_s).new(self)
814
+ return
815
+ end
816
+
817
+ # 今のところは必要なし(lazy create njob時に対応)
818
+ # if @target_bjob.kind_of?(BShuffle)
819
+ # @policy = MPNewProcessorN.new(self)
820
+ # return
821
+ # end
822
+
823
+ case @pre_bjob
824
+ when CFilePlace
825
+ #BInput系
826
+ @policy = MPInputProcessor.new(self)
827
+ when CLocalIOPlace
828
+ @policy = MPLocalInputNewProcessorN.new(self)
829
+ when CIotaPlace, CTherePlace
830
+ @policy = MPInputNewProcessorN.new(self)
831
+ when CVarrayPlace
832
+ @policy = MPVarrayInputProcessor.new(self)
833
+ # when CIotaPlace
834
+ # @policy = MPIotaInputProcessor.new(self)
835
+ when CBasicGroupBy, CDirectProduct::CPreFilter, CWC #, CSegShuffle
836
+ @policy = MPNewProcessorN.new(self)
837
+ # @policy = MPNewProcessor.new(self)
838
+ when CSegSplit, CInject::CLocalInject, CFind::CLocalFind
839
+ @policy = MPNewProcessor.new(self)
840
+ # when CSegShuffle
841
+ # @policy = MPPostShuffle.new(self)
842
+ # when CZip::CPreZipFilter
843
+ # @policy = MPZippedFilter.new(self)
844
+ else
845
+ @policy = MPSameNTask.new(self)
846
+ end
847
+ end
848
+
849
+ def assign_ntask(&block)
850
+ @policy.assign_ntask(&block)
851
+ end
852
+
853
+ def bind_input(njob)
854
+ @policy.bind_input(njob)
855
+ end
856
+ end
857
+
858
+ class NjobMappingPolicy
859
+ extend Forwardable
860
+
861
+ def initialize(mapper)
862
+ @mapper = mapper
863
+ end
864
+
865
+ def_delegator :@mapper, :controller
866
+ def_delegator :@mapper, :pre_bjob
867
+ def_delegator :@mapper, :target_bjob
868
+ def_delegator :@mapper, :input_filter
869
+
870
+ end
871
+
872
+ class MPInputProcessor < NjobMappingPolicy
873
+ def assign_ntask(&block)
874
+ controller.assign_input_processor_n(target_bjob,
875
+ input_filter.host) do |processor|
876
+ ntask = processor.create_ntask
877
+ block.call(ntask, @mapper)
878
+ end
879
+ end
880
+
881
+ def bind_input(njob)
882
+ begin
883
+ njob.open(input_filter)
884
+ rescue
885
+ raise AbortCreateNode
886
+ end
887
+ end
888
+ end
889
+
890
+ class MPInputNewProcessor< MPInputProcessor
891
+ def assign_ntask(&block)
892
+ controller.assign_new_processor(target_bjob) do |processor|
893
+ ntask = processor.create_ntask
894
+ block.call(ntask, @mapper)
895
+ end
896
+ end
897
+ end
898
+
899
+ class MPInputNewProcessorN< MPInputProcessor
900
+ def assign_ntask(&block)
901
+ controller.assign_new_processor_n(target_bjob,
902
+ nil) do |processor|
903
+ ntask = processor.create_ntask
904
+ block.call(ntask, @mapper)
905
+ end
906
+ end
907
+ end
908
+
909
+ class MPLocalInputNewProcessorN< MPInputProcessor
910
+ def assign_ntask(&block)
911
+ controller.assign_new_processor_n_for_local_io(target_bjob) do |processor|
912
+ ntask = processor.create_ntask
913
+ block.call(ntask, @mapper)
914
+ end
915
+ end
916
+ end
917
+
918
+ class MPVarrayInputProcessor < MPInputProcessor
919
+ def assign_ntask(&block)
920
+ controller.assign_same_obj_processor(target_bjob,
921
+ input_filter.ary) do |processor|
922
+ ntask = processor.create_ntask
923
+ block.call(ntask, @mapper)
924
+ end
925
+ end
926
+ end
927
+
928
+ class MPSameNTask < NjobMappingPolicy
929
+ def initialze(mapper)
930
+ super
931
+ @import = nil
932
+ end
933
+
934
+ def assign_ntask(&block)
935
+ # thread を立ち上げるべき
936
+ # このままでは, 十分に並列性が取れない(for [REQ:#5)]
937
+ controller.assign_same_processor(target_bjob,
938
+ input_filter.processor) do |processor|
939
+ ntask = input_filter.ntask
940
+ if input_filter.processor != processor
941
+ Log::warn(self, "ASSIGN_NTASK: assign defferent processor!!")
942
+ ntask = processor.create_ntask
943
+ end
944
+ block.call(ntask, @mapper)
945
+ end
946
+ end
947
+
948
+ def bind_input(njob)
949
+ njob.input = input_filter
950
+ end
951
+ end
952
+
953
+
954
+ # 必要ない?
955
+ # class MPSameProcessorObj < NjobMappingPolicy
956
+ # end
957
+
958
+ class MPNewProcessor < NjobMappingPolicy
959
+
960
+ def initialize(mapper)
961
+ super
962
+ @export = nil
963
+ @import = nil
964
+ end
965
+
966
+ def assign_ntask(&block)
967
+ pre_bjob.start_export(input_filter)
968
+
969
+ pre_bjob.each_export_by(input_filter, self) do |export, opts={}|
970
+ # pre_bjob.each_export_by(input_filter, self) do |export, opts|
971
+ # opts = {} unless opts
972
+
973
+ # thread を立ち上げるべき
974
+ # このままでは, 十分に並列性が取れない(for [REQ:#5)]
975
+ controller.assign_new_processor(target_bjob) do |processor|
976
+ # シリアライズに処理されることが前提になっている
977
+ @export = export
978
+ @import = target_bjob.create_import(processor)
979
+ ntask = processor.create_ntask
980
+ block.call(ntask, @mapper, opts)
981
+ end
982
+ end
983
+ end
984
+
985
+ def bind_input(njob)
986
+ @import.no = @export.no
987
+ @import.key = @export.key
988
+ njob.input = @import
989
+ @export.output = @import
990
+ pre_bjob.bind_export(@export, @import)
991
+ end
992
+ end
993
+
994
+ class MPNewProcessorN < MPNewProcessor
995
+ def assign_ntask(&block)
996
+ pre_bjob.start_export(input_filter)
997
+
998
+ pre_bjob.each_export_by(input_filter, self) do |export, opts={}|
999
+ # pre_bjob.each_export_by(input_filter, self) do |export, opts|
1000
+ # opts = {} unless opts
1001
+ # thread を立ち上げるべき
1002
+ # このままでは, 十分に並列性が取れない(for [REQ:#5)]
1003
+
1004
+ controller.assign_new_processor_n(target_bjob, pre_bjob) do
1005
+ |processor|
1006
+ # シリアライズに処理されることが前提になっている
1007
+ @export = export
1008
+ @import = target_bjob.create_import(processor)
1009
+ ntask = processor.create_ntask
1010
+ block.call(ntask, @mapper, opts)
1011
+ end
1012
+ end
1013
+ end
1014
+ end
1015
+
1016
+ class MPSameProcessor < MPNewProcessor
1017
+
1018
+ def assign_ntask(&block)
1019
+ pre_bjob.start_export(input_filter)
1020
+
1021
+ pre_bjob.each_export_by(input_filter, self) do |export, opts={}|
1022
+ # pre_bjob.each_export_by(input_filter, self) do |export, opts|
1023
+ # Log::debug(self, "YYYYYYYYYYYYYYY: #{export.class}, #{opts.class}")
1024
+ # opts = {} unless opts
1025
+ # thread を立ち上げるべき
1026
+ # このままでは, 十分に並列性が取れない(for [REQ:#5)]
1027
+ controller.assign_same_processor(target_bjob,
1028
+ input_filter.processor) do
1029
+ |processor|
1030
+ # シリアライズに処理されることが前提になっている
1031
+ @export = export
1032
+ @import = target_bjob.create_import(processor)
1033
+
1034
+ ntask = processor.create_ntask
1035
+ block.call(ntask, @mapper, opts)
1036
+ end
1037
+ end
1038
+ end
1039
+ end
1040
+ MPSameProcessorQ = MPSameProcessor
1041
+
1042
+ # class MPZippedFilter<MPNewProcessor
1043
+
1044
+ # def assign_processor(&block)
1045
+ # pre_bjob.start_export(input_filter)
1046
+
1047
+ # pre_bjob.each_export_by(input_filter, self) do |export|
1048
+ # # thread を立ち上げるべき
1049
+ # # このままでは, 十分に並列性が取れない(for [REQ:#5)]
1050
+ # controller.assign_new_processor(target_bjob) do |processor|
1051
+ # # シリアライズに処理されることが前提になっている
1052
+ # @export = export
1053
+ # @import = target_bjob.create_import(processor)
1054
+ # block.call(processor, @mapper)
1055
+ # end
1056
+ # end
1057
+ # end
1058
+
1059
+ # def bind_input(njob)
1060
+ # @import.no = @export.no
1061
+ # @import.key = @export.key
1062
+ # njob.input = @import
1063
+ # @export.output = @import
1064
+ # pre_bjob.bind_export(@export, @import)
1065
+ # end
1066
+ # end
1067
+
1068
+
1069
+ # class MPPreShuffle < NjobMappingPolicy
1070
+ # def each_exports(&block)
1071
+ # pre_bjob.start_export(input_filter)
1072
+
1073
+ # pre_bjob.each_export_by(input_filter, self) do |export|
1074
+ # # thread を立ち上げるべき
1075
+ # # このままでは, 十分に並列性が取れない(for [REQ:#5)]
1076
+ # @export = export
1077
+ # block.call(export)
1078
+ # end
1079
+ # end
1080
+ # end
1081
+
1082
+ # class MPPostShuffle < MPNewProcessorN
1083
+ # def assign_processor(&block)
1084
+ # # すでにスタートしている
1085
+ # #pre_bjob.start_export(input_filter)
1086
+
1087
+ # pre_bjob.each_export_by(input_filter, self) do |export|
1088
+ # # thread を立ち上げるべき
1089
+ # # このままでは, 十分に並列性が取れない(for [REQ:#5)]
1090
+ # controller.assign_new_processor_n(target_bjob, pre_bjob) do
1091
+ # |processor|
1092
+ # # シリアライズに処理されることが前提になっている
1093
+ # @export = export
1094
+ # @import = target_bjob.create_import(processor)
1095
+ # block.call(processor, @mapper)
1096
+ # end
1097
+ # end
1098
+ # end
1099
+ # end
1100
+ end
1101
+ end
1102
+
1103
+ require "fairy/master/addins"