fairy 0.6.0 → 0.6.5

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 (70) hide show
  1. data/Makefile +1 -0
  2. data/bin/fairy +35 -5
  3. data/ext/extconf.rb +3 -0
  4. data/ext/fairy.c +180 -0
  5. data/ext/fairy.h +94 -0
  6. data/ext/fiber_mon.h +32 -0
  7. data/ext/fixnum-buffer.c +483 -0
  8. data/ext/p-group-by.c +529 -0
  9. data/ext/p-xgroup-by.c +467 -0
  10. data/ext/simple-hash.c +44 -0
  11. data/ext/string-buffer.c +286 -0
  12. data/ext/xmarshaled-queue.c +699 -0
  13. data/ext/xsized-queue.c +528 -0
  14. data/ext/xthread.h +65 -0
  15. data/fairy.gemspec +5 -2
  16. data/lib/fairy.rb +10 -1
  17. data/lib/fairy/client/group-by.rb +57 -2
  18. data/lib/fairy/client/here.rb +2 -1
  19. data/lib/fairy/controller.rb +25 -4
  20. data/lib/fairy/master.rb +17 -3
  21. data/lib/fairy/master/c-basic-group-by.rb +4 -2
  22. data/lib/fairy/master/c-cat.rb +3 -2
  23. data/lib/fairy/master/c-direct-product.rb +5 -3
  24. data/lib/fairy/master/c-filter.rb +5 -3
  25. data/lib/fairy/master/c-group-by.rb +13 -0
  26. data/lib/fairy/master/c-junction.rb +3 -2
  27. data/lib/fairy/master/c-seg-join.rb +3 -1
  28. data/lib/fairy/master/c-seg-shuffle.rb +3 -2
  29. data/lib/fairy/master/c-seg-split.rb +1 -1
  30. data/lib/fairy/master/c-seg-zip.rb +3 -1
  31. data/lib/fairy/master/c-sort.rb +7 -2
  32. data/lib/fairy/master/c-wc.rb +5 -3
  33. data/lib/fairy/node.rb +13 -2
  34. data/lib/fairy/node/p-barrier.rb +1 -1
  35. data/lib/fairy/node/p-basic-group-by.rb +22 -12
  36. data/lib/fairy/node/p-direct-product.rb +4 -2
  37. data/lib/fairy/node/p-filter.rb +8 -7
  38. data/lib/fairy/node/p-find.rb +2 -1
  39. data/lib/fairy/node/p-group-by.rb +17 -6
  40. data/lib/fairy/node/p-inject.rb +3 -2
  41. data/lib/fairy/node/p-output-file.rb +1 -1
  42. data/lib/fairy/node/p-seg-join.rb +2 -1
  43. data/lib/fairy/node/p-seg-zip.rb +2 -1
  44. data/lib/fairy/node/p-single-exportable.rb +3 -1
  45. data/lib/fairy/node/p-sort.rb +4 -2
  46. data/lib/fairy/node/p-task.rb +1 -1
  47. data/lib/fairy/node/p-wc.rb +5 -2
  48. data/lib/fairy/processor.rb +25 -18
  49. data/lib/fairy/share/block-source.rb +12 -2
  50. data/lib/fairy/share/conf.rb +35 -5
  51. data/lib/fairy/share/hash-simple-hash.rb +1 -1
  52. data/lib/fairy/share/log.rb +11 -4
  53. data/lib/fairy/share/pool-dictionary.rb +2 -1
  54. data/lib/fairy/share/port-marshaled-queue.rb +8 -1
  55. data/lib/fairy/share/port.rb +55 -45
  56. data/lib/fairy/share/reference.rb +2 -1
  57. data/lib/fairy/share/varray.rb +3 -1
  58. data/lib/fairy/share/vfile.rb +4 -2
  59. data/lib/fairy/version.rb +1 -1
  60. data/sample/sort.rb +69 -3
  61. data/spec/fairy8_spec.rb +1 -1
  62. data/test/testc.rb +380 -2
  63. data/tools/cap_recipe/Capfile +3 -3
  64. data/tools/fairy_conf_wizard.rb +375 -0
  65. data/tools/fairy_perf_graph.rb +15 -3
  66. data/tools/git-tag +1 -0
  67. data/tools/log-analysis.rb +59 -11
  68. metadata +33 -34
  69. data/ext/simple_hash/extconf.rb +0 -4
  70. data/ext/simple_hash/simple_hash.c +0 -42
