ferocia-rubywmq 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.document +8 -0
  2. data/LICENSE +13 -0
  3. data/Manifest.txt +20 -0
  4. data/README +73 -0
  5. data/examples/each_a.rb +32 -0
  6. data/examples/each_b.rb +41 -0
  7. data/examples/each_header.rb +38 -0
  8. data/examples/files_to_q.cfg +24 -0
  9. data/examples/files_to_q.rb +47 -0
  10. data/examples/get_a.rb +35 -0
  11. data/examples/get_client.rb +51 -0
  12. data/examples/put1_a.rb +25 -0
  13. data/examples/put1_b.rb +33 -0
  14. data/examples/put1_c.rb +32 -0
  15. data/examples/put_a.rb +35 -0
  16. data/examples/put_b.rb +43 -0
  17. data/examples/put_dlh.rb +41 -0
  18. data/examples/put_dynamic_q.rb +38 -0
  19. data/examples/put_group_a.rb +51 -0
  20. data/examples/put_group_b.rb +53 -0
  21. data/examples/put_rfh.rb +67 -0
  22. data/examples/put_rfh2_a.rb +43 -0
  23. data/examples/put_rfh2_b.rb +43 -0
  24. data/examples/put_xmit_q.rb +33 -0
  25. data/examples/q_to_files.cfg +17 -0
  26. data/examples/q_to_files.rb +48 -0
  27. data/examples/request.rb +60 -0
  28. data/examples/server.rb +97 -0
  29. data/ext/build.bat +3 -0
  30. data/ext/build.sh +6 -0
  31. data/ext/decode_rfh.c +348 -0
  32. data/ext/decode_rfh.h +45 -0
  33. data/ext/extconf.rb +44 -0
  34. data/ext/extconf_client.rb +40 -0
  35. data/ext/generate/generate_const.rb +167 -0
  36. data/ext/generate/generate_reason.rb +246 -0
  37. data/ext/generate/generate_structs.rb +97 -0
  38. data/ext/generate/wmq_structs.erb +371 -0
  39. data/ext/lib/wmq_temp.rb +197 -0
  40. data/ext/wmq.c +93 -0
  41. data/ext/wmq.h +367 -0
  42. data/ext/wmq_message.c +671 -0
  43. data/ext/wmq_mq_load.c +217 -0
  44. data/ext/wmq_queue.c +1411 -0
  45. data/ext/wmq_queue_manager.c +1587 -0
  46. data/lib/wmq.rb +25 -0
  47. data/rubywmq.binary.gemspec +32 -0
  48. data/rubywmq.gemspec +33 -0
  49. data/tests/test.rb +328 -0
  50. metadata +124 -0
