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,347 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ module Fairy
7
+
8
+ class MarshaledQueue
9
+
10
+ def initialize(policy, queues_mon = Monitor.new, queues_cv = queues_mon.new_cond)
11
+ @policy = policy
12
+
13
+ @chunk_size = CONF.MARSHAL_QUEUE_CHUNK_SIZE
14
+ @min_chunk_no = @policy[:min_chunk_no]
15
+ @min_chunk_no ||= CONF.MARSHAL_QUEUE_MIN_CHUNK_NO
16
+
17
+ @push_queue = []
18
+ @push_queue_mutex = Mutex.new
19
+
20
+ @queues = []
21
+ @queues_mon = queues_mon
22
+ @queues_cv = queues_cv
23
+
24
+ @pop_queue = nil
25
+ end
26
+
27
+ attr_accessor :fib_cv
28
+
29
+ def push(e)
30
+ @push_queue_mutex.synchronize do
31
+ @push_queue.push e
32
+ if @push_queue.size >= @min_chunk_no ||
33
+ e == :END_OF_STREAM ||
34
+ e == Import::SET_NO_IMPORT
35
+ @queues_mon.synchronize do
36
+ @push_queue.pop if e == :END_OF_STREAM
37
+ @queues.push Marshal.dump(@push_queue)
38
+ @queues.push e if e == :END_OF_STREAM
39
+
40
+ @push_queue = []
41
+ @queues_cv.broadcast
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def push_all(buf)
48
+ @push_queue_mutex.synchronize do
49
+ @push_queue.concat buf
50
+ if @push_queue.size > @min_chunk_no ||
51
+ @push_queue.last == :END_OF_STREAM
52
+ @queues_mon.synchronize do
53
+ @push_queue.pop if e == :END_OF_STREAM
54
+ @queues.push Marshal.dump(@push_queue)
55
+ @queues.push e if e == :END_OF_STREAM
56
+
57
+ @push_queue = []
58
+ @queues_cv.broadcast
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ def push_raw(raw)
65
+ @push_queue_mutex.synchronize do
66
+ @queues_mon.synchronize do
67
+ unless @push_queue.empty?
68
+ @queues.push Marshal.dump(@push_queue)
69
+ @push_queue = []
70
+ end
71
+ @queues.push raw
72
+ @queues_cv.broadcast
73
+ end
74
+ end
75
+ end
76
+
77
+ def pop
78
+ while !@pop_queue || @pop_queue.empty?
79
+ @queues_mon.synchronize do
80
+ raw = nil
81
+ @queues_cv.wait_until{raw = @queues.shift}
82
+ if raw == :END_OF_STREAM
83
+ @pop_queue = [raw]
84
+ else
85
+ @pop_queue = Marshal.load(raw)
86
+ end
87
+ end
88
+ end
89
+ e = @pop_queue.shift
90
+ @pop_queue = nil if @pop_queue.empty?
91
+ e
92
+ end
93
+
94
+ def pop_all
95
+ while !@pop_queue
96
+ @queues_mon.synchronize do
97
+ raw = nil
98
+ @queues_cv.wait_until{raw = @queues.shift}
99
+ if raw == :END_OF_STREAM
100
+ @pop_queue = [raw]
101
+ else
102
+ @pop_queue = Marshal.load(raw)
103
+ end
104
+ end
105
+ end
106
+ buf, @pop_queue = @pop_queue, nil
107
+ buf
108
+ end
109
+
110
+ def pop_raw
111
+ if @pop_queue && !@pop_queue.empty?
112
+ ERR::Raise ERR::INTERNAL::MarshalQueueNotEmpty
113
+ end
114
+
115
+ pop_raw = nil
116
+ while !pop_raw
117
+ @queues_mon.synchronize do
118
+ @queues_cv.wait_until{pop_raw = @queues.shift}
119
+ end
120
+ end
121
+ pop_raw
122
+ end
123
+
124
+ end
125
+
126
+ class SizedMarshaledQueue<MarshaledQueue
127
+ def initialize(policy, queues_mon = Monitor.new, queues_cv = queues_mon.new_cond)
128
+ super
129
+ @max_size = policy[:size]
130
+ @max_size ||= CONF.SIZEDMARSHAL_QUEUE_MAX_CHUNK_NO
131
+
132
+ @pop_cv = @queues_cv
133
+ @push_cv = @queues_mon.new_cond
134
+ end
135
+
136
+ def push(e)
137
+ @queues_mon.synchronize do
138
+ @push_cv.wait_while{@queues.size > @max_size}
139
+ end
140
+ super
141
+ end
142
+
143
+ def push_all(buf)
144
+ @queues_mon.synchronize do
145
+ @push_cv.wait_while{@queues.size > @max_size}
146
+ end
147
+ super
148
+ end
149
+
150
+ def push_raw(raw)
151
+ @queues_mon.synchronize do
152
+ @push_cv.wait_while{@queues.size > @max_size}
153
+ end
154
+ super
155
+ end
156
+
157
+ def pop
158
+ e = super
159
+ @queues_mon.synchronize do
160
+ @push_cv.broadcast if @queues.size <= @max_size
161
+ end
162
+ e
163
+ end
164
+
165
+ def pop_all
166
+ buf = super
167
+ @queues_mon.synchronize do
168
+ @push_cv.broadcast if @queues.size <= @max_size
169
+ end
170
+ buf
171
+ end
172
+
173
+ def pop_raw
174
+ raw = super
175
+ @queues_mon.synchronize do
176
+ @push_cv.broadcast if @queues.size <= @max_size
177
+ end
178
+ raw
179
+ end
180
+ end
181
+
182
+ class FileMarshaledQueue
183
+ def initialize(policy, queues_mon = Monitor.new, queues_cv = queues_mon.new_cond)
184
+ @policy = policy
185
+
186
+ @chunk_size = CONF.MARSHAL_QUEUE_CHUNK_SIZE
187
+ @min_chunk_no = @policy[:min_chunk_no]
188
+ @min_chunk_no ||= CONF.MARSHAL_QUEUE_MIN_CHUNK_NO
189
+
190
+ @push_queue = []
191
+ @push_queue_mutex = Mutex.new
192
+
193
+ @buffers_queue = []
194
+ @buffers_queue_mon = queues_mon
195
+ @buffers_queue_cv = queues_cv
196
+
197
+ @pop_queue = nil
198
+
199
+ @buffer_dir = @policy[:buffer_dir]
200
+ @buffer_dir ||= CONF.TMP_DIR
201
+ end
202
+
203
+ def push(e)
204
+ @push_queue_mutex.synchronize do
205
+ @push_queue.push e
206
+ if @push_queue.size >= @min_chunk_no ||
207
+ e == :END_OF_STREAM ||
208
+ e == Import::SET_NO_IMPORT
209
+ @buffers_queue_mon.synchronize do
210
+ @push_queue.pop if e == :END_OF_STREAM
211
+ store_2ndmemory(@push_queue)
212
+ @buffers_queue.push e if e == :END_OF_STREAM
213
+
214
+ @push_queue = []
215
+ @buffers_queue_cv.broadcast
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ def push_all(buf)
222
+ @push_queue_mutex.synchronize do
223
+ @push_queue.concat buf
224
+ if @push_queue.size > @min_chunk_no ||
225
+ @push_queue.last == :END_OF_STREAM
226
+ @buffers_queue_mon.synchronize do
227
+ @push_queue.pop if e == :END_OF_STREAM
228
+ store_2ndmemory(@push_queue)
229
+ @buffers_queue.push e if e == :END_OF_STREAM
230
+
231
+ @push_queue = []
232
+ @buffers_queue_cv.broadcast
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ def push_raw(raw)
239
+ @push_queue_mutex.synchronize do
240
+ @buffers_queue_mon.synchronize do
241
+ unless @push_queue.empty?
242
+ store_2ndmemory(@push_queue)
243
+ @push_queue = []
244
+ end
245
+ if raw == :END_OF_STREAM
246
+ @buffers_queue.push raw
247
+ else
248
+ store_raw_2ndmemory(raw)
249
+ end
250
+ @buffers_queue_cv.broadcast
251
+ end
252
+ end
253
+ end
254
+
255
+ def pop
256
+ while !@pop_queue || @pop_queue.empty?
257
+ @buffers_queue_mon.synchronize do
258
+ buf = nil
259
+ @buffers_queue_cv.wait_until{buf = @buffers_queue.shift}
260
+
261
+ if buf == :END_OF_STREAM
262
+ @pop_queue = [buf]
263
+ else
264
+ @pop_queue = restore_2ndmemory(buf)
265
+ end
266
+ end
267
+ end
268
+ e = @pop_queue.shift
269
+ @pop_queue = nil if @pop_queue.empty?
270
+ e
271
+ end
272
+
273
+ def pop_all
274
+ while !@pop_queue
275
+ @buffers_queue_mon.synchronize do
276
+ buf = nil
277
+ @buffers_queue_cv.wait_until{buf = @buffers_queue.shift}
278
+ if buf == :END_OF_STREAM
279
+ @pop_queue = [buf]
280
+ else
281
+ @pop_queue = restore_2ndmemory(buf)
282
+ end
283
+ end
284
+ end
285
+ buf, @pop_queue = @pop_queue, nil
286
+ buf
287
+ end
288
+
289
+ def pop_raw
290
+ if @pop_queue && !@pop_queue.empty?
291
+ ERR::Raise ERR::INTERNAL::MarshalQueueNotEmpty
292
+ end
293
+
294
+ pop_raw = nil
295
+ while !pop_raw
296
+ @buffers_queue_mon.synchronize do
297
+ buf = nil
298
+ @buffers_queue_cv.wait_until{buf = @buffers_queue.shift}
299
+ if buf == :END_OF_STREAM
300
+ pop_raw = buf
301
+ else
302
+ pop_raw = restore_raw_2ndmemory(buf)
303
+ end
304
+ end
305
+ end
306
+ pop_raw
307
+ end
308
+
309
+ def open_2ndmemory(&block)
310
+ buffer = FastTempfile.open("port-buffer-", @buffer_dir)
311
+ begin
312
+ yield buffer.io
313
+ ensure
314
+ buffer.close
315
+ end
316
+ @buffers_queue.push buffer
317
+ buffer
318
+ end
319
+
320
+ def store_2ndmemory(ary)
321
+ open_2ndmemory do |io|
322
+ Marshal.dump(ary, io)
323
+ end
324
+ end
325
+
326
+ def store_raw_2ndmemory(raw)
327
+ open_2ndmemory do |io|
328
+ io.write raw
329
+ end
330
+ end
331
+
332
+ def restore_2ndmemory(buf)
333
+ io = buf.open
334
+ queue = Marshal.load(io)
335
+ buf.close!
336
+ queue
337
+ end
338
+
339
+ def restore_raw_2ndmemory(buf)
340
+ io = buf.open
341
+ raw = io.read
342
+ buf.close!
343
+ raw
344
+ end
345
+ end
346
+ end
347
+
@@ -0,0 +1,1697 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (C) 2007-2010 Rakuten, Inc.
4
+ #
5
+
6
+ require "forwardable"
7
+
8
+ require "fiber-mon"
9
+ require "fairy/share/fast-tempfile.rb"
10
+
11
+ module Fairy
12
+
13
+ PORT_DEFAULT_KEEP_IDENTITY_CLASSES = [
14
+ Binding,
15
+ UnboundMethod,
16
+ Method,
17
+ Proc,
18
+ Dir,
19
+ File,
20
+ IO,
21
+ ThreadGroup,
22
+ Thread,
23
+ Data,
24
+ # DeepConnect::Reference
25
+ ]
26
+ if defined?(Continuation)
27
+ PORT_DEFAULT_KEEP_IDENTITY_CLASSES.push Continuation
28
+ end
29
+ if defined?(StopIteration)
30
+ PORT_DEFAULT_KEEP_IDENTITY_CLASSES.push StopIteration
31
+ end
32
+ if defined?(Enumerable::Enumerator)
33
+ PORT_DEFAULT_KEEP_IDENTITY_CLASSES.push Enumerable::Enumerator
34
+ end
35
+ PORT_KEEP_IDENTITY_CLASS_SET = {}
36
+ PORT_DEFAULT_KEEP_IDENTITY_CLASSES.each do|k|
37
+ PORT_KEEP_IDENTITY_CLASS_SET[k] = k
38
+ end
39
+
40
+ def self.add_port_keep_identity_class(klass)
41
+ PORT_KEEP_IDENTITY_CLASS_SET[klass] = klass
42
+ end
43
+
44
+ class Import
45
+ include Enumerable
46
+
47
+ ::Fairy.add_port_keep_identity_class(self)
48
+
49
+ END_OF_STREAM = :END_OF_STREAM
50
+
51
+ class CTLTOKEN;end
52
+ class CTLTOKEN_SET_NO_IMPORT<CTLTOKEN;end
53
+ SET_NO_IMPORT = CTLTOKEN_SET_NO_IMPORT.new
54
+
55
+ class CTLTOKEN_NULLVALUE;end
56
+ TOKEN_NULLVALUE = CTLTOKEN_NULLVALUE.new
57
+
58
+ class CTLTOKEN_DELAYED_ELEMENT<CTLTOKEN
59
+ ::Fairy.add_port_keep_identity_class(self)
60
+
61
+ def initialize(&b)
62
+ @call_back = b
63
+ end
64
+
65
+ def get_element(import)
66
+ @call_back.call(import)
67
+ end
68
+ end
69
+
70
+ def initialize(policy = nil)
71
+
72
+ @queuing_policy = policy
73
+ @queuing_policy ||= CONF.PREQUEUING_POLICY
74
+
75
+ case @queuing_policy
76
+ when Hash
77
+ @queue = eval("#{@queuing_policy[:queuing_class]}").new(@queuing_policy)
78
+ else
79
+ @queue = @queuing_policy
80
+ end
81
+
82
+ Log::debug(self, "Using Buffer: #{@queue.class}")
83
+
84
+ @log_import_ntimes_pop = CONF.LOG_IMPORT_NTIMES_POP
85
+ @log_callback_proc = nil
86
+
87
+ @njob_id = nil
88
+
89
+ @no = nil
90
+ @no_mutex = Mutex.new
91
+ @no_cv = ConditionVariable.new
92
+
93
+ @key = nil
94
+
95
+ @no_import = nil
96
+
97
+ @no_pop_elements = 0
98
+ @no_eos = 0
99
+
100
+ @DEBUG_PORT_WAIT = CONF.DEBUG_PORT_WAIT
101
+ end
102
+
103
+ attr_accessor :njob_id
104
+
105
+ def log_id
106
+ "Import[#{@njob_id}[#{@no}:#{@key}]]"
107
+ end
108
+
109
+ def no
110
+ @no_mutex.synchronize do
111
+ while !@no
112
+ Log::debug(self, "Wait until set @no") if @DEBUG_PORT_WAIT
113
+ @no_cv.wait(@no_mutex)
114
+ Log::debug(self, "End: Wait until set @no") if @DEBUG_PORT_WAIT
115
+ end
116
+ @no
117
+ end
118
+ end
119
+
120
+ def no=(no)
121
+ @no_mutex.synchronize do
122
+ @no=no
123
+ @no_cv.broadcast
124
+ end
125
+ end
126
+
127
+ attr_accessor :key
128
+ def add_key(key)
129
+ @key = key
130
+ end
131
+
132
+ def no_import=(n)
133
+ @no_import = n
134
+ @queue.push SET_NO_IMPORT
135
+ nil
136
+ end
137
+
138
+ def push(e)
139
+ @queue.push e
140
+ nil
141
+ end
142
+ DeepConnect.def_method_spec(self, "REF push(DVAL)")
143
+
144
+ def push_buf(buf)
145
+ if @queue.respond_to?(:push_all)
146
+ @queue.push_all(buf)
147
+ nil
148
+ else
149
+ begin
150
+ buf.each{|e| @queue.push e}
151
+ nil
152
+ rescue
153
+ Log::debug_exception(self)
154
+ raise
155
+ end
156
+ end
157
+ end
158
+ DeepConnect.def_method_spec(self, "REF push_buf(DVAL)")
159
+
160
+ def push_strings(bigstr)
161
+ strings = bigstr.split("\t").collect{|e|
162
+ e.gsub(/(\\t|\\\\)/){|v| v == "\\t" ? "\t" : "\\"}
163
+ }
164
+
165
+ if @queue.respond_to?(:push_all)
166
+ @queue.push_all(strings)
167
+ nil
168
+ else
169
+ begin
170
+ strings.each{|e| @queue.push e}
171
+ nil
172
+ rescue
173
+ Log::debug_exception(self)
174
+ raise
175
+ end
176
+ end
177
+ end
178
+
179
+ def push_keep_identity(e)
180
+ @queue.push e
181
+ nil
182
+ end
183
+
184
+ def push_raw(raw)
185
+ if @queue.respond_to?(:push_raw)
186
+ @queue.push_raw(raw)
187
+ nil
188
+ elsif @queue.respond_to?(:push_buf)
189
+ buf = Marshal.load(raw)
190
+ @queue.push_raw(buf)
191
+ nil
192
+ else
193
+ begin
194
+ buf = Marshal.load(raw)
195
+ @queue.push_raw(buf)
196
+ buf.each{|e| @queue.push e}
197
+ nil
198
+ rescue
199
+ Log::debug_exception(self)
200
+ raise
201
+ end
202
+ end
203
+ end
204
+ DeepConnect.def_method_spec(self, "REF push_raw(DVAL)")
205
+
206
+
207
+ def pop
208
+ while !@no_import or @no_import > @no_eos
209
+ e = @queue.pop
210
+ case e
211
+ when CTLTOKEN_DELAYED_ELEMENT
212
+ e = e.get_element(self)
213
+ end
214
+ case e
215
+ when CTLTOKEN_DELAYED_ELEMENT
216
+ e = e.get_element(import)
217
+ when CTLTOKEN_SET_NO_IMPORT
218
+ #when SET_NO_IMPORT
219
+ # do nothing
220
+ when END_OF_STREAM
221
+ @no_eos += 1
222
+ Log::debug(self, "IMPORT EOS key=#{@key}: #{@no_eos}/#{@no_import}")
223
+ else
224
+ @no_pop_elements += 1
225
+ if @log_import_ntimes_pop &&
226
+ (@no_pop_elements % @log_import_ntimes_pop == 0 ||
227
+ @no_pop_elements == 1)
228
+ if @log_callback_proc
229
+ @log_callback_proc.call @no_pop_elements, @key
230
+ else
231
+ Log::verbose(self, "IMPORT POP key=#{@key}: #{@no_pop_elements}")
232
+ end
233
+ end
234
+
235
+ return e
236
+ end
237
+ end
238
+ if @log_callback_proc
239
+ @log_callback_proc.call "EOS", @key
240
+ else
241
+ Log::verbose(self, "IMPORT POP key=#{@key}: EOS")
242
+ end
243
+ return nil
244
+ end
245
+
246
+ def each(&block)
247
+ Log::debug(self, "START IMPORT")
248
+ while !@no_import or @no_import > @no_eos
249
+ e = @queue.pop
250
+ case e
251
+ when CTLTOKEN_DELAYED_ELEMENT
252
+ e = e.get_element(self)
253
+ end
254
+
255
+ case e
256
+ when CTLTOKEN_SET_NO_IMPORT
257
+ #when SET_NO_IMPORT
258
+ # do nothing
259
+ when END_OF_STREAM
260
+ @no_eos += 1
261
+ if @log_callback_proc
262
+ @log_callback_proc.call "EOS(#{@no_eos}/#{@no_import})", @key
263
+ else
264
+ Log::debug(self, "IMPORT POP key=#{@key}: EOS(#{@no_eos}/#{@no_import})")
265
+ end
266
+ else
267
+ @no_pop_elements += 1
268
+ if @log_import_ntimes_pop &&
269
+ (@no_pop_elements % @log_import_ntimes_pop == 0 ||
270
+ @no_pop_elements == 1)
271
+ if @log_callback_proc
272
+ Log::verbose(self, "IMPORT POP key=#{@key}: #{@no_pop_elements}")
273
+ @log_callback_proc.call @no_pop_elements, @key
274
+ else
275
+ Log::verbose(self, "IMPORT POP key=#{@key}: #{@no_pop_elements}")
276
+ end
277
+ end
278
+ block.call(e)
279
+ end
280
+ end
281
+ if @log_callback_proc
282
+ @log_callback_proc.call "EOS(ALL)", @key
283
+ else
284
+ Log::verbose(self, "IMPORT POP key=#{@key}: EOS(ALL)")
285
+ end
286
+ Log::debug(self, "FINISH IMPORT")
287
+ end
288
+
289
+ def size
290
+ size = 0
291
+ each{size += 1}
292
+ size
293
+ end
294
+
295
+ def context_eval(str)
296
+ eval str
297
+ end
298
+
299
+ def set_log_callback(str = nil, bind = binding, file = __FILE__, line_no = __LINE__, &block)
300
+ if str
301
+ @log_callback_proc = eval(%{proc{#{str}}}, bind, file, line_no)
302
+ else
303
+ @log_callback_proc = block
304
+ end
305
+ end
306
+
307
+ # 疑似対応
308
+ def asynchronus_send_with_callback(method, *args, &call_back)
309
+ ret = nil
310
+ exp = nil
311
+ begin
312
+ ret = __send__(method, *args)
313
+ rescue => exp
314
+ end
315
+ call_back.call(ret, exp)
316
+ end
317
+
318
+ end
319
+
320
+ class Export
321
+ END_OF_STREAM = :END_OF_STREAM
322
+
323
+ ExportMonitor = FiberMon.new
324
+ ExportMonitor.start
325
+
326
+ def initialize(policy = nil)
327
+
328
+ @queuing_policy = policy
329
+ @queuing_policy ||= CONF.POSTQUEUING_POLICY
330
+ @max_chunk = CONF.POSTQUEUE_MAX_TRANSFER_SIZE
331
+
332
+ @STR_TRANSFAR = CONF.TRANSFAR_MARSHAL_STRING_ARRAY_OPTIMIZE
333
+
334
+ # @output_buf = []
335
+ # @output_buf_mutex = Mutex.new
336
+ # @output_buf_cv = ConditionVariable.new
337
+
338
+ @output = nil
339
+ @output_mutex = Mutex.new
340
+ @output_cv = ConditionVariable.new
341
+
342
+ @njob_id = nil
343
+
344
+ @no = nil
345
+ @no_mutex = Mutex.new
346
+ @no_cv = ConditionVariable.new
347
+
348
+ @key = nil
349
+
350
+ @status = nil
351
+ @status_mutex = Mutex.new
352
+ @status_cv = ConditionVariable.new
353
+
354
+ @export_mon = ExportMonitor
355
+ @pop_cv = @export_mon.new_cv
356
+ @export_cv = @export_mon.new_cv
357
+
358
+ case @queuing_policy
359
+ when Hash
360
+ klass = eval("#{@queuing_policy[:queuing_class]}")
361
+ mon = @export_mon.new_mon
362
+ cv = mon.new_cv
363
+ @queue = klass.new(@queuing_policy, mon, cv)
364
+ else
365
+ @queue = @queuing_policy
366
+ end
367
+
368
+ Log::debug(self, "Using Buffer: #{@queue.class}")
369
+
370
+ end
371
+
372
+ def log_id
373
+ "Export[#{@njob_id}[#{@no}:#{@key}]]"
374
+ end
375
+
376
+ def no
377
+ @no_mutex.synchronize do
378
+ while !@no
379
+ Log::debug(self, "Wait until set @no.") if @DEBUG_PORT_WAIT
380
+ @no_cv.wait(@no_mutex)
381
+ Log::debug(self, "End: Wait until set @no") if @DEBUG_PORT_WAIT
382
+ end
383
+ @no
384
+ end
385
+ end
386
+
387
+ attr_accessor :njob_id
388
+
389
+ def no=(no)
390
+ @no_mutex.synchronize do
391
+ @no=no
392
+ @no_cv.broadcast
393
+ end
394
+ end
395
+
396
+ attr_accessor :key
397
+ def add_key(key)
398
+ @key = key
399
+ end
400
+
401
+ def output?
402
+ @output_mutex.synchronize do
403
+ @output
404
+ end
405
+ end
406
+
407
+ def output
408
+ @output_mutex.synchronize do
409
+ while !@output
410
+ Log::debug(self, "Wait until set @output") if @DEBUG_PORT_WAIT
411
+ @output_cv.wait(@output_mutex)
412
+ Log::debug(self, "End: Wait until set @output") if @DEBUG_PORT_WAIT
413
+ end
414
+ @output
415
+ end
416
+ end
417
+
418
+ def output=(output)
419
+ @output_mutex.synchronize do
420
+ @output = output
421
+ @output_cv.broadcast
422
+ end
423
+
424
+ start_export
425
+ nil
426
+ end
427
+
428
+ def output_no_import=(n)
429
+ if output?
430
+ @output.no_import = n
431
+ else
432
+ # 遅延設定(shuffleのため)
433
+ Thread.start do
434
+ Log::debug(self, "@output is nil. Enter delay setting.") if @DEBUG_PORT_WAIT
435
+ output.no_import = n
436
+ Log::debug(self, "Exit delay setting.") if @DEBUG_PORT_WAIT
437
+ end
438
+ n
439
+ end
440
+ end
441
+
442
+ def push(e)
443
+ @queue.push e
444
+ nil
445
+ end
446
+
447
+ def push_buf(buf)
448
+ if @queue.respond_to?(:push_all)
449
+ @queue.push_all(buf)
450
+ nil
451
+ else
452
+ begin
453
+ buf.each{|e| @queue.push e}
454
+ nil
455
+ rescue
456
+ Log::debug_exception(self)
457
+ raise
458
+ end
459
+ end
460
+ end
461
+
462
+ def push_delayed_element(&block)
463
+ @queue.push Import::CTLTOKEN_DELAYED_ELEMENT.new(&block)
464
+ end
465
+
466
+ def fib_pop
467
+ @export_mon.synchronize do
468
+ e = nil
469
+ #@export_mon.entry{e = @queue.pop; @pop_cv.signal}
470
+ Thread.start do
471
+ @export_mon.synchronize do
472
+ e = @queue.pop
473
+ @pop_cv.signal
474
+ end
475
+ end
476
+ @pop_cv.wait_until{e}
477
+ e
478
+ end
479
+ end
480
+
481
+ def fib_pop_all
482
+ @export_mon.synchronize do
483
+ e = nil
484
+ #@export_mon.entry{e = @queue.pop; @pop_cv.signal}
485
+ Thread.start do
486
+ @export_mon.synchronize do
487
+ e = @queue.pop_all
488
+ @pop_cv.signal
489
+ end
490
+ end
491
+ @pop_cv.wait_until{e}
492
+ e
493
+ end
494
+ end
495
+
496
+
497
+ # def push(e)
498
+ # # @output_buf_mutex.synchronize do
499
+ # @output_buf.push e
500
+ # if @output_buf.size > 1000 || e == END_OF_STREAM
501
+ # @output_buf_cv.signal
502
+ # end
503
+ # # end
504
+ # # @queue.push e
505
+ # end
506
+
507
+ def start_export0
508
+ @export_mon.entry do
509
+ if bug49 = CONF.DEBUG_BUG49
510
+ # BUG#49用
511
+ Log::debug(self, "export START")
512
+ mod = CONF.LOG_IMPORT_NTIMES_POP
513
+ n = 0
514
+ end
515
+ self.status = :EXPORT
516
+
517
+ @export_mon.synchronize do
518
+ # while (e = fib_pop) != END_OF_STREAM
519
+ while (e = @queue.pop) != END_OF_STREAM
520
+ if bug49
521
+ # BUG#49用
522
+ n += 1
523
+ if (n % mod == 0 || n < 3)
524
+ Log::debug(self, "EXPORT n: #{n}")
525
+ end
526
+ end
527
+ begin
528
+ if PORT_KEEP_IDENTITY_CLASS_SET[e.class]
529
+ @output.asyncronus_send_with_callback(:push_keep_identity, e){
530
+ @export_mon.synchronize{@export_cv.broadcast}
531
+ }
532
+ else
533
+ @output.asyncronus_send_with_callback(:push, e) {
534
+ @export_mon.synchronize{@export_cv.broadcast}
535
+ }
536
+ end
537
+ @export_cv.wait
538
+ rescue DeepConnect::SessionServiceStopped
539
+ Log::debug_exception(self)
540
+ raise
541
+ rescue
542
+ Log::debug_exception(self)
543
+ raise
544
+ end
545
+ if bug49 && (n % mod == mod - 1 || n < 3)
546
+ Log::debug(self, "EXPORT e: #{n - mod + 1}")
547
+ end
548
+ @export_mon.yield
549
+ end
550
+ end
551
+ if bug49
552
+ # BUG#49用
553
+ Log::debug(self, "export PREFINISH0")
554
+ end
555
+ @output.push END_OF_STREAM
556
+ if bug49
557
+ Log::debug(self, "export PREFINISH1")
558
+ end
559
+ self.status = END_OF_STREAM
560
+ if bug49
561
+ Log::debug(self, "export FINISH")
562
+ end
563
+ end
564
+ nil
565
+ end
566
+
567
+ def start_export
568
+ Log::debug(self, "START EXPORT")
569
+
570
+ unless @queue.respond_to?(:pop_all)
571
+ return start_export0
572
+ end
573
+
574
+ if @queue.respond_to?(:pop_raw)
575
+ return start_export_raw
576
+ end
577
+
578
+ @export_mon.entry do
579
+ if bug49 = CONF.DEBUG_BUG49
580
+ # BUG#49用
581
+ Log::debug(self, "export key=#{@key}: START")
582
+ n = 0
583
+ mod = CONF.LOG_IMPORT_NTIMES_POP
584
+ limit = mod
585
+ end
586
+ # @export_mon.synchronize do
587
+ while (pops = @queue.pop_all).last != END_OF_STREAM
588
+ # while (pops = fib_pop_all).last != END_OF_STREAM
589
+
590
+ if bug49
591
+ n += pops.size
592
+ if n >= limit
593
+ Log::debug(self, "EXPORT key=#{@key} n: #{n}")
594
+ while limit > n
595
+ limit += mod
596
+ end
597
+ end
598
+ end
599
+
600
+ begin
601
+ export_elements(pops)
602
+ rescue DeepConnect::SessionServiceStopped
603
+ Log::debug_exception(self)
604
+ raise
605
+ rescue
606
+ Log::debug_exception(self)
607
+ raise
608
+ end
609
+ @export_mon.yield
610
+ end
611
+ export_elements(pops)
612
+ # end
613
+
614
+ if bug49
615
+ # BUG#49用
616
+ Log::debug(self, "export key=#{@key}: PREFINISH0")
617
+ # @output.push END_OF_STREAM
618
+ Log::debug(self, "export key=#{@key}: PREFINISH1")
619
+ end
620
+ self.status = END_OF_STREAM
621
+
622
+ Log::debug(self, "FINISH EXPORT")
623
+ end
624
+ nil
625
+ end
626
+
627
+
628
+ # def export_elements(elements)
629
+ # max = CONF.POSTQUEUE_MAX_TRANSFER_SIZE
630
+
631
+ # if elements.find{|e| PORT_KEEP_IDENTITY_CLASS_SET[e.class]}
632
+ # # elements.each do |e|
633
+ # # @output.push e
634
+ # # end
635
+
636
+ # buf = []
637
+ # elements.each do |e|
638
+ # if PORT_KEEP_IDENTITY_CLASS_SET[e.class]
639
+ # start = 0
640
+ # while buf.size > start
641
+ # @output.push_buf buf[start, start+max]
642
+ # start += max
643
+ # end
644
+ # @output.push e
645
+ # buf = buf.clear
646
+ # else
647
+ # buf.push e
648
+ # end
649
+ # end
650
+ # start = 0
651
+ # while buf.size > start
652
+ # @output.push_buf buf[start, start+max]
653
+ # start += max
654
+ # end
655
+ # buf.clear
656
+ # else
657
+ # start = 0
658
+ # while elements.size > start
659
+ # @output.push_buf elements[start, start+max]
660
+ # start += max
661
+ # end
662
+ # elements.clear
663
+ # end
664
+ # end
665
+
666
+ def export_elements(elements)
667
+ start = 0
668
+ string_p = nil
669
+ elements.each_with_index do |e, idx|
670
+
671
+ if @STR_TRANSFAR
672
+ if e.class == String
673
+ string_p = true
674
+ elsif string_p.nil?
675
+ string_p = false
676
+ elsif string_p
677
+ exports_elements_sub_str(elements, start, idx-1)
678
+ start = idx
679
+ string_p = nil
680
+ end
681
+ end
682
+
683
+ if PORT_KEEP_IDENTITY_CLASS_SET[e.class]
684
+ exports_elements_sub(elements, start, idx-1)
685
+ sended = nil
686
+ @export_mon.synchronize do
687
+ @output.asynchronus_send_with_callback(:push_keep_identity, e){
688
+ @export_mon.synchronize do
689
+ sended = true
690
+ @export_cv.broadcast
691
+ end
692
+ }
693
+ @export_cv.wait_until{sended}
694
+ end
695
+ start = idx + 1
696
+ end
697
+ end
698
+ # @output.push_buf elements
699
+ if string_p
700
+ exports_elements_sub_str(elements, start, elements.size-1)
701
+ else
702
+ exports_elements_sub(elements, start, elements.size-1)
703
+ end
704
+ elements.clear
705
+ end
706
+
707
+ def exports_elements_sub(elements, start, last, max = @max_chunk)
708
+ while last >= start
709
+ len = [max, last - start + 1].min
710
+ @export_mon.synchronize do
711
+ sended = nil
712
+ @output.asynchronus_send_with_callback(:push_buf, elements[start, len]){
713
+ @export_mon.synchronize do
714
+ sended = true
715
+ @export_cv.broadcast
716
+ end
717
+ }
718
+ @export_cv.wait_until{sended}
719
+ end
720
+ start += len
721
+ end
722
+ end
723
+
724
+ def exports_elements_sub_str(elements, start, last, max = @max_chunk)
725
+ while last >= start
726
+ len = [max, last - start + 1].min
727
+ bigstr = elements[start, len].collect{|e|
728
+ e.gsub(/[\\\t]/){|v| v == "\t" ? "\\t" : '\\\\'}
729
+ }.join("\t")
730
+ @export_mon.synchronize do
731
+ sended = nil
732
+ @output.asynchronus_send_with_callback(:push_strings, bigstr) {
733
+ @export_mon.synchronize do
734
+ sended = true
735
+ @export_cv.broadcast
736
+ end
737
+ }
738
+ @export_cv.wait_until{sended}
739
+ end
740
+ start += len
741
+ end
742
+ end
743
+
744
+
745
+ def start_export_raw
746
+ Log::debug(self, "START EXPORT(RAW MODE)")
747
+
748
+ @export_mon.entry do
749
+ if bug49 = CONF.DEBUG_BUG49
750
+ # BUG#49用
751
+ Log::debug(self, "export key=#{@key}: START")
752
+ n = 0
753
+ mod = CONF.LOG_IMPORT_NTIMES_POP
754
+ limit = mod
755
+ end
756
+ # @export_mon.synchronize do
757
+ while (raw = @queue.pop_raw) != END_OF_STREAM
758
+ if bug49
759
+ n += pops.size
760
+ if n >= limit
761
+ Log::debug(self, "EXPORT key=#{@key} raw_size: #{n}")
762
+ while limit > n
763
+ limit += mod
764
+ end
765
+ end
766
+ end
767
+
768
+ begin
769
+ export_elements_raw(raw)
770
+ rescue DeepConnect::SessionServiceStopped
771
+ Log::debug_exception(self)
772
+ raise
773
+ rescue
774
+ Log::debug_exception(self)
775
+ raise
776
+ end
777
+ @export_mon.yield
778
+ end
779
+ export_elements_raw(raw)
780
+ # end
781
+
782
+ if bug49
783
+ # BUG#49用
784
+ Log::debug(self, "export key=#{@key}: PREFINISH0")
785
+ # @output.push END_OF_STREAM
786
+ Log::debug(self, "export key=#{@key}: PREFINISH1")
787
+ end
788
+ self.status = END_OF_STREAM
789
+
790
+ Log::debug(self, "FINISH EXPORT")
791
+ end
792
+ nil
793
+
794
+ end
795
+
796
+ def export_elements_raw(raw)
797
+ @export_mon.synchronize do
798
+ sended = nil
799
+ @output.asynchronus_send_with_callback(:push_raw, raw) {
800
+ @export_mon.synchronize do
801
+ sended = true
802
+ @export_cv.broadcast
803
+ end
804
+ }
805
+ @export_cv.wait_until{sended}
806
+ end
807
+ end
808
+
809
+
810
+ # def start_export
811
+ # Thread.start do
812
+ # self.status = :Export
813
+ # loop do
814
+ # Buf = Nil
815
+ # @Output_Buf_Mutex.Synchronize Do
816
+ # #P "Aaaaaaaaaaa:2"
817
+ # @Output_Buf_Cv.Wait(@Output_Buf_Mutex)
818
+ # #P "Aaaaaaaaaaa:3"
819
+ # Buf = @Output_Buf
820
+ # #P "Aaaaaaaaaaa:4"
821
+ # @Output_Buf = []
822
+ # #P "Aaaaaaaaaaa:5"
823
+ # End
824
+ # #P "Aaaaaaaaaaa:6"
825
+ # #Begin
826
+ # @Output.Push_Buf Buf
827
+ # #Rescue
828
+ # # P $@, $!
829
+ # #End
830
+ # #P "Aaaaaaaaaaa:7"
831
+ # Break If Buf.Last == End_Of_Stream
832
+ # #P "Aaaaaaaaaaa:8"
833
+ # End
834
+ # #P "Aaaaaaaaaaa:9"
835
+
836
+ # # While (E = @Output_Buf.Pop) != End_Of_Stream
837
+ # # Begin
838
+ # # If Port_Keep_Identity_Class_Set[E.Class]
839
+ # # @Output.Push_Keep_Identity(E)
840
+ # # Else
841
+ # # Buf.Push E
842
+ # # If Buf.Size > 1000
843
+ # # @Output.Push_Buf Buf.Join("")
844
+ # # Buf = []
845
+ # # End
846
+ # # # @Output.Push E
847
+ # # End
848
+ # # Rescue Deepconnect::Sessionservicestopped
849
+ # # Debug::Debug_Exception(Self)
850
+ # # Raise
851
+ # # End
852
+ # # End
853
+ # # If Buf.Size > 0
854
+ # # @Output.Push_Buf Buf.Join("")
855
+ # # End
856
+ # @Output.Push End_Of_Stream
857
+ # Self.Status = End_Of_Stream
858
+ # End
859
+ # Nil
860
+ # End
861
+
862
+ # ここから, 後で要検討
863
+ def status=(val)
864
+ @status_mutex.synchronize do
865
+ @status_cv.broadcast{@status = val}
866
+ end
867
+ end
868
+
869
+ def wait_finish(cv)
870
+ @status_mutex.synchronize do
871
+ while @status != END_OF_STREAM
872
+ @status_cv.wait(@status_mutex)
873
+ end
874
+ # @status = :EXPORT_FINISH
875
+ end
876
+ end
877
+
878
+ def fib_wait_finish(cv)
879
+ @status_cv = cv
880
+ cv.wait_until{@status == END_OF_STREAM}
881
+ end
882
+ # ここまで
883
+
884
+ end
885
+
886
+ module OnMemoryQueue
887
+ def self.new(policy, queues_mon = nil, queues_cv = nil)
888
+ if queues_mon
889
+ raise "OnMemoryQueueはfiberをサポートしていません"
890
+ end
891
+ Queue.new
892
+ end
893
+ end
894
+
895
+ class PoolQueue
896
+ def initialize(policy, queue_mon = Monitor.new, queue_cv = queue_mon.new_cond)
897
+ @policy = policy
898
+
899
+ @queue_threshold = CONF.POOLQUEUE_POOL_THRESHOLD
900
+
901
+ @queue = []
902
+ @queue_mon = queue_mon
903
+ @queue_cv = queue_cv
904
+ end
905
+
906
+ def push(e)
907
+ @queue_mon.synchronize do
908
+ @queue.push e
909
+ if @queue.size >= @queue_threshold ||
910
+ e == :END_OF_STREAM ||
911
+ e == Import::SET_NO_IMPORT
912
+ @queue_cv.broadcast
913
+ end
914
+ end
915
+ end
916
+
917
+ def push_all(buf)
918
+ @queue_mon.synchronize do
919
+ @queue.concat buf
920
+ if @queue.size >= @queue_threshold || @queue.last == :END_OF_STREAM
921
+ @queue_cv.broadcast
922
+ end
923
+ end
924
+ end
925
+
926
+ def pop
927
+ @queue_mon.synchronize do
928
+ @queue_cv.wait_while{@queue.empty?}
929
+ @queue.shift
930
+ end
931
+ end
932
+
933
+ def pop_all
934
+ @queue_mon.synchronize do
935
+ @queue_cv.wait_while{@queue.size < @queue_threshold && @queue.last != :END_OF_STREAM}
936
+ # buf = @queue.dup
937
+ # @queue.clear
938
+ buf, @queue = @queue, []
939
+ buf
940
+ end
941
+ end
942
+ end
943
+
944
+ class SizedQueue
945
+ extend Forwardable
946
+
947
+ def initialize(policy, queues_mon = nil, queues_cv = nil)
948
+ if queues_mon
949
+ raise "OnMemoryQueueはfiberをサポートしていません"
950
+ end
951
+
952
+ size = policy[:size]
953
+ size ||= CONF.ONMEMORY_SIZEDQUEUE_SIZE
954
+ @queue = SizedQueue.new(size)
955
+ end
956
+
957
+ def_delegator :@queue, :push
958
+ def_delegator :@queue, :pop
959
+ end
960
+ OnMemorySizedQueue = SizedQueue
961
+
962
+ class SizedPoolQueue<PoolQueue
963
+ def initialize(policy, queue_mon = Monitor.new, queue_cv = queues_mon.new_cond)
964
+ super
965
+ @max_size = policy[:size]
966
+ @max_size ||= CONF.ONMEMORY_SIZEDQUEUE_SIZE
967
+
968
+ @pop_cv = @queue_cv
969
+ @push_cv = @queue_mon.new_cond
970
+ end
971
+
972
+ def push(e)
973
+ @queue_mon.synchronize do
974
+ @push_cv.wait_while{@queue.size > @max_size}
975
+ @queue.push e
976
+ if @queue.size >= @queue_threshold ||
977
+ e == :END_OF_STREAM ||
978
+ e == Import::SET_NO_IMPORT
979
+ @pop_cv.broadcast
980
+ end
981
+ end
982
+ end
983
+
984
+ def push_all(buf)
985
+ @queue_mon.synchronize do
986
+ @push_cv.wait_while{@queue.size > @max_size}
987
+ @queue.concat buf
988
+ if @queue.size >= @queue_threshold || @queue.last == :END_OF_STREAM
989
+ @pop_cv.broadcast
990
+ end
991
+ end
992
+ end
993
+
994
+ def pop
995
+ e = super
996
+ @push_cv.broadcast
997
+ e
998
+ end
999
+
1000
+ def pop_all
1001
+ buf = super
1002
+ @push_cv.broadcast
1003
+ buf
1004
+ end
1005
+ end
1006
+ OnMemorySizedPoolQueue = SizedPoolQueue
1007
+
1008
+ class ChunkedPoolQueue
1009
+ # multi push threads single pop thread
1010
+ def initialize(policy, queues_mon = Monitor.new, queues_cv = queues_mon.new_cond)
1011
+ @policy = policy
1012
+
1013
+ @queue_threshold = CONF.POOLQUEUE_POOL_THRESHOLD
1014
+ @queue_max = CONF.POSTQUEUE_MAX_TRANSFER_SIZE
1015
+
1016
+ @push_queue = []
1017
+ @push_queue_mutex = Mutex.new
1018
+
1019
+ @queues = []
1020
+ @queues_mon = queues_mon
1021
+ @queues_cv = queues_cv
1022
+
1023
+ @pop_queue = nil
1024
+ # @pop_queue_mutex = Mutex.new
1025
+ end
1026
+
1027
+ attr_accessor :fib_cv
1028
+
1029
+ def push(e)
1030
+ @push_queue_mutex.synchronize do
1031
+ @push_queue.push e
1032
+ if @push_queue.size >= @queue_threshold ||
1033
+ e == :END_OF_STREAM ||
1034
+ e == Import::SET_NO_IMPORT
1035
+ @queues_mon.synchronize do
1036
+ @queues.push @push_queue
1037
+ @push_queue = []
1038
+ @queues_cv.broadcast
1039
+ end
1040
+ end
1041
+ end
1042
+ end
1043
+
1044
+ def push_all(buf)
1045
+ @push_queue_mutex.synchronize do
1046
+ @push_queue.concat buf
1047
+ if @push_queue.size > @queue_threshold ||
1048
+ @push_queue.last == :END_OF_STREAM
1049
+ @queues_mon.synchronize do
1050
+ @queues.push @push_queue
1051
+ @push_queue = []
1052
+ @queues_cv.broadcast
1053
+ end
1054
+ end
1055
+ end
1056
+ end
1057
+
1058
+ def pop
1059
+ # @pop_queue.synchronize do
1060
+ while !@pop_queue || @pop_queue.empty?
1061
+ @queues_mon.synchronize do
1062
+ @queues_cv.wait_until{@pop_queue = @queues.shift}
1063
+ end
1064
+ end
1065
+ e = @pop_queue.shift
1066
+ @pop_queue = nil if @pop_queue.empty?
1067
+ e
1068
+ end
1069
+
1070
+ def pop_all
1071
+ # @pop_queue.synchronize do
1072
+ while !@pop_queue
1073
+ @queues_mon.synchronize do
1074
+ @queues_cv.wait_until{@pop_queue = @queues.shift}
1075
+ end
1076
+ end
1077
+ buf, @pop_queue = @pop_queue, nil
1078
+ buf
1079
+ # end
1080
+ end
1081
+ end
1082
+
1083
+ class ChunkedSizedPoolQueue<ChunkedPoolQueue
1084
+ def initialize(policy, queues_mon = Monitor.new, queues_cv = queues_mon.new_cond)
1085
+ super
1086
+ @max_size = policy[:size]
1087
+ @max_size ||= CONF.ONMEMORY_SIZEDQUEUE_SIZE
1088
+
1089
+ @queue_size = 0
1090
+
1091
+ @pop_cv = @queues_cv
1092
+ @push_cv = @queues_mon.new_cond
1093
+ end
1094
+
1095
+ def push(e)
1096
+ @queues_mon.synchronize do
1097
+ @push_cv.wait_while{@queue_size > @max_size}
1098
+ @queue_size += 1
1099
+ end
1100
+ super
1101
+ end
1102
+
1103
+ def push_all(buf)
1104
+ @queues_mon.synchronize do
1105
+ @push_cv.wait_while{@queue_size > @max_size}
1106
+ @queue_size += buf.size
1107
+ end
1108
+ super
1109
+ end
1110
+
1111
+ def pop
1112
+ e = super
1113
+ @queues_mon.synchronize do
1114
+ @queue_size -= 1
1115
+ @push_cv.broadcast if @queue_size <= @max_size
1116
+ end
1117
+ e
1118
+ end
1119
+
1120
+ def pop_all
1121
+ buf = super
1122
+ @queues_mon.synchronize do
1123
+ @queue_size -= buf.size
1124
+ @push_cv.broadcast if @queue_size <= @max_size
1125
+ end
1126
+ buf
1127
+ end
1128
+ end
1129
+
1130
+ class FileBufferdQueue
1131
+ def initialize(policy, queue_mon = Monitor.new, queue_cv = queue_mon.new_cond)
1132
+
1133
+ @policy = policy
1134
+ @threshold = policy[:threshold]
1135
+ @threshold ||= CONF.FILEBUFFEREDQUEUE_THRESHOLD
1136
+
1137
+ @push_queue = []
1138
+ @pop_queue = @push_queue
1139
+ @buffers_queue = nil
1140
+
1141
+ @queue_mon = queue_mon
1142
+ @queue_cv = queue_cv
1143
+ end
1144
+
1145
+ def push(e)
1146
+ @queue_mon.synchronize do
1147
+ @push_queue.push e
1148
+ @queue_cv.broadcast
1149
+
1150
+ if @push_queue.size >= @threshold
1151
+ if @push_queue.equal?(@pop_queue)
1152
+ @push_queue = []
1153
+ else
1154
+ store_2ndmemory(@push_queue)
1155
+ @push_queue = []
1156
+ end
1157
+ end
1158
+ end
1159
+ end
1160
+
1161
+ def pop
1162
+ @queue_mon.synchronize do
1163
+ while @pop_queue.empty?
1164
+ if @pop_queue.equal?(@push_queue)
1165
+ @queue_cv.wait
1166
+ elsif @buffers_queue.nil?
1167
+ @pop_queue = @push_queue
1168
+ elsif @buffers_queue.empty?
1169
+ @pop_queue = @push_queue
1170
+ @push_queue = []
1171
+ @buffers_queue = nil
1172
+ else
1173
+ @pop_queue = restore_2ndmemory
1174
+ end
1175
+ end
1176
+ @pop_queue.shift
1177
+ end
1178
+ end
1179
+
1180
+ def pop_all
1181
+ @queue_mon.synchronize do
1182
+ while @pop_queue.empty?
1183
+ if @pop_queue.equal?(@push_queue)
1184
+ @queue_cv.wait
1185
+ elsif @buffers_queue.nil?
1186
+ @pop_queue = @push_queue
1187
+ elsif @buffers_queue.empty?
1188
+ @pop_queue = @push_queue
1189
+ @push_queue = []
1190
+ @buffers_queue = nil
1191
+ else
1192
+ @pop_queue = restore_2ndmemory
1193
+ end
1194
+ end
1195
+ pops = @pop_queue.dup
1196
+ @pop_queue.clear
1197
+ pops
1198
+ end
1199
+ end
1200
+
1201
+ def init_2ndmemory
1202
+ @buffer_dir = @policy[:buffer_dir]
1203
+ @buffer_dir ||= CONF.TMP_DIR
1204
+
1205
+ @buffers_queue = []
1206
+ end
1207
+
1208
+ def open_2ndmemory(&block)
1209
+ unless @buffers_queue
1210
+ init_2ndmemory
1211
+ end
1212
+ buffer = FastTempfile.open("port-buffer-", @buffer_dir)
1213
+ begin
1214
+ yield buffer.io
1215
+ ensure
1216
+ buffer.close
1217
+ end
1218
+ @buffers_queue.push buffer
1219
+ buffer
1220
+ end
1221
+
1222
+ def store_2ndmemory(ary)
1223
+ # Log::info(self, "start store")
1224
+ open_2ndmemory do |io|
1225
+ # while !ary.empty?
1226
+ # e = ary.shift
1227
+ # Marshal.dump(e, io)
1228
+ # end
1229
+ Marshal.dump(ary, io)
1230
+ end
1231
+ # Log::info(self, "end store")
1232
+ end
1233
+
1234
+ def restore_2ndmemory
1235
+ buf = @buffers_queue.shift
1236
+ io = buf.open
1237
+ # queue = []
1238
+ # begin
1239
+ # loop do
1240
+ # queue.push Marshal.load(io)
1241
+ # end
1242
+ # rescue
1243
+ # end
1244
+ queue = Marshal.load(io)
1245
+ buf.close!
1246
+ # Log::info(self, "end restore")
1247
+ queue
1248
+ end
1249
+ end
1250
+
1251
+ class ChunkedFileBufferdQueue
1252
+ def initialize(policy, queue_mon = Monitor.new, queue_cv = queue_mon.new_cond)
1253
+ @policy = policy
1254
+ @threshold = policy[:threshold]
1255
+ @threshold ||= CONF.FILEBUFFEREDQUEUE_THRESHOLD
1256
+
1257
+ @push_queue = []
1258
+ @push_queue_mutex = Mutex.new
1259
+
1260
+ @buffers_queue = nil
1261
+ @buffers_queue_mon = queue_mon
1262
+ @buffers_queue_cv = queue_cv
1263
+
1264
+ @pop_queue = nil
1265
+ end
1266
+
1267
+ def push(e)
1268
+ @push_queue_mutex.synchronize do
1269
+ @push_queue.push e
1270
+ if @push_queue.size >= @threshold ||
1271
+ e == :END_OF_STREAM ||
1272
+ e == Import::SET_NO_IMPORT
1273
+ @buffers_queue_mon.synchronize do
1274
+ if @pop_queue
1275
+ store_2ndmemory(@push_queue)
1276
+ else
1277
+ @pop_queue = @push_queue
1278
+ end
1279
+ @push_queue = []
1280
+ @buffers_queue_cv.broadcast
1281
+ end
1282
+ end
1283
+ end
1284
+ end
1285
+
1286
+ def push_all(buf)
1287
+ @push_queue_mutex.synchronize do
1288
+ @push_queue.concat buf
1289
+ if @push_queue.size > @threshold ||
1290
+ @push_queue.last == :END_OF_STREAM
1291
+ @buffers_queue_mon.synchronize do
1292
+ if @pop_queue
1293
+ store_2ndmemory(@push_queue)
1294
+ else
1295
+ @pop_queue = @push_queue
1296
+ end
1297
+ @push_queue = []
1298
+ @buffers_queue_cv.broadcast
1299
+ end
1300
+ end
1301
+ end
1302
+ end
1303
+
1304
+ def pop
1305
+ while !@pop_queue || @pop_queue.empty?
1306
+ @buffers_queue_mon.synchronize do
1307
+ if @buffers_queue
1308
+ @pop_queue = restore_2ndmemory
1309
+ else
1310
+ @buffers_queue_cv.wait
1311
+ end
1312
+ end
1313
+ end
1314
+ #e = @pop_queue.shift
1315
+ #@pop_queue = nil if @pop_queue.empty?
1316
+ #@e
1317
+ @pop_queue.shift
1318
+ end
1319
+
1320
+ def pop_all
1321
+ while !@pop_queue || @pop_queue.empty?
1322
+ @buffers_queue_mon.synchronize do
1323
+ if @buffers_queue
1324
+ if @buffers_queue.empty?
1325
+ @buffers_queue_cv.wait
1326
+ else
1327
+ @pop_queue = restore_2ndmemory
1328
+ end
1329
+ else
1330
+ @buffers_queue_cv.wait
1331
+ end
1332
+ end
1333
+ end
1334
+ #buf, @pop_queue = @pop_queue, nil
1335
+ #buf
1336
+
1337
+ buf, @pop_queue = @pop_queue, []
1338
+ buf
1339
+ end
1340
+
1341
+ def init_2ndmemory
1342
+ @buffer_dir = @policy[:buffer_dir]
1343
+ @buffer_dir ||= CONF.TMP_DIR
1344
+
1345
+ @buffers_queue = []
1346
+ end
1347
+
1348
+ def open_2ndmemory(&block)
1349
+ unless @buffers_queue
1350
+ init_2ndmemory
1351
+ end
1352
+ buffer = FastTempfile.open("port-buffer-", @buffer_dir)
1353
+ begin
1354
+ yield buffer.io
1355
+ ensure
1356
+ buffer.close
1357
+ end
1358
+ @buffers_queue.push buffer
1359
+ buffer
1360
+ end
1361
+
1362
+ def store_2ndmemory(ary)
1363
+ # Log::debug(self, "start store")
1364
+ open_2ndmemory do |io|
1365
+ Marshal.dump(ary, io)
1366
+ end
1367
+ # Log::debug(self, "end store")
1368
+ end
1369
+
1370
+ def restore_2ndmemory
1371
+ # Log::debug(self, "start restore")
1372
+ buf = @buffers_queue.shift
1373
+ io = buf.open
1374
+ queue = Marshal.load(io)
1375
+ buf.close!
1376
+ # Log::debug(self, "end restore")
1377
+ queue
1378
+ end
1379
+ end
1380
+
1381
+ class SortedQueue
1382
+ def initialize(policy, queue_mon = Monitor.new, queue_cv = queue_mon.new_cond)
1383
+ @policy = policy
1384
+
1385
+ @pool_threshold = policy[:pool_threshold]
1386
+ @pool_threshold ||= CONF.SORTEDQUEUE_POOL_THRESHOLD
1387
+
1388
+ @threshold = policy[:threshold]
1389
+ @threshold ||= CONF.SORTEDQUEUE_THRESHOLD
1390
+
1391
+ @push_queue = []
1392
+ @pop_queue = nil
1393
+ @buffers = nil
1394
+
1395
+ @queue_mon = queue_mon
1396
+ @queue_cv = queue_cv
1397
+
1398
+ @sort_by = policy[:sort_by]
1399
+ @sort_by ||= CONF.SORTEDQUEUE_SORTBY
1400
+
1401
+ if @sort_by.kind_of?(String)
1402
+ @sort_by = eval("proc{#{@sort_by}}")
1403
+ end
1404
+ end
1405
+
1406
+ def push(e)
1407
+ @queue_mon.synchronize do
1408
+ @push_queue.push e
1409
+ if e == :END_OF_STREAM
1410
+ @push_queue.pop
1411
+ if @buffers
1412
+ store_2ndmemory(@push_queue)
1413
+ @push_queue = []
1414
+ @pop_queue = []
1415
+ else
1416
+ begin
1417
+ @pop_queue = @push_queue.sort_by{|e| @sort_by.call(e)}
1418
+ @pop_queue.push :END_OF_STREAM
1419
+ rescue
1420
+ Log::debug_exception
1421
+ end
1422
+ end
1423
+ @queue_cv.broadcast
1424
+ end
1425
+ if @push_queue.size >= @threshold
1426
+ store_2ndmemory(@push_queue)
1427
+ @push_queue = []
1428
+ end
1429
+ end
1430
+ end
1431
+
1432
+ def pop
1433
+ @queue_mon.synchronize do
1434
+ @queue_cv.wait_while{@pop_queue.nil?}
1435
+
1436
+ if @buffers.nil?
1437
+ #Log::debug(self, @pop_queue.inspect)
1438
+ return @pop_queue.shift
1439
+ else
1440
+ pop_2ndmemory
1441
+ end
1442
+ end
1443
+ end
1444
+
1445
+ def pop_all
1446
+ buf = []
1447
+ while e = pop
1448
+ buf.push e
1449
+ return buf if buf.size > @pool_threshold
1450
+ end
1451
+ buf
1452
+ end
1453
+
1454
+ # def pop_all
1455
+ # @queue_mutex.synchronize do
1456
+ # while @pop_queue.empty?
1457
+ # if @pop_queue.equal?(@push_queue)
1458
+ # @queue_cv.wait(@queue_mutex)
1459
+ # elsif @buffers_queue.nil?
1460
+ # @pop_queue = @push_queue
1461
+ # elsif @buffers_queue.empty?
1462
+ # @pop_queue = @push_queue
1463
+ # @push_queue = []
1464
+ # @buffers_queue = nil
1465
+ # else
1466
+ # @pop_queue = restore_2ndmemory
1467
+ # end
1468
+ # end
1469
+ # pops = @pop_queue.dup
1470
+ # @pop_queue.clear
1471
+ # pops
1472
+ # end
1473
+ # end
1474
+
1475
+
1476
+ def init_2ndmemory
1477
+ require "tempfile"
1478
+
1479
+ @buffer_dir = @policy[:buffer_dir]
1480
+ @buffer_dir ||= CONF.TMP_DIR
1481
+
1482
+ @buffers = []
1483
+ @merge_io = nil
1484
+ end
1485
+
1486
+ def open_2ndmemory(&block)
1487
+ unless @buffers
1488
+ init_2ndmemory
1489
+ end
1490
+ buffer = Tempfile.open("port-buffer-", @buffer_dir)
1491
+ begin
1492
+ # ruby BUG#2390の対応のため.
1493
+ # yield buffer
1494
+ yield buffer.instance_eval{@tmpfile}
1495
+ ensure
1496
+ buffer.close
1497
+ end
1498
+ @buffers.push buffer
1499
+ buffer
1500
+ end
1501
+
1502
+ def store_2ndmemory(ary)
1503
+ Log::debug(self, "start store: ")
1504
+ open_2ndmemory do |io|
1505
+ ary = ary.sort_by{|e| @sort_by.call(e)}
1506
+ while !ary.empty?
1507
+ e = ary.shift
1508
+ Marshal.dump(e, io)
1509
+ end
1510
+ end
1511
+ Log::debug(self, "end store")
1512
+ end
1513
+
1514
+ def pop_2ndmemory
1515
+ unless @merge_io
1516
+ @buffers.each{|tf| tf.open}
1517
+ @merge_io = @buffers.map{|io|
1518
+ e = nil
1519
+ begin
1520
+ e = Marshal.load(io)
1521
+ rescue EOFError
1522
+ io.close!
1523
+ end
1524
+ [io, e]}.select{|io, v| !v.nil?}.sort_by{|io, v| @sort_by.call(v)}
1525
+ end
1526
+ unless io_min = @merge_io.shift
1527
+ return :END_OF_STREAM
1528
+ end
1529
+
1530
+ io, min = io_min
1531
+ begin
1532
+ e = Marshal.load(io)
1533
+ @merge_io.push [io, e]
1534
+ @merge_io = @merge_io.sort_by{|io, e| @sort_by.call(e)}
1535
+ rescue EOFError
1536
+ io.close!
1537
+ end
1538
+ min
1539
+ end
1540
+ end
1541
+
1542
+ class OnMemorySortedQueue
1543
+ def initialize(policy, queue_mon = Monitor.new, queue_cv = queue_mon.new_cond)
1544
+ @policy = policy
1545
+
1546
+ @pool_threshold = policy[:pool_threshold]
1547
+ @pool_threshold ||= CONF.SORTEDQUEUE_POOL_THRESHOLD
1548
+
1549
+ @push_queue = []
1550
+ @pop_queue = nil
1551
+
1552
+ @queue_mutex = queue_mon
1553
+ @queue_cv = queue_cv
1554
+
1555
+ @sort_by = policy[:sort_by]
1556
+ @sort_by ||= CONF.SORTEDQUEUE_SORTBY
1557
+
1558
+ if @sort_by.kind_of?(String)
1559
+ @sort_by = eval("proc{#{@sort_by}}")
1560
+ end
1561
+ end
1562
+
1563
+ def push(e)
1564
+ @queue_mon.synchronize do
1565
+ @push_queue.push e
1566
+ if e == :END_OF_STREAM
1567
+ @push_queue.pop
1568
+ push_on_eos
1569
+ end
1570
+ end
1571
+ end
1572
+
1573
+ def push_on_eos
1574
+ begin
1575
+ @pop_queue = @push_queue.sort_by{|e| @sort_by.call(e)}
1576
+ @pop_queue.push :END_OF_STREAM
1577
+ @push_queue.clear
1578
+ @push_queue = nil
1579
+ rescue
1580
+ Log::debug_exception
1581
+ end
1582
+ @queue_cv.broadcast
1583
+ end
1584
+
1585
+ def pop
1586
+ @queue_mon.synchronize do
1587
+ @queue_cv.wait_while{@pop_queue.nil?}
1588
+ @pop_queue.shift
1589
+ end
1590
+ end
1591
+
1592
+ def pop_all
1593
+ @queue_mon.synchronize do
1594
+ @queue_cv.wait_while{@pop_queue.nil?}
1595
+ @pop_queue.shift(@pool_threshold)
1596
+ end
1597
+ end
1598
+ end
1599
+
1600
+ class SortedQueue1<OnMemorySortedQueue
1601
+ def initialize(policy, queue_mon = Monitor.new, queue_cv = queue_mon.new_cond)
1602
+ super
1603
+
1604
+ @threshold = policy[:threshold]
1605
+ @threshold ||= CONF.SORTEDQUEUE_THRESHOLD
1606
+
1607
+ @buffers = nil
1608
+ end
1609
+
1610
+ def push_on_eos
1611
+ if @push_queue.size <= @threshold
1612
+ super
1613
+ else
1614
+ store_2ndmemory(@push_queue)
1615
+ @push_queue.clear
1616
+ @push_queue = nil
1617
+ @queue_cv.broadcast
1618
+ end
1619
+ end
1620
+
1621
+ def pop
1622
+ @queue_mon.synchronize do
1623
+ @queue_cv.wait_while{@pop_queue.nil? && @buffers.nil?}
1624
+
1625
+ if @pop_queue.nil? && @buffers
1626
+ @pop_queue = restore_2ndmemory
1627
+ end
1628
+
1629
+ @pop_queue.shift
1630
+ end
1631
+ end
1632
+
1633
+ def pop_all
1634
+ @queue_mon.synchronize do
1635
+ @queue_cv.wait_while{@pop_queue.nil? && @buffers.nil?}
1636
+
1637
+ if @pop_queue.nil? || @pop_queue.empty?
1638
+ @pop_queue = restore_2ndmemory
1639
+ end
1640
+ pops = @pop_queue
1641
+ @pop_queue = nil
1642
+ pops
1643
+ end
1644
+ end
1645
+
1646
+ def init_2ndmemory
1647
+ require "tempfile"
1648
+
1649
+ @buffer_dir = @policy[:buffer_dir]
1650
+ @buffer_dir ||= CONF.TMP_DIR
1651
+
1652
+ @buffers = []
1653
+ end
1654
+
1655
+ def open_2ndmemory(&block)
1656
+ unless @buffers
1657
+ init_2ndmemory
1658
+ end
1659
+ io = Tempfile.open("port-buffer-", @buffer_dir)
1660
+ @buffers.push io
1661
+ begin
1662
+ # ruby BUG#2390の対応のため.
1663
+ # yield io
1664
+ yield io.instance_eval{@tmpfile}
1665
+ ensure
1666
+ io.close
1667
+ end
1668
+ @buffers
1669
+ end
1670
+
1671
+ def store_2ndmemory(ary)
1672
+ Log::debug(self, "start store: ")
1673
+ ary = ary.sort_by{|e| @sort_by.call(e)}
1674
+
1675
+ while !ary.empty?
1676
+ open_2ndmemory do |io|
1677
+ buf = ary.shift(@pool_threshold)
1678
+ Marshal.dump(buf, io)
1679
+ end
1680
+ end
1681
+ Log::debug(self, "end store")
1682
+ end
1683
+
1684
+ def restore_2ndmemory
1685
+ io = @buffers.shift
1686
+ io.open
1687
+ buf = Marshal.load(io)
1688
+ if @buffers.empty?
1689
+ buf.push :END_OF_STREAM
1690
+ end
1691
+ io.close!
1692
+ buf
1693
+ end
1694
+ end
1695
+ end
1696
+
1697
+ require "fairy/share/port-marshaled-queue"