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,510 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "fiber-mon"
7
+ require "deep-connect"
8
+
9
+ require "fairy/version"
10
+ require "fairy/share/conf"
11
+ require "fairy/share/stdout"
12
+
13
+
14
+ #DeepConnect::Organizer.immutable_classes.push Array
15
+
16
+ # require "node/nfile"
17
+ # require "node/n-local-file-input"
18
+ # require "node/n-input-iota"
19
+ # require "node/n-there"
20
+
21
+ # require "node/n-file-output"
22
+ # require "node/n-local-file-output"
23
+
24
+ # require "node/nhere"
25
+ # require "node/n-each-element-mapper"
26
+ # require "node/n-each-element-selector"
27
+ # require "node/n-each-substream-mapper"
28
+ # require "node/n-group-by"
29
+ # require "node/n-zipper"
30
+ # require "node/n-splitter"
31
+ # require "node/n-barrier"
32
+
33
+ module Fairy
34
+
35
+ class Processor
36
+
37
+ EXPORTS = []
38
+ def Processor.def_export(obj, name = nil)
39
+ unless name
40
+ if obj.kind_of?(Class)
41
+ if /Fairy::(.*)$/ =~ obj.name
42
+ name = $1
43
+ else
44
+ name = obj.name
45
+ end
46
+ else
47
+ ERR::Raise ERR::INTERNAL::CantDefExport, obj.to_s
48
+ end
49
+ end
50
+
51
+ EXPORTS.push [name, obj]
52
+ end
53
+
54
+ def initialize(id)
55
+ @id = id
56
+ @reserve = 0
57
+
58
+ @services = {}
59
+
60
+ @ntasks = []
61
+ @ntask_seq = -1
62
+ @ntask_seq_mutex = Mutex.new
63
+
64
+ @njob_mon = FiberMon.new
65
+
66
+ init_varray_feature
67
+ init_ntask_status_feature
68
+ end
69
+
70
+ attr_reader :id
71
+ attr_reader :ntasks
72
+
73
+ attr_reader :njob_mon
74
+
75
+ def log_id
76
+ "Processor[#{@id}]"
77
+ end
78
+
79
+ attr_reader :deepconnect
80
+
81
+ def start(node_port, service=0)
82
+ # if CONF.THREAD_STACK_SIZE
83
+ # Process.setrlimit(Process::RLIMIT_STACK, CONF.THREAD_STACK_SIZE)
84
+ # end
85
+
86
+ @addr = nil
87
+
88
+ @deepconnect = DeepConnect.start(service)
89
+ @deepconnect.register_service("Processor", self)
90
+
91
+ @deepconnect.when_disconnected do |deepspace, opts|
92
+ when_disconnected(deepspace, opts)
93
+ end
94
+
95
+ for name, obj in EXPORTS
96
+ export(name, obj)
97
+ end
98
+
99
+ @njob_mon.start
100
+
101
+ require "fairy/share/inspector"
102
+ @deepconnect.export("Inspector", Inspector.new(self))
103
+
104
+ require "fairy/share/log"
105
+ @node_deepspace = @deepconnect.open_deepspace("localhost", node_port)
106
+ @node = @node_deepspace.import("Node")
107
+ @logger = @node.logger
108
+ Log.type = "[P]"
109
+ Log.pid =id
110
+ Log.logger = @logger
111
+ Log::info self, "Processor Service Start"
112
+ Log::info(self, "\tfairy version: #{Version}")
113
+ Log::info(self, "\t[Powered By #{RUBY_DESCRIPTION}]")
114
+
115
+ start_watch_status
116
+
117
+
118
+ # GC.disable
119
+ # Thread.start do
120
+ # loop do
121
+ # sleep 60
122
+ # GC.start
123
+ # end
124
+ # end
125
+ @node.register_processor(self)
126
+ end
127
+
128
+ def connect_controller(controller, conf)
129
+ @controller = controller
130
+ conf.base_conf = CONF
131
+ Fairy::REPLACE_CONF(conf)
132
+
133
+ # Log::set_local_output_dev
134
+
135
+ if CONF.PROCESSOR_MON_ON
136
+ Log::info self, "Processor Status Monitoring: ON"
137
+ start_process_status_monitor
138
+ end
139
+
140
+ $stdout = Stdout.new(controller)
141
+ end
142
+ DeepConnect.def_method_spec(self, "REF connect_controller(REF, DVAL)")
143
+
144
+ def terminate
145
+ # clientが終了したときの終了処理
146
+ Log::info(self, "terminate!!")
147
+ Thread.start do
148
+ begin
149
+ # このメソッドが戻るまで待つ
150
+ sleep 0.2
151
+ @ntasks.each{|ntask| ntask.abort_running}
152
+
153
+ @deepconnect.stop
154
+ Process.exit(0)
155
+ rescue
156
+ Log::debug(self, "Exception Rised in termination ntasks.")
157
+ Log::debug_exception(self)
158
+ end
159
+ end
160
+ nil
161
+ end
162
+
163
+ def terminate_all_ntasks
164
+ Log::debug(self, "Terminate all ntasks!!")
165
+ begin
166
+ @ntasks.each{|ntask| ntask.abort_running}
167
+ rescue
168
+ Log::debug(self, "Exception Rised in termination ntasks.")
169
+ Log::debug_exception(self)
170
+ end
171
+ end
172
+
173
+ def when_disconnected(deepspace, opts)
174
+ Log::debug self, "PROCESSOR: disconnected #{deepspace.peer_uuid}"
175
+ end
176
+
177
+ attr_accessor :addr
178
+ attr_reader :node
179
+
180
+ def node
181
+ @node
182
+ end
183
+
184
+ def export(service, obj)
185
+ @services[service] = obj
186
+ end
187
+
188
+ def import(service)
189
+ svs = @services[service]
190
+ unless svs
191
+ ERR::Raise ERR::INTERNAL::NoRegisterService, service
192
+ end
193
+ svs
194
+ end
195
+
196
+ def ntask_next_id
197
+ @ntask_seq_mutex.synchronize do
198
+ @ntask_seq += 1
199
+ end
200
+ end
201
+
202
+ def no_ntasks
203
+ @ntasks.size
204
+ end
205
+
206
+ def create_ntask
207
+ ntask = PTask.new(ntask_next_id, self)
208
+ @ntasks.push ntask
209
+ ntask
210
+ end
211
+ DeepConnect.def_method_spec(self, "REF create_ntask(VAL, *VAL)")
212
+
213
+ # def create_njob(njob_class_name, bjob, opts, *rests)
214
+ # klass = import(njob_class_name)
215
+ # njob = klass.new(self, bjob, opts, *rests)
216
+ # @njobs.push njob
217
+ # Log.debugf(self, "Njob number of %d", @njobs.size)
218
+ # njob
219
+ # end
220
+ # DeepConnect.def_method_spec(self, "REF create_njob(VAL, REF, VAL, *VAL)")
221
+
222
+ def create_import(policy)
223
+ import = Import.new(policy)
224
+ import.set_log_callback do |n, key|
225
+ Log::verbose(self, "IMPORT POP key=#{key}: #{n}")
226
+ end
227
+ import
228
+ end
229
+ DeepConnect.def_method_spec(self, "REF create_import(DVAL)")
230
+
231
+
232
+ LIMIT_PROCESS_SIZE = 100 #kbyte
233
+ def life_out_life_span?
234
+ # puts "LOLS: #{inspectx}"
235
+ # puts "njob: #{all_njob_finished?}"
236
+ # unless all_njob_finished?
237
+ # for njob, status in @njob_status
238
+ # puts "#{njob.class} => #{status}"
239
+ # end
240
+ # end
241
+
242
+ # puts "varry: #{exist_varray_elements?}"
243
+
244
+ return false unless all_ntasks_finished?
245
+ return false if exist_varray_elements?
246
+
247
+ # 取りあえず
248
+ vsz = `ps -ovsz h#{Process.pid}`.to_i
249
+ #puts "vsz: #{vsz}, #{LIMIT_PROCESS_SIZE > vsz}"
250
+
251
+ LIMIT_PROCESS_SIZE < vsz
252
+ end
253
+
254
+ #
255
+ # varray management
256
+ #
257
+ def init_varray_feature
258
+ @varray_elements = {}
259
+ @varray_elements_mutex = Mutex.new
260
+ end
261
+
262
+ def exist_varray_elements?
263
+ @varray_elements_mutex.synchronize do
264
+ !@varray_elements.empty?
265
+ end
266
+ end
267
+
268
+ def register_varray_element(array)
269
+ @varray_elements_mutex.synchronize do
270
+ @varray_elements[array.object_id] = array.object_id
271
+ end
272
+ ObjectSpace.define_finalizer(array, deregister_varray_element_proc)
273
+ end
274
+
275
+ def deregister_varray_element_proc
276
+ proc do |oid|
277
+ @varray_elements_mutex.synchronize do
278
+ @varray_elements.delete(oid)
279
+ end
280
+ end
281
+ end
282
+
283
+ #
284
+ # (processor) status management and ntask status management
285
+ # processor status:
286
+ # ST_WAIT
287
+ # ST_ACTIVATE
288
+ #
289
+ def init_ntask_status_feature
290
+ @status = :ST_WAIT
291
+ @ntask_status = {}
292
+
293
+ # @status_mutex = Mutex.new
294
+ @status_cv = @njob_mon.new_cv
295
+
296
+ end
297
+
298
+ ACTIVE_STATUS = {
299
+ :ST_INIT => true,
300
+ :ST_WAIT_IMPORT => true,
301
+ :ST_ACTIVATE => true
302
+ }
303
+
304
+ SEMIACTIVE_STATUS = {
305
+ # :ST_INIT => true,
306
+ # :ST_WAIT_IMPORT => true,
307
+ :ST_ALL_IMPORTED => true,
308
+ :ST_WAIT_EXPORT_FINISH => true,
309
+ :ST_EXPORT_FINISH => true,
310
+ :ST_OUTPUT_FINISH => true
311
+ }
312
+
313
+ def no_active_ntasks
314
+ no_actives = 0
315
+ @ntask_status.each{|ntask, st|
316
+ no_actives += 1 if ACTIVE_STATUS[st]
317
+ }
318
+ no_actives
319
+ end
320
+
321
+ def all_ntasks_finished?(lock = :lock)
322
+ if lock == :lock
323
+ @status_cv.synchronize do
324
+ all_ntasks_finished_no_lock?
325
+ end
326
+ else
327
+ all_ntasks_finished_no_lock?
328
+ end
329
+ end
330
+
331
+ def all_ntasks_finished_no_lock?
332
+ for node, status in @ntask_status
333
+ return false if status != :ST_FINISH
334
+ end
335
+ true
336
+ end
337
+
338
+ def all_ntasks_semiactivated?(lock = :lock)
339
+ if lock == :lock
340
+ @status_cv.synchronize do
341
+ all_ntasks_semiactivated_no_lock?
342
+ end
343
+ else
344
+ all_ntasks_semiactivated_no_lock?
345
+ end
346
+ end
347
+
348
+ def all_ntasks_semiactivated_no_lock?
349
+ for node, status in @ntask_status
350
+ return false unless SEMIACTIVE_STATUS[status]
351
+ end
352
+ true
353
+ end
354
+
355
+
356
+ def update_status(ntask, st)
357
+ Log::debug(self, "UPDATE_STATUS: #{ntask}, #{st}")
358
+ @njob_mon.synchronize do
359
+ @ntask_status[ntask] = st
360
+
361
+ case st
362
+ when :ST_INIT
363
+ # do nothing
364
+ if all_ntasks_semiactivated?(:no_lock)
365
+ Log::debug(self, "UPDATE_STATUS A: #{st}")
366
+ @status = :ST_SEMIACTIVATE
367
+ end
368
+ when :ST_WAIT_IMPORT
369
+ if all_ntasks_semiactivated?(:no_lock)
370
+ Log::debug(self, "UPDATE_STATUS B: #{st}")
371
+ @status = :ST_SEMIACTIVATE
372
+ end
373
+ when :ST_ACTIVATE
374
+ Log::debug(self, "UPDATE_STATUS C: #{st}")
375
+ @status = :ST_ACTIVATE
376
+ when :ST_ALL_IMPORTED,
377
+ :ST_WAIT_EXPORT_FINISH,
378
+ :ST_EXPORT_FINISH,
379
+ :ST_OUTPUT_FINISH
380
+ if all_ntasks_semiactivated?(:no_lock)
381
+ Log::debug(self, "UPDATE_STATUS D: #{st}")
382
+ @status = :ST_SEMIACTIVATE
383
+ end
384
+ when :ST_FINISH
385
+ if all_ntasks_finished?(:no_lock)
386
+ Log::debug(self, "UPDATE_STATUS E: #{st}")
387
+ @status = :ST_WAIT
388
+ end
389
+ else
390
+ if @status == :ST_WAIT
391
+ Log::debug(self, "UPDATE_STATUS F: #{st}")
392
+ @status = :ST_ACTIVATE
393
+ end
394
+ end
395
+ @status_cv.broadcast
396
+ end
397
+ end
398
+
399
+ def start_watch_status
400
+ # 初期状態通知
401
+ notice_status(@status)
402
+
403
+ @njob_mon.entry do
404
+ @njob_mon.synchronize do
405
+ old_status = nil
406
+ old_no_active_ntasks = 0
407
+ loop do
408
+ @status_cv.wait_while{
409
+ old_status == @status && old_no_active_ntasks == no_active_ntasks
410
+ }
411
+ no = no_active_ntasks
412
+ if old_no_active_ntasks != no
413
+ old_no_active_ntasks = no
414
+ @controller.update_active_ntasks(self, no)
415
+ end
416
+ if old_status != @status
417
+ old_status = @status
418
+ notice_status(@status)
419
+ end
420
+ end
421
+ end
422
+ end
423
+ nil
424
+ end
425
+
426
+ def notice_status(st)
427
+ @node.update_processor_status(self, st)
428
+ end
429
+
430
+ #
431
+ # prossessor monitoring
432
+ #
433
+ def start_process_status_monitor
434
+ Thread.start do
435
+ begin
436
+ idle = CONF.PROCESSOR_MON_INTERVAL
437
+ loop do
438
+ sleep idle
439
+ process_status_mon
440
+ end
441
+ rescue
442
+ Log::debug_exception
443
+ raise
444
+ end
445
+ end
446
+ end
447
+
448
+ def process_status_mon(inspect_p = CONF.PROCESSOR_MON_OBJECTSPACE_INSPECT_ON)
449
+
450
+ if inspect_p
451
+ GC.start
452
+
453
+ count = 0
454
+ count_by_class = {}
455
+ ObjectSpace.each_object do |o|
456
+ count += 1
457
+ klass = o.__deep_connect_real_class
458
+ count_by_class[klass] = (count_by_class[klass] || 0) + 1
459
+ end
460
+ exp = 0
461
+ exp_by_class = {}
462
+ imp = 0
463
+ for ds in @deepconnect.instance_eval{@organizer}.deep_spaces.values
464
+ exp_roots = ds.instance_eval{@export_roots}
465
+ exp += exp_roots.size
466
+ exp_roots.each do |k, v|
467
+ klass = v.class
468
+ exp_by_class[klass] = (exp_by_class[klass] || 0) + 1
469
+ end
470
+ imp += ds.instance_eval{@import_reference.size}
471
+ end
472
+ end
473
+
474
+ format = CONF.PROCESSOR_MON_PSFORMAT
475
+ m = `ps -o#{format} h#{Process.pid}`.chomp
476
+ Log::info(self) do |sio|
477
+ sio.puts("PROCESS MONITOR:")
478
+ sio.puts("#{Log.host} [P]\##{@id} MONITOR: PS: #{m}")
479
+ if inspect_p
480
+ sio.puts("#{Log.host} [P]\##{@id} MONITOR: OBJECT: #{count}")
481
+ for klass in count_by_class.keys.sort_by{|k| k.name}
482
+ sio.puts("#{Log.host} [P]\##{@id} MONITOR: C: #{klass.name} => #{count_by_class[klass]}")
483
+ end
484
+ sio.puts("#{Log.host} [P]\##{@id} MONITOR: DEEP-CONNECT: exports: #{exp}")
485
+ for klass in exp_by_class.keys.sort_by{|k| k.name}
486
+ sio.puts("#{Log.host} [P]\##{@id} MONITOR: C: #{klass.name} => #{exp_by_class[klass]}")
487
+ end
488
+ sio.puts("#{Log.host} [P]\##{@id} MONITOR: DEEP-CONNECT: imports: #{imp}")
489
+ end
490
+ end
491
+ end
492
+
493
+ def inspectx
494
+ "#<#{self.class}: #{id} [#{@ntask.collect{|n| n.class.name}.join(" ")}]>"
495
+ end
496
+
497
+ def to_s
498
+ "#<#{self.class}: #{id}>"
499
+ end
500
+
501
+ end
502
+
503
+ def Processor.start(id, node_port)
504
+ processor = Processor.new(id)
505
+ processor.start(node_port)
506
+ end
507
+
508
+ end
509
+
510
+ require "fairy/node/addins"