data/ext/wmq.h ADDED
@@ -0,0 +1,367 @@
1
+ /* --------------------------------------------------------------------------
2
+ * Copyright 2006 J. Reid Morrison. Dimension Solutions, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ * --------------------------------------------------------------------------*/
16
+
17
+ #include <ruby.h>
18
+
19
+ /* New with Ruby 1.9, define for prior Ruby versions */
20
+ #ifndef RSTRING_PTR
21
+ #define RSTRING_PTR(str) RSTRING(str)->ptr
22
+ #endif
23
+ #ifndef RSTRING_LEN
24
+ #define RSTRING_LEN(str) RSTRING(str)->len
25
+ #endif
26
+ #ifndef RARRAY_PTR
27
+ #define RARRAY_PTR(ary) RARRAY(ary)->ptr
28
+ #endif
29
+ #ifndef RARRAY_LEN
30
+ #define RARRAY_LEN(ary) RARRAY(ary)->len
31
+ #endif
32
+ #ifndef HAVE_RB_STR_SET_LEN
33
+ #define rb_str_set_len(str, length) (RSTRING_LEN(str) = (length))
34
+ #endif
35
+
36
+ #include <cmqc.h>
37
+ #include <cmqxc.h>
38
+
39
+ /* Todo: Add a #ifdef here to exclude the following includes when applicable */
40
+ #include <cmqcfc.h> /* PCF */
41
+ #include <cmqbc.h> /* MQAI */
42
+
43
+ #ifdef _WIN32
44
+ #define WMQ_EXPORT __declspec(dllexport)
45
+ #else
46
+ #define WMQ_EXPORT
47
+ #endif
48
+
49
+ void QueueManager_id_init();
50
+ void QueueManager_selector_id_init();
51
+ void QueueManager_command_id_init();
52
+ VALUE QUEUE_MANAGER_alloc(VALUE klass);
53
+ VALUE QueueManager_singleton_connect(int argc, VALUE *argv, VALUE self);
54
+ VALUE QueueManager_open_queue(int argc, VALUE *argv, VALUE self);
55
+ VALUE QueueManager_initialize(VALUE self, VALUE parms);
56
+ VALUE QueueManager_connect(VALUE self);
57
+ VALUE QueueManager_disconnect(VALUE self);
58
+ VALUE QueueManager_begin(VALUE self);
59
+ VALUE QueueManager_commit(VALUE self);
60
+ VALUE QueueManager_backout(VALUE self);
61
+ VALUE QueueManager_put(VALUE self, VALUE parms);
62
+ VALUE QueueManager_reason_code(VALUE self);
63
+ VALUE QueueManager_comp_code(VALUE self);
64
+ VALUE QueueManager_reason(VALUE self);
65
+ VALUE QueueManager_exception_on_error(VALUE self);
66
+ VALUE QueueManager_connected_q(VALUE self);
67
+ VALUE QueueManager_name(VALUE self);
68
+ VALUE QueueManager_execute(VALUE self, VALUE hash);
69
+
70
+ void Queue_id_init();
71
+ VALUE QUEUE_alloc(VALUE klass);
72
+ VALUE Queue_initialize(VALUE self, VALUE parms);
73
+ VALUE Queue_singleton_open(int argc, VALUE *argv, VALUE self);
74
+ VALUE Queue_open(VALUE self);
75
+ VALUE Queue_close(VALUE self);
76
+ VALUE Queue_put(VALUE self, VALUE parms);
77
+ VALUE Queue_get(VALUE self, VALUE parms);
78
+ VALUE Queue_each(int argc, VALUE *argv, VALUE self);
79
+ VALUE Queue_name(VALUE self);
80
+ VALUE Queue_reason_code(VALUE self);
81
+ VALUE Queue_comp_code(VALUE self);
82
+ VALUE Queue_reason(VALUE self);
83
+ VALUE Queue_open_q(VALUE self);
84
+
85
+ void Queue_extract_put_message_options(VALUE hash, PMQPMO ppmo);
86
+
87
+ extern VALUE wmq_queue;
88
+ extern VALUE wmq_queue_manager;
89
+ extern VALUE wmq_message;
90
+ extern VALUE wmq_exception;
91
+
92
+ #define WMQ_EXEC_STRING_INQ_BUFFER_SIZE 32768 /* Todo: Should we make the mqai string return buffer dynamic? */
93
+
94
+ /* Internal C Structures for holding MQ data types */
95
+ typedef struct tagQUEUE_MANAGER QUEUE_MANAGER;
96
+ typedef QUEUE_MANAGER MQPOINTER PQUEUE_MANAGER;
97
+
98
+ struct tagQUEUE_MANAGER {
99
+ MQHCONN hcon; /* connection handle */
100
+ MQLONG comp_code; /* completion code */
101
+ MQLONG reason_code; /* reason code for MQCONN */
102
+ MQLONG exception_on_error; /* Non-Zero means throw exception*/
103
+ MQLONG already_connected; /* Already connected means don't disconnect */
104
+ MQLONG trace_level; /* Trace level. 0==None, 1==Info 2==Debug ..*/
105
+ MQCNO connect_options; /* MQCONNX Connection Options */
106
+ #ifdef MQCNO_VERSION_2
107
+ MQCD client_conn; /* Client Connection */
108
+ #endif
109
+ #ifdef MQCNO_VERSION_4
110
+ MQSCO ssl_config_opts; /* Security options */
111
+ #endif
112
+ #ifdef MQCD_VERSION_6
113
+ MQPTR long_remote_user_id_ptr;
114
+ #endif
115
+ #ifdef MQCD_VERSION_7
116
+ MQPTR ssl_peer_name_ptr;
117
+ #endif
118
+ #ifdef MQHB_UNUSABLE_HBAG
119
+ MQHBAG admin_bag;
120
+ MQHBAG reply_bag;
121
+ #endif
122
+ PMQBYTE p_buffer; /* message buffer */
123
+ MQLONG buffer_size; /* Allocated size of buffer */
124
+
125
+ MQLONG is_client_conn; /* Is this a Client Connection? */
126
+ void* mq_lib_handle; /* Handle to MQ library */
127
+
128
+ void(*MQCONNX)(PMQCHAR,PMQCNO,PMQHCONN,PMQLONG,PMQLONG);
129
+ void(*MQCONN) (PMQCHAR,PMQHCONN,PMQLONG,PMQLONG);
130
+ void(*MQDISC) (PMQHCONN,PMQLONG,PMQLONG);
131
+ void(*MQBEGIN)(MQHCONN,PMQVOID,PMQLONG,PMQLONG);
132
+ void(*MQBACK) (MQHCONN,PMQLONG,PMQLONG);
133
+ void(*MQCMIT) (MQHCONN,PMQLONG,PMQLONG);
134
+ void(*MQPUT1) (MQHCONN,PMQVOID,PMQVOID,PMQVOID,MQLONG,PMQVOID,PMQLONG,PMQLONG);
135
+
136
+ void(*MQOPEN) (MQHCONN,PMQVOID,MQLONG,PMQHOBJ,PMQLONG,PMQLONG);
137
+ void(*MQCLOSE)(MQHCONN,PMQHOBJ,MQLONG,PMQLONG,PMQLONG);
138
+ void(*MQGET) (MQHCONN,MQHOBJ,PMQVOID,PMQVOID,MQLONG,PMQVOID,PMQLONG,PMQLONG,PMQLONG);
139
+ void(*MQPUT) (MQHCONN,MQHOBJ,PMQVOID,PMQVOID,MQLONG,PMQVOID,PMQLONG,PMQLONG);
140
+
141
+ void(*MQINQ) (MQHCONN,MQHOBJ,MQLONG,PMQLONG,MQLONG,PMQLONG,MQLONG,PMQCHAR,PMQLONG,PMQLONG);
142
+ void(*MQSET) (MQHCONN,MQHOBJ,MQLONG,PMQLONG,MQLONG,PMQLONG,MQLONG,PMQCHAR,PMQLONG,PMQLONG);
143
+
144
+ void(*mqCreateBag)(MQLONG,PMQHBAG,PMQLONG,PMQLONG);
145
+ void(*mqDeleteBag)(PMQHBAG,PMQLONG,PMQLONG);
146
+ void(*mqClearBag)(MQHBAG,PMQLONG,PMQLONG);
147
+ void(*mqExecute)(MQHCONN,MQLONG,MQHBAG,MQHBAG,MQHBAG,MQHOBJ,MQHOBJ,PMQLONG,PMQLONG);
148
+ void(*mqCountItems)(MQHBAG,MQLONG,PMQLONG,PMQLONG,PMQLONG);
149
+ void(*mqInquireBag)(MQHBAG,MQLONG,MQLONG,PMQHBAG,PMQLONG,PMQLONG);
150
+ void(*mqInquireItemInfo)(MQHBAG,MQLONG,MQLONG,PMQLONG,PMQLONG,PMQLONG,PMQLONG);
151
+ void(*mqInquireInteger)(MQHBAG,MQLONG,MQLONG,PMQLONG,PMQLONG,PMQLONG);
152
+ void(*mqInquireString)(MQHBAG,MQLONG,MQLONG,MQLONG,PMQCHAR,PMQLONG,PMQLONG,PMQLONG,PMQLONG);
153
+ void(*mqAddInquiry)(MQHBAG,MQLONG,PMQLONG,PMQLONG);
154
+ void(*mqAddInteger)(MQHBAG,MQLONG,MQLONG,PMQLONG,PMQLONG);
155
+ void(*mqAddString)(MQHBAG,MQLONG,MQLONG,PMQCHAR,PMQLONG,PMQLONG);
156
+ };
157
+
158
+ void Queue_manager_mq_load(PQUEUE_MANAGER pqm);
159
+ void Queue_manager_mq_free(PQUEUE_MANAGER pqm);
160
+
161
+
162
+ /*
163
+ * Message
164
+ */
165
+ struct Message_build_header_arg {
166
+ PMQBYTE* pp_buffer; /* Autosize: Pointer to start of total buffer */
167
+ PMQLONG p_buffer_size; /* Autosize: Size of total buffer */
168
+ MQLONG data_length; /* Autosize: Length of the data being written */
169
+ PMQLONG p_data_offset; /* Current offset of data portion in total buffer */
170
+ MQLONG trace_level; /* Trace level. 0==None, 1==Info 2==Debug ..*/
171
+ ID next_header_id; /* Used for setting MQ Format to next header */
172
+ PMQBYTE data_format; /* Format of data. Used when next_header_id == 0 */
173
+ };
174
+
175
+ void Message_id_init();
176
+ VALUE Message_initialize(int argc, VALUE *argv, VALUE self);
177
+ VALUE Message_clear(VALUE self);
178
+ PMQBYTE Message_autogrow_data_buffer(struct Message_build_header_arg* parg, MQLONG additional_size);
179
+ void Message_build_rf_header (VALUE hash, struct Message_build_header_arg* parg);
180
+ MQLONG Message_deblock_rf_header (VALUE hash, PMQBYTE p_data, MQLONG data_len);
181
+ void Message_build_rf_header_2 (VALUE hash, struct Message_build_header_arg* parg);
182
+ MQLONG Message_deblock_rf_header_2 (VALUE hash, PMQBYTE p_data, MQLONG data_len);
183
+
184
+ void Message_build_set_format(ID header_type, PMQBYTE p_format);
185
+ void Message_build(PMQBYTE* pq_pp_buffer, PMQLONG pq_p_buffer_size, MQLONG trace_level,
186
+ VALUE parms, PPMQVOID pp_buffer, PMQLONG p_total_length, PMQMD pmqmd);
187
+ void Message_build_mqmd(VALUE self, PMQMD pmqmd);
188
+ void Message_deblock(VALUE message, PMQMD pmqmd, PMQBYTE p_buffer, MQLONG total_length, MQLONG trace_level);
189
+
190
+ int Message_build_header(VALUE hash, struct Message_build_header_arg* parg);
191
+
192
+ /* Utility methods */
193
+
194
+ /* --------------------------------------------------
195
+ * Set internal variable based on value passed in from
196
+ * a hash
197
+ * --------------------------------------------------*/
198
+ void setFromHashString(VALUE self, VALUE hash, char* pKey, char* pAttribute, char* pDefault);
199
+ void setFromHashValue(VALUE self, VALUE hash, char* pKey, char* pAttribute, VALUE valDefault);
200
+
201
+ void to_mqmd(VALUE hash, MQMD* pmqmd);
202
+ void from_mqmd(VALUE hash, MQMD* pmqmd);
203
+
204
+ void to_mqdlh(VALUE hash, MQDLH* pmqdlh);
205
+ void from_mqdlh(VALUE hash, MQDLH* pmqdlh);
206
+
207
+ void wmq_structs_id_init();
208
+ void Message_to_mqmd(VALUE hash, MQMD* pmqmd);
209
+ void Message_to_mqmd1(VALUE hash, MQMD1* pmqmd1);
210
+ void Message_to_mqrfh2(VALUE hash, MQRFH2* pmqrfh2);
211
+ void Message_to_mqrfh(VALUE hash, MQRFH* pmqrfh);
212
+ void Message_to_mqdlh(VALUE hash, MQDLH* pmqdlh);
213
+ void Message_to_mqcih(VALUE hash, MQCIH* pmqcih);
214
+ void Message_to_mqdh(VALUE hash, MQDH* pmqdh);
215
+ void Message_to_mqiih(VALUE hash, MQIIH* pmqiih);
216
+ void Message_to_mqrmh(VALUE hash, MQRMH* pmqrmh);
217
+ void Message_to_mqtm(VALUE hash, MQTM* pmqtm);
218
+ void Message_to_mqtmc2(VALUE hash, MQTMC2* pmqtmc2);
219
+ void Message_to_mqwih(VALUE hash, MQWIH* pmqwih);
220
+ void Message_to_mqxqh(VALUE hash, MQXQH* pmqxqh);
221
+ void Message_from_mqmd(VALUE hash, MQMD* pmqmd);
222
+ void Message_from_mqmd1(VALUE hash, MQMD1* pmqmd1);
223
+ void Message_from_mqrfh2(VALUE hash, MQRFH2* pmqrfh2);
224
+ void Message_from_mqrfh(VALUE hash, MQRFH* pmqrfh);
225
+ void Message_from_mqdlh(VALUE hash, MQDLH* pmqdlh);
226
+ void Message_from_mqcih(VALUE hash, MQCIH* pmqcih);
227
+ void Message_from_mqdh(VALUE hash, MQDH* pmqdh);
228
+ void Message_from_mqiih(VALUE hash, MQIIH* pmqiih);
229
+ void Message_from_mqrmh(VALUE hash, MQRMH* pmqrmh);
230
+ void Message_from_mqtm(VALUE hash, MQTM* pmqtm);
231
+ void Message_from_mqtmc2(VALUE hash, MQTMC2* pmqtmc2);
232
+ void Message_from_mqwih(VALUE hash, MQWIH* pmqwih);
233
+ void Message_from_mqxqh(VALUE hash, MQXQH* pmqxqh);
234
+
235
+ char* wmq_reason(MQLONG reason_code);
236
+ ID wmq_selector_id(MQLONG selector);
237
+ MQLONG wmq_command_lookup(ID command_id);
238
+ void wmq_selector(ID selector_id, PMQLONG selector_type, PMQLONG selector);
239
+
240
+ /* --------------------------------------------------
241
+ * MACROS for moving data between Ruby and MQ
242
+ * --------------------------------------------------*/
243
+ #define WMQ_STR2MQLONG(STR,ELEMENT) \
244
+ ELEMENT = NUM2LONG(STR);
245
+
246
+ #define WMQ_STR2MQCHAR(STR,ELEMENT) \
247
+ ELEMENT = NUM2LONG(STR);
248
+
249
+ #define WMQ_STR2MQCHARS(STR,ELEMENT) \
250
+ str = StringValue(STR); \
251
+ length = RSTRING_LEN(STR); \
252
+ size = sizeof(ELEMENT); \
253
+ strncpy(ELEMENT, RSTRING_PTR(STR), length > size ? size : length);
254
+
255
+ #define WMQ_STR2MQBYTES(STR,ELEMENT) \
256
+ str = StringValue(STR); \
257
+ length = RSTRING_LEN(str); \
258
+ size = sizeof(ELEMENT); \
259
+ if (length >= size) \
260
+ { \
261
+ memcpy(ELEMENT, RSTRING_PTR(str), size); \
262
+ } \
263
+ else \
264
+ { \
265
+ memcpy(ELEMENT, RSTRING_PTR(str), length); \
266
+ memset(ELEMENT+length, 0, size-length); \
267
+ }
268
+
269
+ #define WMQ_HASH2MQLONG(HASH,KEY,ELEMENT) \
270
+ val = rb_hash_aref(HASH, ID2SYM(ID_##KEY)); \
271
+ if (!NIL_P(val)) { WMQ_STR2MQLONG(val,ELEMENT) }
272
+
273
+ #define WMQ_HASH2MQCHARS(HASH,KEY,ELEMENT) \
274
+ val = rb_hash_aref(HASH, ID2SYM(ID_##KEY)); \
275
+ if (!NIL_P(val)) \
276
+ { \
277
+ WMQ_STR2MQCHARS(val,ELEMENT) \
278
+ }
279
+
280
+ #define WMQ_HASH2MQCHAR(HASH,KEY,ELEMENT) \
281
+ val = rb_hash_aref(HASH, ID2SYM(ID_##KEY)); \
282
+ if (!NIL_P(val)) { WMQ_STR2MQCHAR(val,ELEMENT); } \
283
+
284
+ #define WMQ_HASH2MQBYTES(HASH,KEY,ELEMENT) \
285
+ val = rb_hash_aref(HASH, ID2SYM(ID_##KEY)); \
286
+ if (!NIL_P(val)) \
287
+ { \
288
+ WMQ_STR2MQBYTES(val,ELEMENT) \
289
+ }
290
+
291
+ #define WMQ_HASH2BOOL(HASH,KEY,ELEMENT) \
292
+ val = rb_hash_aref(hash, ID2SYM(ID_##KEY)); \
293
+ if (!NIL_P(val)) \
294
+ { \
295
+ if(TYPE(val) == T_TRUE) ELEMENT = 1; \
296
+ else if(TYPE(val) == T_FALSE) ELEMENT = 0; \
297
+ else \
298
+ rb_raise(rb_eTypeError, ":" #KEY \
299
+ " must be true or false"); \
300
+ }
301
+
302
+ #define IF_TRUE(KEY,DEFAULT) \
303
+ val = rb_hash_aref(hash, ID2SYM(ID_##KEY)); \
304
+ if (NIL_P(val)) \
305
+ { \
306
+ flag = DEFAULT; \
307
+ } \
308
+ else \
309
+ { \
310
+ if(TYPE(val) == T_TRUE) flag = 1; \
311
+ else if(TYPE(val) == T_FALSE) flag = 0; \
312
+ else \
313
+ rb_raise(rb_eTypeError, ":" #KEY \
314
+ " must be true or false"); \
315
+ } \
316
+ if (flag)
317
+
318
+ /* --------------------------------------------------
319
+ * Strip trailing nulls and spaces
320
+ * --------------------------------------------------*/
321
+ #define WMQ_MQCHARS2STR(ELEMENT, TARGET) \
322
+ size = sizeof(ELEMENT); \
323
+ length = 0; \
324
+ pChar = ELEMENT + size-1; \
325
+ for (i = size; i > 0; i--) \
326
+ { \
327
+ if (*pChar != ' ' && *pChar != 0) \
328
+ { \
329
+ length = i; \
330
+ break; \
331
+ } \
332
+ pChar--; \
333
+ } \
334
+ TARGET = rb_str_new(ELEMENT,length);
335
+
336
+ #define WMQ_MQCHARS2HASH(HASH,KEY,ELEMENT) \
337
+ WMQ_MQCHARS2STR(ELEMENT, str) \
338
+ rb_hash_aset(HASH, ID2SYM(ID_##KEY), str);
339
+
340
+ #define WMQ_MQLONG2HASH(HASH,KEY,ELEMENT) \
341
+ rb_hash_aset(HASH, ID2SYM(ID_##KEY), LONG2NUM(ELEMENT));
342
+
343
+ #define WMQ_MQCHAR2HASH(HASH,KEY,ELEMENT) \
344
+ rb_hash_aset(HASH, ID2SYM(ID_##KEY), LONG2NUM(ELEMENT));
345
+
346
+ /* --------------------------------------------------
347
+ * Trailing Spaces are important with binary fields
348
+ * --------------------------------------------------*/
349
+ #define WMQ_MQBYTES2STR(ELEMENT,TARGET) \
350
+ size = sizeof(ELEMENT); \
351
+ length = 0; \
352
+ pChar = ELEMENT + size-1; \
353
+ for (i = size; i > 0; i--) \
354
+ { \
355
+ if (*pChar != 0) \
356
+ { \
357
+ length = i; \
358
+ break; \
359
+ } \
360
+ pChar--; \
361
+ } \
362
+ TARGET = rb_str_new(ELEMENT,length);
363
+
364
+ #define WMQ_MQBYTES2HASH(HASH,KEY,ELEMENT) \
365
+ WMQ_MQBYTES2STR(ELEMENT, str) \
366
+ rb_hash_aset(HASH, ID2SYM(ID_##KEY), str);
367
+