fairy 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. data/LICENSE +674 -0
  2. data/Makefile +116 -0
  3. data/README +15 -0
  4. data/bin/fairy +582 -0
  5. data/bin/fairy-cat +74 -0
  6. data/bin/fairy-cp +128 -0
  7. data/bin/fairy-rm +122 -0
  8. data/bin/subcmd/controller +41 -0
  9. data/bin/subcmd/inspector +81 -0
  10. data/bin/subcmd/master +43 -0
  11. data/bin/subcmd/node +47 -0
  12. data/bin/subcmd/processor +54 -0
  13. data/doc/programming-interface.html +240 -0
  14. data/doc/programming-interface.rd +300 -0
  15. data/etc/fairy.conf.tmpl +118 -0
  16. data/ext/simple_hash/extconf.rb +4 -0
  17. data/ext/simple_hash/simple_hash.c +42 -0
  18. data/fairy.gemspec +60 -0
  19. data/lib/fairy/client/addins.rb +20 -0
  20. data/lib/fairy/client/barrier.rb +29 -0
  21. data/lib/fairy/client/basic-group-by.rb +52 -0
  22. data/lib/fairy/client/cat.rb +41 -0
  23. data/lib/fairy/client/direct-product.rb +51 -0
  24. data/lib/fairy/client/equijoin.rb +79 -0
  25. data/lib/fairy/client/exec.rb +54 -0
  26. data/lib/fairy/client/filter.rb +62 -0
  27. data/lib/fairy/client/find.rb +35 -0
  28. data/lib/fairy/client/group-by.rb +194 -0
  29. data/lib/fairy/client/here.rb +84 -0
  30. data/lib/fairy/client/inject.rb +70 -0
  31. data/lib/fairy/client/input-file.rb +53 -0
  32. data/lib/fairy/client/input-iota.rb +49 -0
  33. data/lib/fairy/client/input-local-file.rb +188 -0
  34. data/lib/fairy/client/input-varray.rb +30 -0
  35. data/lib/fairy/client/input.rb +42 -0
  36. data/lib/fairy/client/io-filter.rb +26 -0
  37. data/lib/fairy/client/junction.rb +31 -0
  38. data/lib/fairy/client/map.rb +34 -0
  39. data/lib/fairy/client/merge-group-by.rb +71 -0
  40. data/lib/fairy/client/output-file.rb +64 -0
  41. data/lib/fairy/client/output-local-file.rb +60 -0
  42. data/lib/fairy/client/output-null.rb +47 -0
  43. data/lib/fairy/client/output-varray.rb +50 -0
  44. data/lib/fairy/client/output.rb +29 -0
  45. data/lib/fairy/client/roma-put.rb +62 -0
  46. data/lib/fairy/client/roma.rb +156 -0
  47. data/lib/fairy/client/seg-join.rb +61 -0
  48. data/lib/fairy/client/seg-map.rb +78 -0
  49. data/lib/fairy/client/seg-shuffle.rb +35 -0
  50. data/lib/fairy/client/seg-split.rb +27 -0
  51. data/lib/fairy/client/seg-zip.rb +60 -0
  52. data/lib/fairy/client/select.rb +38 -0
  53. data/lib/fairy/client/sort.rb +48 -0
  54. data/lib/fairy/client/sort18.rb +56 -0
  55. data/lib/fairy/client/sort19.rb +61 -0
  56. data/lib/fairy/client/there.rb +47 -0
  57. data/lib/fairy/client/top_n_into_roma.rb +34 -0
  58. data/lib/fairy/client/wc.rb +92 -0
  59. data/lib/fairy/controller.rb +1103 -0
  60. data/lib/fairy/logger.rb +107 -0
  61. data/lib/fairy/master/addins.rb +20 -0
  62. data/lib/fairy/master/atom.rb +17 -0
  63. data/lib/fairy/master/c-barrier.rb +283 -0
  64. data/lib/fairy/master/c-basic-group-by.rb +250 -0
  65. data/lib/fairy/master/c-cat.rb +159 -0
  66. data/lib/fairy/master/c-direct-product.rb +203 -0
  67. data/lib/fairy/master/c-exec.rb +68 -0
  68. data/lib/fairy/master/c-filter.rb +422 -0
  69. data/lib/fairy/master/c-find.rb +138 -0
  70. data/lib/fairy/master/c-group-by.rb +64 -0
  71. data/lib/fairy/master/c-here.rb +80 -0
  72. data/lib/fairy/master/c-inject.rb +119 -0
  73. data/lib/fairy/master/c-input-file.rb +46 -0
  74. data/lib/fairy/master/c-input-iota.rb +66 -0
  75. data/lib/fairy/master/c-input-local-file.rb +117 -0
  76. data/lib/fairy/master/c-input-varray.rb +53 -0
  77. data/lib/fairy/master/c-input.rb +24 -0
  78. data/lib/fairy/master/c-inputtable.rb +31 -0
  79. data/lib/fairy/master/c-inputtable18.rb +36 -0
  80. data/lib/fairy/master/c-inputtable19.rb +35 -0
  81. data/lib/fairy/master/c-io-filter.rb +28 -0
  82. data/lib/fairy/master/c-junction.rb +54 -0
  83. data/lib/fairy/master/c-map.rb +27 -0
  84. data/lib/fairy/master/c-merge-group-by.rb +241 -0
  85. data/lib/fairy/master/c-output-file.rb +84 -0
  86. data/lib/fairy/master/c-output-local-file.rb +19 -0
  87. data/lib/fairy/master/c-output-null.rb +45 -0
  88. data/lib/fairy/master/c-output-varray.rb +57 -0
  89. data/lib/fairy/master/c-output.rb +20 -0
  90. data/lib/fairy/master/c-seg-join.rb +141 -0
  91. data/lib/fairy/master/c-seg-map.rb +26 -0
  92. data/lib/fairy/master/c-seg-shuffle.rb +87 -0
  93. data/lib/fairy/master/c-seg-split.rb +110 -0
  94. data/lib/fairy/master/c-seg-zip.rb +132 -0
  95. data/lib/fairy/master/c-select.rb +27 -0
  96. data/lib/fairy/master/c-sort.rb +108 -0
  97. data/lib/fairy/master/c-there.rb +57 -0
  98. data/lib/fairy/master/c-wc.rb +232 -0
  99. data/lib/fairy/master/job-interpriter.rb +19 -0
  100. data/lib/fairy/master/scheduler.rb +24 -0
  101. data/lib/fairy/master.rb +329 -0
  102. data/lib/fairy/node/addins.rb +19 -0
  103. data/lib/fairy/node/p-barrier.rb +95 -0
  104. data/lib/fairy/node/p-basic-group-by.rb +252 -0
  105. data/lib/fairy/node/p-direct-product.rb +153 -0
  106. data/lib/fairy/node/p-exec.rb +30 -0
  107. data/lib/fairy/node/p-filter.rb +363 -0
  108. data/lib/fairy/node/p-find.rb +111 -0
  109. data/lib/fairy/node/p-group-by.rb +1534 -0
  110. data/lib/fairy/node/p-here.rb +21 -0
  111. data/lib/fairy/node/p-identity.rb +24 -0
  112. data/lib/fairy/node/p-inject.rb +127 -0
  113. data/lib/fairy/node/p-input-file.rb +108 -0
  114. data/lib/fairy/node/p-input-iota.rb +39 -0
  115. data/lib/fairy/node/p-input-local-file.rb +61 -0
  116. data/lib/fairy/node/p-input-varray.rb +26 -0
  117. data/lib/fairy/node/p-io-filter.rb +28 -0
  118. data/lib/fairy/node/p-map.rb +40 -0
  119. data/lib/fairy/node/p-merger-group-by.rb +48 -0
  120. data/lib/fairy/node/p-output-file.rb +104 -0
  121. data/lib/fairy/node/p-output-local-file.rb +14 -0
  122. data/lib/fairy/node/p-output-null.rb +32 -0
  123. data/lib/fairy/node/p-output-varray.rb +41 -0
  124. data/lib/fairy/node/p-seg-join.rb +82 -0
  125. data/lib/fairy/node/p-seg-map.rb +34 -0
  126. data/lib/fairy/node/p-seg-split.rb +61 -0
  127. data/lib/fairy/node/p-seg-zip.rb +79 -0
  128. data/lib/fairy/node/p-select.rb +40 -0
  129. data/lib/fairy/node/p-single-exportable.rb +90 -0
  130. data/lib/fairy/node/p-sort.rb +195 -0
  131. data/lib/fairy/node/p-task.rb +113 -0
  132. data/lib/fairy/node/p-there.rb +44 -0
  133. data/lib/fairy/node/p-wc.rb +266 -0
  134. data/lib/fairy/node.rb +187 -0
  135. data/lib/fairy/processor.rb +510 -0
  136. data/lib/fairy/share/base-app.rb +114 -0
  137. data/lib/fairy/share/block-source.rb +234 -0
  138. data/lib/fairy/share/conf.rb +396 -0
  139. data/lib/fairy/share/debug.rb +21 -0
  140. data/lib/fairy/share/encoding.rb +17 -0
  141. data/lib/fairy/share/fast-tempfile.rb +93 -0
  142. data/lib/fairy/share/file-place.rb +176 -0
  143. data/lib/fairy/share/hash-1.rb +20 -0
  144. data/lib/fairy/share/hash-md5.rb +28 -0
  145. data/lib/fairy/share/hash-murmur.rb +69 -0
  146. data/lib/fairy/share/hash-rb18.rb +20 -0
  147. data/lib/fairy/share/hash-simple-hash.rb +28 -0
  148. data/lib/fairy/share/inspector.rb +16 -0
  149. data/lib/fairy/share/lc/exceptions.rb +82 -0
  150. data/lib/fairy/share/lc/ja/exceptions.rb +81 -0
  151. data/lib/fairy/share/locale.rb +17 -0
  152. data/lib/fairy/share/log.rb +215 -0
  153. data/lib/fairy/share/pool-dictionary.rb +53 -0
  154. data/lib/fairy/share/port-marshaled-queue.rb +347 -0
  155. data/lib/fairy/share/port.rb +1697 -0
  156. data/lib/fairy/share/reference.rb +45 -0
  157. data/lib/fairy/share/stdout.rb +56 -0
  158. data/lib/fairy/share/tr.rb +16 -0
  159. data/lib/fairy/share/varray.rb +147 -0
  160. data/lib/fairy/share/vfile.rb +183 -0
  161. data/lib/fairy/version.rb +8 -0
  162. data/lib/fairy.rb +206 -0
  163. data/sample/grep.rb +46 -0
  164. data/sample/ping.rb +19 -0
  165. data/sample/sort.rb +102 -0
  166. data/sample/wordcount.rb +61 -0
  167. data/spec/README +12 -0
  168. data/spec/fairy1_spec.rb +31 -0
  169. data/spec/fairy2_spec.rb +42 -0
  170. data/spec/fairy3_spec.rb +126 -0
  171. data/spec/fairy4_spec.rb +63 -0
  172. data/spec/fairy5_spec.rb +45 -0
  173. data/spec/fairy6_spec.rb +52 -0
  174. data/spec/fairy7_spec.rb +58 -0
  175. data/spec/fairy8_spec.rb +48 -0
  176. data/spec/mkdat.rb +148 -0
  177. data/spec/run_all.sh +65 -0
  178. data/test/testc.rb +7111 -0
  179. data/tools/cap_recipe/Capfile +144 -0
  180. data/tools/cap_recipe/cluster.yml.sample +14 -0
  181. data/tools/fairy_perf_graph.rb +444 -0
  182. data/tools/git-tag +44 -0
  183. data/tools/log-analysis.rb +62 -0
  184. data/tools/svn-ls-diff +38 -0
  185. data/tools/svn-tags +37 -0
  186. metadata +298 -0
@@ -0,0 +1,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"