data/ext/simple-hash.c ADDED
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright (C) 2007-2010 Rakuten, Inc.
3
+ */
4
+
5
+ #include <ruby.h>
6
+
7
+ #include "fairy.h"
8
+
9
+ #define MULTIPLIER 137
10
+
11
+ VALUE rb_mFairySimpleHash;
12
+
13
+ VALUE
14
+ rb_fairy_simple_hash(VALUE self, VALUE vstr)
15
+ {
16
+ return INT2FIX(rb_fairy_simple_hash_uint(self, vstr));
17
+ }
18
+
19
+ inline unsigned int
20
+ rb_fairy_simple_hash_uint(VALUE self, VALUE vstr)
21
+ {
22
+ VALUE vh;
23
+ char *str;
24
+ int len;
25
+ char *p;
26
+ unsigned int h = 0;
27
+
28
+ str = StringValuePtr(vstr);
29
+ len = RSTRING_LEN(vstr);
30
+
31
+ for (p = str; p - str < len; p++) {
32
+ h = h * MULTIPLIER + *p;
33
+ }
34
+ return h;
35
+ }
36
+
37
+
38
+ void Init_simple_hash(void) {
39
+ rb_mFairySimpleHash = rb_define_module_under(rb_mFairy, "SimpleHash");
40
+
41
+ rb_define_module_function(rb_mFairySimpleHash, "hash", rb_fairy_simple_hash, 1);
42
+ }
43
+
44
+
@@ -0,0 +1,286 @@
1
+ /**********************************************************************
2
+
3
+ string-buffer.c -
4
+ Copyright (C) 2007-2011 Rakuten, Inc.
5
+
6
+ **********************************************************************/
7
+
8
+ #include "ruby.h"
9
+
10
+ #include "fairy.h"
11
+
12
+ #define STRING_BUFFER_CAPA 10240
13
+
14
+ VALUE rb_cFairyStringBuffer;
15
+
16
+ typedef struct rb_fairy_string_buffer_struct
17
+ {
18
+ long size;
19
+ VALUE string_sizes;
20
+ VALUE buffer;
21
+ } fairy_string_buffer_t;
22
+
23
+ #define GetFairyStringBufferPtr(obj, tobj) \
24
+ TypedData_Get_Struct((obj), fairy_string_buffer_t, &fairy_string_buffer_data_type, (tobj))
25
+
26
+ static void
27
+ fairy_string_buffer_mark(void *ptr)
28
+ {
29
+ fairy_string_buffer_t *sb = (fairy_string_buffer_t*)ptr;
30
+
31
+ rb_gc_mark(sb->string_sizes);
32
+ rb_gc_mark(sb->buffer);
33
+ }
34
+
35
+ static void
36
+ fairy_string_buffer_free(void *ptr)
37
+ {
38
+ ruby_xfree(ptr);
39
+ }
40
+
41
+ static size_t
42
+ fairy_string_buffer_memsize(const void *ptr)
43
+ {
44
+ return ptr ? sizeof(fairy_string_buffer_t) : 0;
45
+ }
46
+
47
+ #ifdef HAVE_RB_DATA_TYPE_T_FUNCTION
48
+ static const rb_data_type_t fairy_string_buffer_data_type = {
49
+ "fairy_string_buffer",
50
+ {fairy_string_buffer_mark, fairy_string_buffer_free, fairy_string_buffer_memsize,},
51
+ };
52
+ #else
53
+ static const rb_data_type_t fairy_string_buffer_data_type = {
54
+ "fairy_string_buffer",
55
+ fairy_string_buffer_mark,
56
+ fairy_string_buffer_free,
57
+ fairy_string_buffer_memsize,
58
+ };
59
+ #endif
60
+
61
+ static VALUE
62
+ fairy_string_buffer_alloc(VALUE klass)
63
+ {
64
+ VALUE volatile obj;
65
+ fairy_string_buffer_t *sb;
66
+
67
+ obj = TypedData_Make_Struct(klass, fairy_string_buffer_t, &fairy_string_buffer_data_type, sb);
68
+
69
+ sb->size = 0;
70
+ sb->string_sizes = Qnil;
71
+ sb->buffer = Qnil;
72
+
73
+ return obj;
74
+ }
75
+
76
+ static VALUE
77
+ rb_fairy_string_buffer_initialize(VALUE self)
78
+ {
79
+ fairy_string_buffer_t *sb;
80
+
81
+ GetFairyStringBufferPtr(self, sb);
82
+ sb->string_sizes = rb_fairy_fixnum_buffer_new();
83
+ sb->buffer = rb_str_buf_new(STRING_BUFFER_CAPA);
84
+ return self;
85
+ }
86
+
87
+ static VALUE
88
+ fairy_string_buffer_initialize(int argc, VALUE *argv, VALUE self)
89
+ {
90
+ rb_fairy_string_buffer_initialize(self);
91
+ if (argc == 0) {
92
+ /* do nothing */
93
+ }
94
+ else if (argc == 1 && CLASS_OF(argv[0]) == rb_cArray) {
95
+ VALUE ary = argv[0];
96
+ long i;
97
+
98
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
99
+ rb_fairy_string_buffer_push(self, RARRAY_PTR(ary)[i]);
100
+ }
101
+ }
102
+ else {
103
+ int i;
104
+ for (i = 0; i < argc; i++) {
105
+ rb_fairy_string_buffer_push(self, argv[i]);
106
+ }
107
+ }
108
+ return self;
109
+ }
110
+
111
+
112
+ VALUE
113
+ rb_fairy_string_buffer_new(void)
114
+ {
115
+ VALUE sb;
116
+ sb = fairy_string_buffer_alloc(rb_cFairyStringBuffer);
117
+ rb_fairy_string_buffer_initialize(sb);
118
+ return sb;
119
+ }
120
+
121
+ VALUE
122
+ rb_fairy_string_buffer_new2(VALUE ary)
123
+ {
124
+ VALUE sb;
125
+ long i;
126
+ sb = rb_fairy_string_buffer_new();
127
+
128
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
129
+ rb_fairy_string_buffer_push(sb, RARRAY_PTR(ary)[i]);
130
+ }
131
+
132
+ return sb;
133
+ }
134
+
135
+ VALUE
136
+ rb_fairy_string_buffer_clear(VALUE self)
137
+ {
138
+ fairy_string_buffer_t *sb;
139
+ GetFairyStringBufferPtr(self, sb);
140
+
141
+ sb->size = 0;
142
+ rb_fairy_fixnum_buffer_clear(sb->string_sizes);
143
+ rb_str_replace(sb->buffer, rb_str_new2(""));
144
+
145
+ return self;
146
+
147
+ }
148
+
149
+ VALUE
150
+ rb_fairy_string_buffer_size(VALUE self)
151
+ {
152
+ fairy_string_buffer_t *sb;
153
+ GetFairyStringBufferPtr(self, sb);
154
+
155
+ return LONG2NUM(sb->size);
156
+ }
157
+
158
+ VALUE
159
+ rb_fairy_string_buffer_push(VALUE self, VALUE str)
160
+ {
161
+ fairy_string_buffer_t *sb;
162
+ GetFairyStringBufferPtr(self, sb);
163
+
164
+ if (!RB_TYPE_P(str, T_STRING))
165
+ rb_raise(rb_eTypeError, "wrong argument type (expected String)");
166
+ rb_fairy_fixnum_buffer_push_long(sb->string_sizes, RSTRING_LEN(str));
167
+ rb_str_buf_cat(sb->buffer, RSTRING_PTR(str), RSTRING_LEN(str));
168
+ sb->size++;
169
+ return self;
170
+ }
171
+
172
+ struct each_arg {
173
+ char *current;
174
+ };
175
+
176
+ static VALUE
177
+ each_proc(long str_size, VALUE v)
178
+ {
179
+ struct each_arg *arg = (struct each_arg *)v;
180
+ VALUE str;
181
+ VALUE ret;
182
+
183
+ str = rb_str_new(arg->current, str_size);
184
+ ret = rb_yield(str);
185
+ arg->current += str_size;
186
+ return ret;
187
+ }
188
+
189
+
190
+ VALUE
191
+ rb_fairy_string_buffer_each(VALUE self)
192
+ {
193
+ fairy_string_buffer_t *sb;
194
+ struct each_arg arg;
195
+
196
+ GetFairyStringBufferPtr(self, sb);
197
+
198
+ arg.current = RSTRING_PTR(sb->buffer);
199
+ rb_fairy_fixnum_buffer_each_callback(sb->string_sizes,
200
+ each_proc, (VALUE)&arg);
201
+ return self;
202
+ }
203
+
204
+ struct to_a_arg {
205
+ char *current;
206
+ VALUE ary;
207
+ };
208
+
209
+
210
+ static VALUE
211
+ to_a_proc(long str_size, VALUE v)
212
+ {
213
+ struct to_a_arg *arg = (struct to_a_arg *)v;
214
+ VALUE ret;
215
+
216
+ rb_ary_push(arg->ary, rb_str_new(arg->current, str_size));
217
+ arg->current += str_size;
218
+ return arg->ary;
219
+ }
220
+
221
+ VALUE
222
+ rb_fairy_string_buffer_to_a(VALUE self)
223
+ {
224
+ fairy_string_buffer_t *sb;
225
+ struct to_a_arg arg;
226
+
227
+ GetFairyStringBufferPtr(self, sb);
228
+
229
+ arg.current = RSTRING_PTR(sb->buffer);
230
+ arg.ary = rb_ary_new2(sb->size);
231
+
232
+ rb_fairy_fixnum_buffer_each_callback(sb->string_sizes,
233
+ to_a_proc, (VALUE)&arg);
234
+ return arg.ary;
235
+ }
236
+
237
+ VALUE
238
+ rb_fairy_string_buffer_marshal_dump(VALUE self)
239
+ {
240
+ fairy_string_buffer_t *sb;
241
+ GetFairyStringBufferPtr(self, sb);
242
+
243
+ return rb_ary_new3(3, LONG2NUM(sb->size), sb->string_sizes, sb->buffer);
244
+ }
245
+
246
+
247
+ VALUE
248
+ rb_fairy_string_buffer_marshal_load(VALUE self, VALUE obj)
249
+ {
250
+ fairy_string_buffer_t *sb;
251
+ GetFairyStringBufferPtr(self, sb);
252
+ sb->size = NUM2LONG(rb_ary_entry(obj, 0));
253
+ sb->string_sizes = rb_ary_entry(obj, 1);
254
+ sb->buffer = rb_ary_entry(obj, 2);
255
+ return self;
256
+ }
257
+
258
+ VALUE
259
+ rb_fairy_string_buffer_inspect(VALUE self)
260
+ {
261
+ fairy_string_buffer_t *sb;
262
+ VALUE str;
263
+
264
+ GetFairyStringBufferPtr(self, sb);
265
+
266
+ str = rb_sprintf("<%s:%x size=%d>", rb_obj_classname(self), (void*)self, sb->size);
267
+ return str;
268
+ }
269
+
270
+
271
+ Init_string_buffer()
272
+ {
273
+ VALUE fsb;
274
+ rb_cFairyStringBuffer = rb_define_class_under(rb_mFairy, "StringBuffer", rb_cObject);
275
+
276
+ fsb = rb_cFairyStringBuffer;
277
+ rb_define_alloc_func(fsb, fairy_string_buffer_alloc);
278
+ rb_define_method(fsb, "initialize", fairy_string_buffer_initialize, -1);
279
+ rb_define_method(fsb, "size", rb_fairy_string_buffer_size, 0);
280
+ rb_define_method(fsb, "push", rb_fairy_string_buffer_push, 1);
281
+ rb_define_method(fsb, "each", rb_fairy_string_buffer_each, 0);
282
+ rb_define_method(fsb, "to_a", rb_fairy_string_buffer_to_a, 0);
283
+ rb_define_method(fsb, "marshal_dump", rb_fairy_string_buffer_marshal_dump, 0);
284
+ rb_define_method(fsb, "marshal_load", rb_fairy_string_buffer_marshal_load, 1);
285
+ rb_define_method(fsb, "inspect", rb_fairy_string_buffer_inspect, 0);
286
+ }
@@ -0,0 +1,699 @@
1
+ /**********************************************************************
2
+
3
+ xmarshaled_queue.c -
4
+ Copyright (C) 2007-2011 Rakuten, Inc.
5
+
6
+ **********************************************************************/
7
+
8
+ #include "ruby.h"
9
+
10
+ #include "xthread.h"
11
+ #include "fiber_mon.h"
12
+
13
+ #include "fairy.h"
14
+
15
+ extern VALUE rb_cXThreadMonitor;
16
+ extern VALUE rb_cFiberMon;
17
+
18
+ static VALUE rb_cFairyFastTempfile;
19
+
20
+ static VALUE SET_NO_IMPORT;
21
+
22
+ VALUE rb_cFairyXMarshaledQueue;
23
+
24
+ static ID id_io;
25
+ static ID id_open;
26
+ static ID id_read;
27
+ static ID id_write;
28
+ static ID id_close;
29
+ static ID id_close_bang;
30
+
31
+ typedef struct rb_fairy_xmarshaled_queue_struct
32
+ {
33
+ long chunk_size;
34
+ long min_chunk_no;
35
+ long buffers_cache_limit;
36
+
37
+ char use_string_buffer_p;
38
+ char log_mstore_p;
39
+
40
+ VALUE push_queue;
41
+
42
+ VALUE buffers;
43
+ VALUE buffers_mon;
44
+ VALUE buffers_cv;
45
+ long buffers_cache_no;
46
+
47
+ VALUE pop_queue;
48
+
49
+ VALUE buffer_dir;
50
+
51
+ VALUE (*queue_push)(VALUE, VALUE);
52
+
53
+ VALUE (*mon_synchronize)();
54
+ VALUE (*cv_wait)();
55
+ VALUE (*cv_broadcast)();
56
+
57
+ } fairy_xmarshaled_queue_t;
58
+
59
+ #define GetFairyXMarshaledQueuePtr(obj, tobj) \
60
+ TypedData_Get_Struct((obj), fairy_xmarshaled_queue_t, &fairy_xmarshaled_queue_data_type, (tobj))
61
+
62
+ static void
63
+ fairy_xmarshaled_queue_mark(void *ptr)
64
+ {
65
+ fairy_xmarshaled_queue_t *mq = (fairy_xmarshaled_queue_t*)ptr;
66
+
67
+ rb_gc_mark(mq->push_queue);
68
+ rb_gc_mark(mq->buffers);
69
+ rb_gc_mark(mq->buffers_mon);
70
+ rb_gc_mark(mq->buffers_cv);
71
+ rb_gc_mark(mq->pop_queue);
72
+ rb_gc_mark(mq->buffer_dir);
73
+ }
74
+
75
+ static void
76
+ fairy_xmarshaled_queue_free(void *ptr)
77
+ {
78
+ ruby_xfree(ptr);
79
+ }
80
+
81
+ static size_t
82
+ fairy_xmarshaled_queue_memsize(const void *ptr)
83
+ {
84
+ return ptr ? sizeof(fairy_xmarshaled_queue_t) : 0;
85
+ }
86
+
87
+ #ifdef HAVE_RB_DATA_TYPE_T_FUNCTION
88
+ static const rb_data_type_t fairy_xmarshaled_queue_data_type = {
89
+ "fairy_xmarshaled_queue",
90
+ {fairy_xmarshaled_queue_mark, fairy_xmarshaled_queue_free, fairy_xmarshaled_queue_memsize,},
91
+ };
92
+ #else
93
+ static const rb_data_type_t fairy_xmarshaled_queue_data_type = {
94
+ "fairy_xmarshaled_queue",
95
+ fairy_xmarshaled_queue_mark,
96
+ fairy_xmarshaled_queue_free,
97
+ fairy_xmarshaled_queue_memsize,
98
+ };
99
+ #endif
100
+
101
+ static VALUE
102
+ fairy_xmarshaled_queue_alloc(VALUE klass)
103
+ {
104
+ VALUE volatile obj;
105
+ fairy_xmarshaled_queue_t *mq;
106
+
107
+ obj = TypedData_Make_Struct(klass, fairy_xmarshaled_queue_t, &fairy_xmarshaled_queue_data_type, mq);
108
+
109
+ mq->chunk_size = 0;
110
+ mq->min_chunk_no = 0;
111
+ mq->buffers_cache_limit = 0;
112
+
113
+ mq->push_queue = Qnil;
114
+
115
+ mq->buffers = Qnil;
116
+ mq->buffers_mon = Qnil;
117
+ mq->buffers_cv = Qnil;
118
+ mq->buffers_cache_no = 0;
119
+
120
+ mq->pop_queue = Qnil;
121
+
122
+ mq->buffer_dir = Qnil;
123
+
124
+ mq->queue_push = NULL;
125
+
126
+ mq->mon_synchronize = NULL;
127
+ mq->cv_wait = NULL;
128
+ mq->cv_broadcast = NULL;
129
+
130
+ return obj;
131
+ }
132
+
133
+ static VALUE rb_fairy_xmarshaled_queue_monitor_cond_wait(VALUE);
134
+ static VALUE rb_fairy_xmarshaled_queue_genmon_synchronize(VALUE, VALUE (*)(VALUE), VALUE);
135
+ static VALUE rb_fairy_xmarshaled_queue_gencond_wait(VALUE);
136
+ static VALUE rb_fairy_xmarshaled_queue_gencond_broadcast(VALUE);
137
+
138
+ static VALUE rb_fairy_xmarshaled_queue_empty_push(VALUE, VALUE);
139
+ static VALUE rb_fairy_xmarshaled_queue_str_push(VALUE, VALUE);
140
+ static VALUE rb_fairy_xmarshaled_queue_obj_push(VALUE, VALUE);
141
+
142
+ static VALUE
143
+ rb_fairy_xmarshaled_queue_initialize(VALUE self, VALUE policy, VALUE buffers_mon, VALUE buffers_cv)
144
+ {
145
+ VALUE sz;
146
+ VALUE flag;
147
+ VALUE dir;
148
+ fairy_xmarshaled_queue_t *mq;
149
+
150
+ GetFairyXMarshaledQueuePtr(self, mq);
151
+
152
+ sz = rb_fairy_conf("XMARSHAL_QUEUE_CHUNK_SIZE", policy, "chunk_size");
153
+ mq->chunk_size = NUM2LONG(sz);
154
+
155
+ sz = rb_fairy_conf("XMARSHAL_QUEUE_BUFFERS_CACHE_LIMIT",
156
+ policy, "buffers_cache_limit");
157
+ mq->buffers_cache_limit = NUM2LONG(sz);
158
+
159
+ flag = rb_fairy_conf("XMARSHAL_QUEUE_USE_STRING_BUFFER",
160
+ policy, "use_string_buffer");
161
+ mq->use_string_buffer_p = RTEST(flag);
162
+
163
+
164
+ flag = rb_fairy_conf("XMARSHAL_QUEUE_LOG_MSTORE",
165
+ policy, "log_mstore");
166
+ mq->log_mstore_p = RTEST(flag);
167
+
168
+ dir = rb_fairy_conf("TMP_DIR", policy, "buffer_dir");
169
+ mq->buffer_dir = dir;
170
+
171
+ mq->push_queue = Qnil;
172
+
173
+ mq->buffers = rb_xthread_fifo_new();
174
+ if (NIL_P(buffers_mon)) {
175
+ buffers_mon = rb_xthread_monitor_new();
176
+ }
177
+ mq->buffers_mon = buffers_mon;
178
+
179
+ if (NIL_P(buffers_cv)) {
180
+ buffers_cv = rb_funcall(buffers_mon, rb_intern("new_cond"), 0);
181
+ }
182
+ mq->buffers_cv = buffers_cv;
183
+
184
+ mq->pop_queue = Qnil;
185
+
186
+ mq->queue_push = rb_fairy_xmarshaled_queue_empty_push;
187
+
188
+ if (CLASS_OF(mq->buffers_mon) == rb_cXThreadMonitor) {
189
+ mq->mon_synchronize = rb_xthread_monitor_synchronize;
190
+ mq->cv_wait = rb_fairy_xmarshaled_queue_monitor_cond_wait;
191
+ mq->cv_broadcast = rb_xthread_monitor_cond_broadcast;
192
+ }
193
+ else if (CLASS_OF(mq->buffers_mon) == rb_cFiberMonMonitor) {
194
+ mq->mon_synchronize = rb_fibermon_monitor_synchronize;
195
+ mq->cv_wait = rb_fibermon_cond_wait;
196
+ mq->cv_broadcast = rb_fibermon_cond_broadcast;
197
+ }
198
+ else {
199
+ mq->mon_synchronize = rb_fairy_xmarshaled_queue_genmon_synchronize;
200
+ mq->cv_wait = rb_fairy_xmarshaled_queue_gencond_wait;
201
+ mq->cv_broadcast = rb_fairy_xmarshaled_queue_gencond_broadcast;
202
+ }
203
+
204
+ return self;
205
+ }
206
+
207
+ static VALUE
208
+ rb_fairy_xmarshaled_queue_monitor_cond_wait(VALUE arg)
209
+ {
210
+ return rb_xthread_monitor_cond_wait(arg, Qnil);
211
+ }
212
+
213
+ static VALUE
214
+ rb_fairy_xmarshaled_queue_genmon_synchronize(VALUE arg1, VALUE (*arg2)(VALUE), VALUE arg3)
215
+ {
216
+ static ID id_synchronize;
217
+ if (!id_synchronize) id_synchronize = rb_intern("synchronize");
218
+
219
+ return rb_funcall(arg1, id_synchronize, 2, arg2, arg3);
220
+ }
221
+
222
+ static VALUE
223
+ rb_fairy_xmarshaled_queue_gencond_wait(VALUE arg)
224
+ {
225
+ static ID id_wait;
226
+ if (!id_wait) id_wait = rb_intern("wait");
227
+
228
+ return rb_funcall(arg, id_wait, 1, Qnil);
229
+ }
230
+
231
+ static VALUE
232
+ rb_fairy_xmarshaled_queue_gencond_broadcast(VALUE arg1)
233
+ {
234
+ static ID id_broadcast;
235
+ if (!id_broadcast) id_broadcast = rb_intern("broadcast");
236
+
237
+ return rb_funcall(arg1, id_broadcast, 0);
238
+ }
239
+
240
+ static VALUE
241
+ fairy_xmarshaled_queue_initialize(int argc, VALUE *argv, VALUE self)
242
+ {
243
+ VALUE policy;
244
+ VALUE buffers_mon;
245
+ VALUE buffers_cv;
246
+
247
+ rb_scan_args(argc, argv, "12", &policy, &buffers_mon, &buffers_cv);
248
+ return rb_fairy_xmarshaled_queue_initialize(self, policy, buffers_mon, buffers_cv);
249
+ }
250
+
251
+ VALUE
252
+ rb_fairy_xmarshaled_queue_new(VALUE policy, VALUE buffers_mon, VALUE buffers_cv)
253
+ {
254
+ VALUE self;
255
+
256
+ self = fairy_xmarshaled_queue_alloc(rb_cFairyXMarshaledQueue);
257
+ rb_fairy_xmarshaled_queue_initialize(self, policy, buffers_mon, buffers_cv);
258
+ return self;
259
+ }
260
+
261
+ static VALUE rb_fairy_xmarshaled_queue_buffers_push(VALUE, VALUE);
262
+ static VALUE rb_fairy_xmarshaled_queue_broadcast(VALUE);
263
+ static VALUE rb_fairy_xmarshaled_queue_store(VALUE, VALUE);
264
+ static VALUE rb_fairy_xmarshaled_queue_restore(VALUE, VALUE);
265
+
266
+ #define BUFFERS_PUSH(self, buf) \
267
+ rb_fairy_xmarshaled_queue_buffers_push(self, buf)
268
+
269
+ #define BUFFERS_PUSH_PUSH_QUEUE(self, mq, buf) \
270
+ if (mq->buffers_cache_limit >= mq->buffers_cache_no) { \
271
+ BUFFERS_PUSH(self, rb_marshal_dump(buf, Qnil)); \
272
+ mq->buffers_cache_no++; \
273
+ } \
274
+ else { \
275
+ BUFFERS_PUSH(self, rb_fairy_xmarshaled_queue_store(self, buf)); \
276
+ }
277
+
278
+ VALUE
279
+ rb_fairy_xmarshaled_queue_push(VALUE self, VALUE e)
280
+ {
281
+ fairy_xmarshaled_queue_t *mq;
282
+
283
+ GetFairyXMarshaledQueuePtr(self, mq);
284
+ return mq->queue_push(self, e);
285
+ }
286
+
287
+ static VALUE
288
+ rb_fairy_xmarshaled_queue_empty_push(VALUE self, VALUE e)
289
+ {
290
+ fairy_xmarshaled_queue_t *mq;
291
+ GetFairyXMarshaledQueuePtr(self, mq);
292
+
293
+ if (EOS_P(e)) {
294
+ BUFFERS_PUSH(self, e);
295
+ return self;
296
+ }
297
+
298
+ if (mq->use_string_buffer_p && CLASS_OF(e) == rb_cString) {
299
+ mq->push_queue = rb_fairy_string_buffer_new();
300
+ mq->queue_push = rb_fairy_xmarshaled_queue_str_push;
301
+ }
302
+ else {
303
+ mq->push_queue = rb_ary_new2(mq->min_chunk_no);
304
+ mq->queue_push = rb_fairy_xmarshaled_queue_obj_push;
305
+ }
306
+ return mq->queue_push(self, e);
307
+ }
308
+
309
+ static VALUE
310
+ rb_fairy_xmarshaled_queue_obj_push(VALUE self, VALUE e)
311
+ {
312
+ fairy_xmarshaled_queue_t *mq;
313
+ GetFairyXMarshaledQueuePtr(self, mq);
314
+
315
+ if (EOS_P(e)) {
316
+ BUFFERS_PUSH_PUSH_QUEUE(self, mq, mq->push_queue);
317
+ mq->push_queue = Qnil;
318
+ BUFFERS_PUSH(self, e);
319
+ return self;
320
+ }
321
+
322
+ if (mq->use_string_buffer_p && CLASS_OF(e) == rb_cString) {
323
+ BUFFERS_PUSH_PUSH_QUEUE(self, mq, mq->push_queue);
324
+ mq->push_queue = Qnil;
325
+ mq->queue_push = rb_fairy_xmarshaled_queue_empty_push;
326
+ /*
327
+ return mq->queue_push(self, e);
328
+ */
329
+ }
330
+
331
+ rb_ary_push(mq->push_queue, e);
332
+ if (RARRAY_LEN(mq->push_queue) >= mq->chunk_size || e == SET_NO_IMPORT) {
333
+ BUFFERS_PUSH_PUSH_QUEUE(self, mq, mq->push_queue);
334
+ mq->push_queue = Qnil;
335
+ mq->queue_push = rb_fairy_xmarshaled_queue_empty_push;
336
+ }
337
+ return self;
338
+ }
339
+
340
+ static VALUE
341
+ rb_fairy_xmarshaled_queue_str_push(VALUE self, VALUE e)
342
+ {
343
+ fairy_xmarshaled_queue_t *mq;
344
+
345
+ GetFairyXMarshaledQueuePtr(self, mq);
346
+ if (EOS_P(e)) {
347
+ BUFFERS_PUSH_PUSH_QUEUE(self, mq, mq->push_queue);
348
+ mq->push_queue = Qnil;
349
+ BUFFERS_PUSH(self, e);
350
+ return self;
351
+ }
352
+
353
+ if (CLASS_OF(e) != rb_cString) {
354
+ BUFFERS_PUSH_PUSH_QUEUE(self, mq, mq->push_queue);
355
+ rb_fairy_string_buffer_clear(mq->push_queue);
356
+ mq->push_queue = Qnil;
357
+ mq->queue_push = rb_fairy_xmarshaled_queue_empty_push;
358
+ }
359
+ rb_fairy_string_buffer_push(mq->push_queue, e);
360
+ if (NUM2LONG(rb_fairy_string_buffer_size(mq->push_queue)) >= mq->chunk_size) {
361
+ BUFFERS_PUSH_PUSH_QUEUE(self, mq, mq->push_queue);
362
+ rb_fairy_string_buffer_clear(mq->push_queue);
363
+ mq->push_queue = Qnil;
364
+ mq->queue_push = rb_fairy_xmarshaled_queue_empty_push;
365
+ }
366
+ return self;
367
+ }
368
+
369
+ static VALUE rb_fairy_xmarshaled_queue_store_raw(VALUE, VALUE);
370
+
371
+ static VALUE
372
+ rb_fairy_xmarshaled_queue_push_raw(VALUE self, VALUE raw)
373
+ {
374
+ fairy_xmarshaled_queue_t *mq;
375
+
376
+ GetFairyXMarshaledQueuePtr(self, mq);
377
+
378
+ if (!NIL_P(mq->push_queue)) {
379
+ BUFFERS_PUSH_PUSH_QUEUE(self, mq, mq->push_queue);
380
+ mq->push_queue = Qnil;
381
+ }
382
+ if (EOS_P(raw)) {
383
+ BUFFERS_PUSH(self, raw);
384
+ }
385
+ else {
386
+ if (mq->buffers_cache_limit >= mq->buffers_cache_no) {
387
+ BUFFERS_PUSH(self, raw);
388
+ mq->buffers_cache_no++;
389
+ }
390
+ else {
391
+ BUFFERS_PUSH(self, rb_fairy_xmarshaled_queue_store_raw(self, raw));
392
+ }
393
+ }
394
+ return self;
395
+ }
396
+
397
+
398
+
399
+ struct rb_fairy_xmarshaled_queue_buffers_push_arg
400
+ {
401
+ VALUE self;
402
+ VALUE buf;
403
+ };
404
+
405
+ static VALUE rb_fairy_xmarshaled_queue_push_sync(struct rb_fairy_xmarshaled_queue_buffers_push_arg *);
406
+
407
+
408
+ static VALUE
409
+ rb_fairy_xmarshaled_queue_buffers_push(VALUE self, VALUE buf)
410
+ {
411
+ fairy_xmarshaled_queue_t *mq;
412
+ struct rb_fairy_xmarshaled_queue_buffers_push_arg arg;
413
+
414
+ GetFairyXMarshaledQueuePtr(self, mq);
415
+
416
+ arg.self = self;
417
+ arg.buf = buf;
418
+
419
+ mq->mon_synchronize(mq->buffers_mon,
420
+ rb_fairy_xmarshaled_queue_push_sync, &arg);
421
+ }
422
+
423
+ static VALUE
424
+ rb_fairy_xmarshaled_queue_push_sync(struct rb_fairy_xmarshaled_queue_buffers_push_arg *arg)
425
+ {
426
+ fairy_xmarshaled_queue_t *mq;
427
+ GetFairyXMarshaledQueuePtr(arg->self, mq);
428
+
429
+ rb_xthread_fifo_push(mq->buffers, arg->buf);
430
+ mq->cv_broadcast(mq->buffers_cv);
431
+ return arg->self;
432
+ }
433
+
434
+ struct rb_fairy_xmarshaled_queue_pop_arg
435
+ {
436
+ VALUE self;
437
+ VALUE buf;
438
+ };
439
+
440
+ static VALUE rb_fairy_xmarshaled_queue_pop_wait(struct rb_fairy_xmarshaled_queue_pop_arg *arg);
441
+
442
+ VALUE
443
+ rb_fairy_xmarshaled_queue_pop(VALUE self)
444
+ {
445
+ fairy_xmarshaled_queue_t *mq;
446
+ VALUE buf;
447
+ struct rb_fairy_xmarshaled_queue_pop_arg arg;
448
+ GetFairyXMarshaledQueuePtr(self, mq);
449
+
450
+ while (NIL_P(mq->pop_queue) || RARRAY_LEN(mq->pop_queue) == 0) {
451
+ buf = rb_xthread_fifo_pop(mq->buffers);
452
+ if (NIL_P(buf)) {
453
+ arg.self = self;
454
+ arg.buf = Qnil;
455
+ mq->mon_synchronize(mq->buffers_mon,
456
+ rb_fairy_xmarshaled_queue_pop_wait, &arg);
457
+ buf = arg.buf;
458
+ }
459
+ if (EOS_P(buf)) {
460
+ mq->pop_queue = rb_ary_new3(1, buf);
461
+ }
462
+ else if (CLASS_OF(buf) == rb_cFairyFastTempfile) {
463
+ buf = rb_fairy_xmarshaled_queue_restore(self, buf);
464
+ if (CLASS_OF(buf) == rb_cFairyStringBuffer) {
465
+ VALUE tmp = buf;
466
+ buf = rb_fairy_string_buffer_to_a(tmp);
467
+ rb_fairy_string_buffer_clear(tmp);
468
+ }
469
+ mq->pop_queue = buf;
470
+ }
471
+ else {
472
+ buf = rb_marshal_load(buf);
473
+ if (CLASS_OF(buf) == rb_cFairyStringBuffer) {
474
+ mq->pop_queue = rb_fairy_string_buffer_to_a(buf);
475
+ rb_fairy_string_buffer_clear(buf);
476
+ mq->buffers_cache_no--;
477
+ }
478
+ else {
479
+ mq->pop_queue = buf;
480
+ mq->buffers_cache_no--;
481
+ }
482
+ }
483
+ }
484
+ return rb_ary_shift(mq->pop_queue);
485
+ }
486
+
487
+ static VALUE
488
+ rb_fairy_xmarshaled_queue_pop_wait(struct rb_fairy_xmarshaled_queue_pop_arg *arg)
489
+ {
490
+ VALUE self = arg->self;
491
+ fairy_xmarshaled_queue_t *mq;
492
+ VALUE buf = Qnil;
493
+
494
+ GetFairyXMarshaledQueuePtr(self, mq);
495
+
496
+ buf = rb_xthread_fifo_pop(mq->buffers);
497
+ while (NIL_P(buf)) {
498
+ mq->cv_wait(mq->buffers_cv);
499
+ buf = rb_xthread_fifo_pop(mq->buffers);
500
+ }
501
+ arg->buf = buf;
502
+ return arg->self;
503
+ }
504
+
505
+ static VALUE rb_fairy_xmarshaled_queue_restore_raw(VALUE, VALUE);
506
+
507
+ VALUE
508
+ rb_fairy_xmarshaled_queue_pop_raw(VALUE self)
509
+ {
510
+ fairy_xmarshaled_queue_t *mq;
511
+ VALUE pop_raw = Qnil;
512
+ VALUE buf;
513
+ struct rb_fairy_xmarshaled_queue_pop_arg arg;
514
+
515
+ GetFairyXMarshaledQueuePtr(self, mq);
516
+ buf = rb_xthread_fifo_pop(mq->buffers);
517
+ if (NIL_P(buf)) {
518
+ arg.self = self;
519
+ arg.buf = Qnil;
520
+ mq->mon_synchronize(mq->buffers_mon,
521
+ rb_fairy_xmarshaled_queue_pop_wait, &arg);
522
+ buf = arg.buf;
523
+ }
524
+ if (EOS_P(buf)) {
525
+ pop_raw = buf;
526
+ }
527
+ else if (CLASS_OF(buf) == rb_cFairyFastTempfile) {
528
+ pop_raw = rb_fairy_xmarshaled_queue_restore_raw(self, buf);
529
+ }
530
+ else {
531
+ pop_raw = buf;
532
+ mq->buffers_cache_no--;
533
+ }
534
+ return pop_raw;
535
+ }
536
+
537
+ static VALUE
538
+ rb_fairy_xmarshaled_queue_store(VALUE self, VALUE buffer)
539
+ {
540
+ VALUE tmpbuf;
541
+ VALUE io;
542
+ fairy_xmarshaled_queue_t *mq;
543
+
544
+ GetFairyXMarshaledQueuePtr(self, mq);
545
+
546
+ if (mq->log_mstore_p) {
547
+ rb_fairy_debug(self, "START M.STORE");
548
+ }
549
+
550
+ if (NIL_P(mq->buffer_dir)) {
551
+ tmpbuf = rb_funcall(rb_cFairyFastTempfile, id_open, 1,
552
+ rb_str_new2("port-buffer-"));
553
+ }
554
+ else {
555
+ tmpbuf = rb_funcall(rb_cFairyFastTempfile, id_open, 2,
556
+ rb_str_new2("port-buffer-"),
557
+ mq->buffer_dir);
558
+ }
559
+
560
+ io = rb_funcall(tmpbuf, id_io, 0);
561
+ rb_marshal_dump(buffer, io);
562
+ rb_funcall(tmpbuf, id_close, 0);
563
+
564
+ if (mq->log_mstore_p) {
565
+ rb_fairy_debug(self, "FINISH M.STORE");
566
+ }
567
+ return tmpbuf;
568
+ }
569
+
570
+ static VALUE
571
+ rb_fairy_xmarshaled_queue_store_raw(VALUE self, VALUE raw)
572
+ {
573
+ VALUE tmpbuf;
574
+ VALUE io;
575
+ fairy_xmarshaled_queue_t *mq;
576
+
577
+ GetFairyXMarshaledQueuePtr(self, mq);
578
+
579
+ if (mq->log_mstore_p) {
580
+ rb_fairy_debug(self, "START M.STORE");
581
+ }
582
+
583
+ if (NIL_P(mq->buffer_dir)) {
584
+ tmpbuf = rb_funcall(rb_cFairyFastTempfile, id_open, 1,
585
+ rb_str_new2("port-buffer-"));
586
+ }
587
+ else {
588
+ tmpbuf = rb_funcall(rb_cFairyFastTempfile, id_open, 2,
589
+ rb_str_new2("port-buffer-"),
590
+ mq->buffer_dir);
591
+ }
592
+
593
+ io = rb_funcall(tmpbuf, id_io, 0);
594
+ rb_io_write(io, raw);
595
+ rb_funcall(tmpbuf, id_close, 0);
596
+
597
+ if (mq->log_mstore_p) {
598
+ rb_fairy_debug(self, "FINISH M.STORE");
599
+ }
600
+ return tmpbuf;
601
+ }
602
+
603
+ static VALUE
604
+ rb_fairy_xmarshaled_queue_restore(VALUE self, VALUE tmpbuf)
605
+ {
606
+ VALUE buf;
607
+ VALUE io;
608
+ fairy_xmarshaled_queue_t *mq;
609
+
610
+ GetFairyXMarshaledQueuePtr(self, mq);
611
+
612
+ if (mq->log_mstore_p) {
613
+ rb_fairy_debug(self, "START M.RESTORE");
614
+ }
615
+
616
+ io = rb_funcall(tmpbuf, id_open, 0);
617
+
618
+ buf = rb_marshal_load(io);
619
+
620
+ if (mq->log_mstore_p) {
621
+ rb_fairy_debug(self, "FINISH M.RESTORE");
622
+ }
623
+ return buf;
624
+ }
625
+
626
+ static VALUE
627
+ rb_fairy_xmarshaled_queue_restore_raw(VALUE self, VALUE tmpbuf)
628
+ {
629
+ VALUE buf;
630
+ VALUE io;
631
+ fairy_xmarshaled_queue_t *mq;
632
+
633
+ GetFairyXMarshaledQueuePtr(self, mq);
634
+
635
+ if (mq->log_mstore_p) {
636
+ rb_fairy_debug(self, "START M.RESTORE");
637
+ }
638
+
639
+ io = rb_funcall(tmpbuf, id_open, 0);
640
+
641
+ buf = rb_funcall(io, id_read, 1, Qnil);
642
+
643
+ if (mq->log_mstore_p) {
644
+ rb_fairy_debug(self, "FINISH M.RESTORE");
645
+ }
646
+ return buf;
647
+ }
648
+
649
+ VALUE
650
+ rb_fairy_xmarshaled_queue_inspect(VALUE self)
651
+ {
652
+ VALUE str;
653
+ fairy_xmarshaled_queue_t *mq;
654
+
655
+ GetFairyXMarshaledQueuePtr(self, mq);
656
+
657
+ str = rb_sprintf("<%s:%p chunk_size=%d, min_chunk_no=%d, mq_bufferes_cache_no=%d use_string_bffer_p=%d buffers_cache_no=%d buffer_dir=",
658
+ rb_obj_classname(self),
659
+ (void*)self,
660
+ mq->chunk_size,
661
+ mq->min_chunk_no,
662
+ mq->buffers_cache_limit,
663
+ mq->use_string_buffer_p,
664
+ mq->buffers_cache_no);
665
+ rb_str_append(str, mq->buffer_dir);
666
+ rb_str_cat2(str, ">");
667
+ return str;
668
+ }
669
+
670
+
671
+ void
672
+ Init_xmarshaled_queue()
673
+ {
674
+ VALUE xmq;
675
+
676
+ rb_cFairyFastTempfile = rb_const_get(rb_mFairy, rb_intern("FastTempfile"));
677
+
678
+ id_io = rb_intern("io");
679
+ id_open = rb_intern("open");
680
+ id_read = rb_intern("read");
681
+ id_write = rb_intern("write");
682
+ id_close = rb_intern("close");
683
+ id_close_bang = rb_intern("close!");
684
+
685
+ SET_NO_IMPORT = rb_const_get(rb_cFairyImport, rb_intern("SET_NO_IMPORT"));
686
+
687
+ rb_cFairyXMarshaledQueue = rb_define_class_under(rb_mFairy, "XMarshaledQueue", rb_cObject);
688
+
689
+ xmq = rb_cFairyXMarshaledQueue;
690
+
691
+ rb_define_alloc_func(xmq, fairy_xmarshaled_queue_alloc);
692
+ rb_define_method(xmq, "initialize", fairy_xmarshaled_queue_initialize, -1);
693
+ rb_define_method(xmq, "push", rb_fairy_xmarshaled_queue_push, 1);
694
+ rb_define_method(xmq, "push_raw", rb_fairy_xmarshaled_queue_push_raw, 1);
695
+ rb_define_method(xmq, "pop", rb_fairy_xmarshaled_queue_pop, 0);
696
+ rb_define_method(xmq, "pop_raw", rb_fairy_xmarshaled_queue_pop_raw, 0);
697
+ rb_define_method(xmq, "inspect", rb_fairy_xmarshaled_queue_inspect, 0);
698
+ }
699
+