ekaranto-rubywmq 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/.document +4 -0
  2. data/LICENSE.txt +201 -0
  3. data/README.md +408 -0
  4. data/Rakefile +87 -0
  5. data/examples/each_a.rb +16 -0
  6. data/examples/each_b.rb +25 -0
  7. data/examples/each_header.rb +22 -0
  8. data/examples/files_to_q.cfg +24 -0
  9. data/examples/files_to_q.rb +31 -0
  10. data/examples/get_a.rb +19 -0
  11. data/examples/get_client.rb +35 -0
  12. data/examples/put1_a.rb +9 -0
  13. data/examples/put1_b.rb +17 -0
  14. data/examples/put1_c.rb +16 -0
  15. data/examples/put_a.rb +19 -0
  16. data/examples/put_b.rb +27 -0
  17. data/examples/put_dlh.rb +25 -0
  18. data/examples/put_dynamic_q.rb +22 -0
  19. data/examples/put_group_a.rb +35 -0
  20. data/examples/put_group_b.rb +37 -0
  21. data/examples/put_rfh.rb +51 -0
  22. data/examples/put_rfh2_a.rb +27 -0
  23. data/examples/put_rfh2_b.rb +27 -0
  24. data/examples/put_xmit_q.rb +17 -0
  25. data/examples/q_to_files.cfg +17 -0
  26. data/examples/q_to_files.rb +32 -0
  27. data/examples/request.rb +44 -0
  28. data/examples/server.rb +81 -0
  29. data/ext/decode_rfh.c +348 -0
  30. data/ext/decode_rfh.h +45 -0
  31. data/ext/extconf.rb +30 -0
  32. data/ext/extconf_client.rb +24 -0
  33. data/ext/generate/generate_const.rb +140 -0
  34. data/ext/generate/generate_reason.rb +233 -0
  35. data/ext/generate/generate_structs.rb +82 -0
  36. data/ext/generate/wmq_structs.erb +341 -0
  37. data/ext/wmq.c +90 -0
  38. data/ext/wmq.h +371 -0
  39. data/ext/wmq_message.c +671 -0
  40. data/ext/wmq_mq_load.c +217 -0
  41. data/ext/wmq_queue.c +1411 -0
  42. data/ext/wmq_queue_manager.c +1570 -0
  43. data/lib/rubywmq.rb +1 -0
  44. data/lib/wmq/message.rb +70 -0
  45. data/lib/wmq/queue_manager.rb +110 -0
  46. data/lib/wmq/version.rb +3 -0
  47. data/lib/wmq.rb +16 -0
  48. data/nbproject/project.properties +11 -0
  49. data/nbproject/project.xml +17 -0
  50. data/tests/test.rb +318 -0
  51. metadata +115 -0
@@ -0,0 +1,1570 @@
1
+ /*
2
+ * Copyright 2006 J. Reid Morrison
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 "wmq.h"
18
+
19
+ static ID ID_open;
20
+ static ID ID_call;
21
+ static ID ID_new;
22
+ static ID ID_backout;
23
+ static ID ID_connect_options;
24
+ static ID ID_q_mgr_name;
25
+ static ID ID_queue_manager;
26
+ static ID ID_exception_on_error;
27
+ static ID ID_descriptor;
28
+ static ID ID_message;
29
+ static ID ID_trace_level;
30
+
31
+ /* MQCD ID's */
32
+ static ID ID_channel_name;
33
+ static ID ID_transport_type;
34
+ static ID ID_mode_name;
35
+ static ID ID_tp_name;
36
+ static ID ID_security_exit;
37
+ static ID ID_send_exit;
38
+ static ID ID_receive_exit;
39
+ static ID ID_max_msg_length;
40
+ static ID ID_security_user_data;
41
+ static ID ID_send_user_data;
42
+ static ID ID_receive_user_data;
43
+ static ID ID_user_identifier;
44
+ static ID ID_password;
45
+ static ID ID_connection_name;
46
+ static ID ID_heartbeat_interval;
47
+ static ID ID_long_remote_user_id;
48
+ static ID ID_remote_security_id;
49
+ static ID ID_ssl_cipher_spec;
50
+ static ID ID_ssl_peer_name;
51
+ static ID ID_keep_alive_interval;
52
+ static ID ID_crypto_hardware;
53
+
54
+ /* MQSCO ID's */
55
+ static ID ID_key_repository;
56
+
57
+ /* Admin ID's */
58
+ static ID ID_create_queue;
59
+ static ID ID_q_name;
60
+ static ID ID_command;
61
+
62
+ void QueueManager_id_init(void)
63
+ {
64
+ ID_open = rb_intern("open");
65
+ ID_call = rb_intern("call");
66
+ ID_new = rb_intern("new");
67
+ ID_backout = rb_intern("backout");
68
+ ID_q_mgr_name = rb_intern("q_mgr_name");
69
+ ID_queue_manager = rb_intern("queue_manager");
70
+ ID_exception_on_error = rb_intern("exception_on_error");
71
+ ID_connect_options = rb_intern("connect_options");
72
+ ID_trace_level = rb_intern("trace_level");
73
+ ID_descriptor = rb_intern("descriptor");
74
+ ID_message = rb_intern("message");
75
+
76
+ /* MQCD ID's */
77
+ ID_channel_name = rb_intern("channel_name");
78
+ ID_transport_type = rb_intern("transport_type");
79
+ ID_mode_name = rb_intern("mode_name");
80
+ ID_tp_name = rb_intern("tp_name");
81
+ ID_security_exit = rb_intern("security_exit");
82
+ ID_send_exit = rb_intern("send_exit");
83
+ ID_receive_exit = rb_intern("receive_exit");
84
+ ID_max_msg_length = rb_intern("max_msg_length");
85
+ ID_security_user_data = rb_intern("security_user_data");
86
+ ID_send_user_data = rb_intern("send_user_data");
87
+ ID_receive_user_data = rb_intern("receive_user_data");
88
+ ID_user_identifier = rb_intern("user_identifier");
89
+ ID_password = rb_intern("password");
90
+ ID_connection_name = rb_intern("connection_name");
91
+ ID_heartbeat_interval = rb_intern("heartbeat_interval");
92
+ ID_long_remote_user_id = rb_intern("long_remote_user_id");
93
+ ID_remote_security_id = rb_intern("remote_security_id");
94
+ ID_ssl_cipher_spec = rb_intern("ssl_cipher_spec");
95
+ ID_ssl_peer_name = rb_intern("ssl_peer_name");
96
+ ID_keep_alive_interval = rb_intern("keep_alive_interval");
97
+
98
+ /* MQSCO ID's */
99
+ ID_key_repository = rb_intern("key_repository");
100
+ ID_crypto_hardware = rb_intern("crypto_hardware");
101
+
102
+ /* Admin ID's */
103
+ ID_create_queue = rb_intern("create_queue");
104
+ ID_q_name = rb_intern("q_name");
105
+ ID_command = rb_intern("command");
106
+ }
107
+
108
+ /* --------------------------------------------------
109
+ * C Structure to store MQ data types and other
110
+ * C internal values
111
+ * --------------------------------------------------*/
112
+ void QUEUE_MANAGER_free(void* p)
113
+ {
114
+ PQUEUE_MANAGER pqm = (PQUEUE_MANAGER)p;
115
+
116
+ if(pqm->trace_level>1) printf("WMQ::QueueManager Freeing QUEUE_MANAGER structure\n");
117
+
118
+ if (pqm->hcon && !pqm->already_connected) /* Valid MQ handle means MQDISC was not called */
119
+ {
120
+ printf("WMQ::QueueManager#free disconnect() was not called for Queue Manager instance!!\n");
121
+ printf("WMQ::QueueManager#free Automatically calling back() and disconnect()\n");
122
+ pqm->MQBACK(pqm->hcon, &pqm->comp_code, &pqm->reason_code);
123
+ pqm->MQDISC(&pqm->hcon, &pqm->comp_code, &pqm->reason_code);
124
+ }
125
+ #ifdef MQCD_VERSION_6
126
+ free(pqm->long_remote_user_id_ptr);
127
+ #endif
128
+ #ifdef MQCD_VERSION_7
129
+ free(pqm->ssl_peer_name_ptr);
130
+ #endif
131
+ #ifdef MQHB_UNUSABLE_HBAG
132
+ if (pqm->admin_bag != MQHB_UNUSABLE_HBAG)
133
+ {
134
+ pqm->mqDeleteBag(&pqm->admin_bag, &pqm->comp_code, &pqm->reason_code);
135
+ }
136
+
137
+ if (pqm->reply_bag != MQHB_UNUSABLE_HBAG)
138
+ {
139
+ pqm->mqDeleteBag(&pqm->reply_bag, &pqm->comp_code, &pqm->reason_code);
140
+ }
141
+ #endif
142
+ Queue_manager_mq_free(pqm);
143
+ free(pqm->p_buffer);
144
+ free(p);
145
+ }
146
+
147
+ VALUE QUEUE_MANAGER_alloc(VALUE klass)
148
+ {
149
+ static MQCNO default_MQCNO = {MQCNO_DEFAULT}; /* MQCONNX Connection Options */
150
+ #ifdef MQCNO_VERSION_2
151
+ static MQCD default_MQCD = {MQCD_CLIENT_CONN_DEFAULT}; /* Client Connection */
152
+ #endif
153
+ #ifdef MQCNO_VERSION_4
154
+ static MQSCO default_MQSCO = {MQSCO_DEFAULT};
155
+ #endif
156
+
157
+ PQUEUE_MANAGER pqm = ALLOC(QUEUE_MANAGER);
158
+
159
+ pqm->hcon = 0;
160
+ pqm->comp_code = 0;
161
+ pqm->reason_code = 0;
162
+ pqm->exception_on_error = 1;
163
+ pqm->already_connected = 0;
164
+ pqm->trace_level = 0;
165
+ memcpy(&pqm->connect_options, &default_MQCNO, sizeof(MQCNO));
166
+ #ifdef MQCNO_VERSION_2
167
+ memcpy(&pqm->client_conn, &default_MQCD, sizeof(MQCD));
168
+
169
+ /* Tell MQ to use Client Conn structures, etc. */
170
+ pqm->connect_options.Version = MQCNO_CURRENT_VERSION;
171
+ pqm->connect_options.ClientConnPtr = &pqm->client_conn;
172
+ #endif
173
+ #ifdef MQCNO_VERSION_4
174
+ memcpy(&pqm->ssl_config_opts, &default_MQSCO, sizeof(MQSCO));
175
+ #endif
176
+ #ifdef MQCD_VERSION_6
177
+ pqm->long_remote_user_id_ptr = 0;
178
+ #endif
179
+ #ifdef MQCD_VERSION_7
180
+ pqm->ssl_peer_name_ptr = 0;
181
+ #endif
182
+ #ifdef MQHB_UNUSABLE_HBAG
183
+ pqm->admin_bag = MQHB_UNUSABLE_HBAG;
184
+ pqm->reply_bag = MQHB_UNUSABLE_HBAG;
185
+ #endif
186
+ pqm->buffer_size = 0;
187
+ pqm->p_buffer = 0;
188
+
189
+ pqm->is_client_conn = 0;
190
+ pqm->mq_lib_handle = 0;
191
+
192
+ return Data_Wrap_Struct(klass, 0, QUEUE_MANAGER_free, pqm);
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * new(...)
198
+ *
199
+ * Parameters:
200
+ * * Since the number of parameters can vary dramatically, all parameters are passed by name in a hash
201
+ * * See QueueManager.new for details on all the parameters
202
+ *
203
+ * Note:
204
+ * * It is not recommended to use this method, rather use QueueManager.connect, since
205
+ * it will automatically disconnect from the queue manager. It also deals with backing out
206
+ * the current unit of work in the event of an unhandled exception. E.g. Syntax Error
207
+ * * RuntimeError and ArgumentError exceptions are always thrown regardless of the
208
+ * value of :exception_on_error
209
+ *
210
+ * Todo:
211
+ * * Support multiple send and receive exits
212
+ */
213
+ VALUE QueueManager_initialize(VALUE self, VALUE hash)
214
+ {
215
+ VALUE val;
216
+ VALUE str;
217
+ size_t size;
218
+ size_t length;
219
+ PQUEUE_MANAGER pqm;
220
+
221
+ Check_Type(hash, T_HASH);
222
+
223
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
224
+
225
+ WMQ_HASH2MQLONG(hash,trace_level, pqm->trace_level)
226
+
227
+ /* @name = options[:q_mgr_name] || '' # QMGR Name optional with Client Connection */
228
+ val = rb_hash_aref(hash, ID2SYM(ID_q_mgr_name));
229
+ if (NIL_P(val))
230
+ {
231
+ rb_iv_set(self, "@name", rb_str_new2(""));
232
+ if(pqm->trace_level > 1) printf("WMQ::QueueManager#initialize() Queue Manager:[Not specified, use Default QMGR]\n");
233
+ }
234
+ else
235
+ {
236
+ rb_iv_set(self, "@name", val);
237
+ if(pqm->trace_level > 1) printf("WMQ::QueueManager#initialize() Queue Manager:%s\n", RSTRING_PTR(val));
238
+ }
239
+
240
+ WMQ_HASH2BOOL(hash,exception_on_error, pqm->exception_on_error)
241
+
242
+ /*
243
+ * All Client connection parameters are ignored if connection_name is missing
244
+ */
245
+ #ifdef MQCNO_VERSION_2
246
+ if(!NIL_P(rb_hash_aref(hash, ID2SYM(ID_connection_name))))
247
+ {
248
+ PMQCD pmqcd = &pqm->client_conn; /* Process MQCD */
249
+ pqm->is_client_conn = 1; /* Set to Client connection */
250
+
251
+ WMQ_HASH2MQCHARS(hash,connection_name, pmqcd->ConnectionName)
252
+ WMQ_HASH2MQLONG (hash,transport_type, pmqcd->TransportType)
253
+ WMQ_HASH2MQCHARS(hash,mode_name, pmqcd->ModeName)
254
+ WMQ_HASH2MQCHARS(hash,tp_name, pmqcd->TpName)
255
+ WMQ_HASH2MQCHARS(hash,security_exit, pmqcd->SecurityExit)
256
+ WMQ_HASH2MQCHARS(hash,send_exit, pmqcd->SendExit)
257
+ WMQ_HASH2MQCHARS(hash,receive_exit, pmqcd->ReceiveExit)
258
+ WMQ_HASH2MQLONG (hash,max_msg_length, pmqcd->MaxMsgLength)
259
+ WMQ_HASH2MQCHARS(hash,security_user_data, pmqcd->SecurityUserData)
260
+ WMQ_HASH2MQCHARS(hash,send_user_data, pmqcd->SendUserData)
261
+ WMQ_HASH2MQCHARS(hash,receive_user_data, pmqcd->ReceiveUserData)
262
+ WMQ_HASH2MQCHARS(hash,user_identifier, pmqcd->UserIdentifier)
263
+ WMQ_HASH2MQCHARS(hash,password, pmqcd->Password)
264
+
265
+ /* Default channel name to system default */
266
+ val = rb_hash_aref(hash, ID2SYM(ID_channel_name));
267
+ if (NIL_P(val))
268
+ {
269
+ strncpy(pmqcd->ChannelName, "SYSTEM.DEF.SVRCONN", sizeof(pmqcd->ChannelName));
270
+ }
271
+ else
272
+ {
273
+ WMQ_HASH2MQCHARS(hash,channel_name, pmqcd->ChannelName)
274
+ }
275
+
276
+ #ifdef MQCD_VERSION_4
277
+ WMQ_HASH2MQLONG(hash,heartbeat_interval, pmqcd->HeartbeatInterval)
278
+ /* TODO:
279
+ WMQ_HASH2MQLONG(hash,exit_name_length, pmqcd->ExitNameLength)
280
+ WMQ_HASH2MQLONG(hash,exit_data_length, pmqcd->ExitDataLength)
281
+ WMQ_HASH2MQLONG(hash,send_exits_defined, pmqcd->SendExitsDefined)
282
+ WMQ_HASH2MQLONG(hash,receive_exits_defined, pmqcd->ReceiveExitsDefined)
283
+ TO_PTR (send_exit_ptr, pmqcd->SendExitPtr)
284
+ TO_PTR (send_user_data_ptr, pmqcd->SendUserDataPtr)
285
+ TO_PTR (receive_exit_ptr, pmqcd->ReceiveExitPtr)
286
+ TO_PTR (receive_user_data_ptr, pmqcd->ReceiveUserDataPtr)
287
+ */
288
+ #endif
289
+ #ifdef MQCD_VERSION_6
290
+ val = rb_hash_aref(hash, ID2SYM(ID_long_remote_user_id));
291
+ if (!NIL_P(val))
292
+ {
293
+ str = StringValue(val);
294
+ length = RSTRING_LEN(str);
295
+
296
+ if (length > 0)
297
+ {
298
+ MQPTR pBuffer;
299
+ if(pqm->trace_level > 1)
300
+ printf("WMQ::QueueManager#initialize() Setting long_remote_user_id:%s\n",
301
+ RSTRING_PTR(str));
302
+
303
+ /* Include null at end of string */
304
+ pBuffer = ALLOC_N(char, length+1);
305
+ memcpy(pBuffer, RSTRING_PTR(str), length+1);
306
+
307
+ pmqcd->LongRemoteUserIdLength = length;
308
+ pmqcd->LongRemoteUserIdPtr = pBuffer;
309
+ pqm->long_remote_user_id_ptr = pBuffer;
310
+ }
311
+ }
312
+ WMQ_HASH2MQBYTES(hash,remote_security_id, pmqcd->RemoteSecurityId)
313
+ WMQ_HASH2MQCHARS(hash,ssl_cipher_spec, pmqcd->SSLCipherSpec)
314
+ #endif
315
+ #ifdef MQCD_VERSION_7
316
+ val = rb_hash_aref(hash, ID2SYM(ID_ssl_peer_name));
317
+ if (!NIL_P(val))
318
+ {
319
+ str = StringValue(val);
320
+ length = RSTRING_LEN(str);
321
+
322
+ if (length > 0)
323
+ {
324
+ MQPTR pBuffer;
325
+ if(pqm->trace_level > 1)
326
+ printf("WMQ::QueueManager#initialize() Setting ssl_peer_name:%s\n",
327
+ RSTRING_PTR(str));
328
+
329
+ /* Include null at end of string */
330
+ pBuffer = ALLOC_N(char, length+1);
331
+ memcpy(pBuffer, RSTRING_PTR(str), length+1);
332
+
333
+ pmqcd->SSLPeerNameLength = length;
334
+ pmqcd->SSLPeerNamePtr = pBuffer;
335
+ pqm->ssl_peer_name_ptr = pBuffer;
336
+ }
337
+ }
338
+ WMQ_HASH2MQLONG(hash,keep_alive_interval, pmqcd->KeepAliveInterval)
339
+
340
+ /* Only set if SSL options are supplied, otherwise
341
+ * environment variables are ignored: MQSSLKEYR and MQSSLCRYP
342
+ * Any SSL info in the client channel definition tables is also ignored
343
+ */
344
+ if (!NIL_P(rb_hash_aref(hash, ID2SYM(ID_key_repository))) ||
345
+ !NIL_P(rb_hash_aref(hash, ID2SYM(ID_crypto_hardware))))
346
+ {
347
+ /* Process MQSCO */
348
+ WMQ_HASH2MQCHARS(hash,key_repository, pqm->ssl_config_opts.KeyRepository)
349
+ WMQ_HASH2MQCHARS(hash,crypto_hardware, pqm->ssl_config_opts.CryptoHardware)
350
+
351
+ pqm->connect_options.SSLConfigPtr = &pqm->ssl_config_opts;
352
+ }
353
+ #endif
354
+
355
+ }
356
+ else
357
+ {
358
+ pqm->is_client_conn = 0; /* Set to Server connection */
359
+ }
360
+ #endif
361
+
362
+ #ifdef MQCNO_VERSION_4
363
+ /* Process MQCNO */
364
+ WMQ_HASH2MQLONG(hash,connect_options, pqm->connect_options.Options)
365
+ #endif
366
+
367
+ /* --------------------------------------------------
368
+ * TODO: MQAIR Structure - LDAP Security
369
+ * --------------------------------------------------*/
370
+
371
+ return Qnil;
372
+ }
373
+
374
+ /*
375
+ * Before working with any queues, it is necessary to connect
376
+ * to the queue manager.
377
+ *
378
+ * Returns:
379
+ * * true : On Success
380
+ * * false: On Failure
381
+ *
382
+ * comp_code and reason_code are also updated.
383
+ * reason will return a text description of the reason_code
384
+ *
385
+ * Throws:
386
+ * * WMQ::WMQException if comp_code != MQCC_OK
387
+ * * Except if :exception_on_error => false was supplied as a parameter
388
+ * to QueueManager.new
389
+ */
390
+ VALUE QueueManager_connect(VALUE self)
391
+ {
392
+ VALUE name;
393
+
394
+ PQUEUE_MANAGER pqm;
395
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
396
+ pqm->already_connected = 0;
397
+
398
+ Queue_manager_mq_load(pqm); /* Load MQ Library */
399
+
400
+ name = rb_iv_get(self,"@name");
401
+ name = StringValue(name);
402
+
403
+ if(pqm->trace_level)
404
+ printf("WMQ::QueueManager#connect() Connect to Queue Manager:%s\n", RSTRING_PTR(name));
405
+
406
+ if (pqm->hcon) /* Disconnect from qmgr if already connected, ignore errors */
407
+ {
408
+ if(pqm->trace_level)
409
+ printf("WMQ::QueueManager#connect() Already connected to Queue Manager:%s, Disconnecting first!\n", RSTRING_PTR(name));
410
+
411
+ pqm->MQDISC(&pqm->hcon, &pqm->comp_code, &pqm->reason_code);
412
+ }
413
+
414
+ pqm->MQCONNX(
415
+ RSTRING_PTR(name), /* queue manager */
416
+ &pqm->connect_options, /* Connection Options */
417
+ &pqm->hcon, /* connection handle */
418
+ &pqm->comp_code, /* completion code */
419
+ &pqm->reason_code); /* connect reason code */
420
+
421
+ if(pqm->trace_level)
422
+ printf("WMQ::QueueManager#connect() MQCONNX completed with reason:%s, Handle:%ld\n",
423
+ wmq_reason(pqm->reason_code),
424
+ (long)pqm->hcon);
425
+
426
+ if (pqm->comp_code == MQCC_FAILED)
427
+ {
428
+ pqm->hcon = 0;
429
+
430
+ if (pqm->exception_on_error)
431
+ {
432
+ rb_raise(wmq_exception,
433
+ "WMQ::QueueManager#connect(). Error connecting to Queue Manager:%s, reason:%s",
434
+ RSTRING_PTR(name),
435
+ wmq_reason(pqm->reason_code));
436
+ }
437
+
438
+ return Qfalse;
439
+ }
440
+
441
+ if (pqm->reason_code == MQRC_ALREADY_CONNECTED)
442
+ {
443
+ if(pqm->trace_level) printf("WMQ::QueueManager#connect() Already connected\n");
444
+ pqm->already_connected = 1;
445
+ }
446
+
447
+ return Qtrue;
448
+ }
449
+
450
+ /*
451
+ * Disconnect from this QueueManager instance
452
+ *
453
+ * Returns:
454
+ * * true : On Success
455
+ * * false: On Failure
456
+ *
457
+ * comp_code and reason_code are also updated.
458
+ * reason will return a text description of the reason_code
459
+ *
460
+ * Throws:
461
+ * * WMQ::WMQException if comp_code != MQCC_OK
462
+ * * Except if :exception_on_error => false was supplied as a parameter
463
+ * to QueueManager.new
464
+ */
465
+ VALUE QueueManager_disconnect(VALUE self)
466
+ {
467
+ PQUEUE_MANAGER pqm;
468
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
469
+
470
+ if(pqm->trace_level) printf ("WMQ::QueueManager#disconnect() Queue Manager Handle:%ld\n", (long)pqm->hcon);
471
+
472
+ if (!pqm->already_connected)
473
+ {
474
+ pqm->MQDISC(&pqm->hcon, &pqm->comp_code, &pqm->reason_code);
475
+
476
+ if(pqm->trace_level) printf("WMQ::QueueManager#disconnect() MQDISC completed with reason:%s\n", wmq_reason(pqm->reason_code));
477
+
478
+ if (pqm->comp_code != MQCC_OK)
479
+ {
480
+ if (pqm->exception_on_error)
481
+ {
482
+ VALUE name = rb_iv_get(self,"@name");
483
+ name = StringValue(name);
484
+
485
+ rb_raise(wmq_exception,
486
+ "WMQ::QueueManager#disconnect(). Error disconnecting from Queue Manager:%s, reason:%s",
487
+ RSTRING_PTR(name),
488
+ wmq_reason(pqm->reason_code));
489
+ }
490
+
491
+ return Qfalse;
492
+ }
493
+ }
494
+ else
495
+ {
496
+ pqm->comp_code = 0;
497
+ pqm->reason_code = 0;
498
+
499
+ if(pqm->trace_level) printf ("WMQ::QueueManager#disconnect() Not calling MQDISC, since already connected on connect\n");
500
+ }
501
+
502
+ pqm->hcon = 0;
503
+
504
+ return Qtrue;
505
+ }
506
+
507
+ /*
508
+ * Commit the current unit of work for this QueueManager instance
509
+ *
510
+ * Note:
511
+ * * commit will have no effect if all put and get operations were performed
512
+ * without specifying :sync => true
513
+ *
514
+ * Returns:
515
+ * * true : On Success
516
+ * * false: On Failure
517
+ *
518
+ * comp_code and reason_code are also updated.
519
+ * reason will return a text description of the reason_code
520
+ *
521
+ * Throws:
522
+ * * WMQ::WMQException if comp_code != MQCC_OK
523
+ * * Except if :exception_on_error => false was supplied as a parameter
524
+ * to QueueManager.new
525
+ */
526
+ VALUE QueueManager_commit(VALUE self)
527
+ {
528
+ PQUEUE_MANAGER pqm;
529
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
530
+
531
+ if(pqm->trace_level) printf ("WMQ::QueueManager#commit() Queue Manager Handle:%ld\n", (long)pqm->hcon);
532
+
533
+ pqm->MQCMIT(pqm->hcon, &pqm->comp_code, &pqm->reason_code);
534
+
535
+ if(pqm->trace_level) printf("WMQ::QueueManager#commit() MQCMIT completed with reason:%s\n", wmq_reason(pqm->reason_code));
536
+
537
+ if (pqm->comp_code != MQCC_OK)
538
+ {
539
+ if (pqm->exception_on_error)
540
+ {
541
+ VALUE name = rb_iv_get(self,"@name");
542
+ name = StringValue(name);
543
+
544
+ rb_raise(wmq_exception,
545
+ "WMQ::QueueManager#commit(). Error commiting changes to Queue Manager:%s, reason:%s",
546
+ RSTRING_PTR(name),
547
+ wmq_reason(pqm->reason_code));
548
+ }
549
+ return Qfalse;
550
+ }
551
+
552
+ return Qtrue;
553
+ }
554
+
555
+ /*
556
+ * Backout the current unit of work for this QueueManager instance
557
+ *
558
+ * Since the last commit or rollback any messages put to a queue
559
+ * under synchpoint will be removed and any messages retrieved
560
+ * under synchpoint from any queues will be returned
561
+ *
562
+ * Note:
563
+ * * backout will have no effect if all put and get operations were performed
564
+ * without specifying :sync => true
565
+ *
566
+ * Returns:
567
+ * * true : On Success
568
+ * * false: On Failure
569
+ *
570
+ * comp_code and reason_code are also updated.
571
+ * reason will return a text description of the reason_code
572
+ *
573
+ * Throws:
574
+ * * WMQ::WMQException if comp_code != MQCC_OK
575
+ * * Except if :exception_on_error => false was supplied as a parameter
576
+ * to QueueManager.new
577
+ */
578
+ VALUE QueueManager_backout(VALUE self)
579
+ {
580
+ PQUEUE_MANAGER pqm;
581
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
582
+
583
+ if(pqm->trace_level) printf ("WMQ::QueueManager#backout() Queue Manager Handle:%ld\n", (long)pqm->hcon);
584
+
585
+ pqm->MQBACK(pqm->hcon, &pqm->comp_code, &pqm->reason_code);
586
+
587
+ if(pqm->trace_level) printf("WMQ::QueueManager#backout() MQBACK completed with reason:%s\n", wmq_reason(pqm->reason_code));
588
+
589
+ if (pqm->comp_code != MQCC_OK)
590
+ {
591
+ if (pqm->exception_on_error)
592
+ {
593
+ VALUE name = rb_iv_get(self,"@name");
594
+ name = StringValue(name);
595
+
596
+ rb_raise(wmq_exception,
597
+ "WMQ::QueueManager#backout(). Error backing out changes to Queue Manager:%s, reason:%s",
598
+ RSTRING_PTR(name),
599
+ wmq_reason(pqm->reason_code));
600
+ }
601
+ return Qfalse;
602
+ }
603
+
604
+ return Qtrue;
605
+ }
606
+
607
+ /*
608
+ * Advanced WebSphere MQ Use:
609
+ *
610
+ * Begin a unit of work between this QueueManager instance and another
611
+ * resource such as a Database
612
+ *
613
+ * Starts a new unit of work under which put and get can be called with
614
+ * with the parameter :sync => true
615
+ *
616
+ * Returns:
617
+ * * true : On Success
618
+ * * false: On Failure
619
+ *
620
+ * comp_code and reason_code are also updated.
621
+ * reason will return a text description of the reason_code
622
+ *
623
+ * Throws:
624
+ * * WMQ::WMQException if comp_code != MQCC_OK
625
+ * * Except if :exception_on_error => false was supplied as a parameter
626
+ * to QueueManager.new
627
+ */
628
+ VALUE QueueManager_begin(VALUE self)
629
+ {
630
+ PQUEUE_MANAGER pqm;
631
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
632
+
633
+ if(pqm->trace_level) printf ("WMQ::QueueManager#begin() Queue Manager Handle:%ld\n", (long)pqm->hcon);
634
+
635
+ pqm->MQBEGIN(pqm->hcon, 0, &pqm->comp_code, &pqm->reason_code);
636
+
637
+ if(pqm->trace_level) printf("WMQ::QueueManager#begin() MQBEGIN completed with reason:%s\n", wmq_reason(pqm->reason_code));
638
+
639
+ if (pqm->comp_code != MQCC_OK)
640
+ {
641
+ if (pqm->exception_on_error)
642
+ {
643
+ VALUE name = rb_iv_get(self,"@name");
644
+ name = StringValue(name);
645
+
646
+ rb_raise(wmq_exception,
647
+ "WMQ::QueueManager#begin(). Error starting unit of work on Queue Manager:%s, reason:%s",
648
+ RSTRING_PTR(name),
649
+ wmq_reason(pqm->reason_code));
650
+ }
651
+ return Qfalse;
652
+ }
653
+
654
+ return Qtrue;
655
+ }
656
+
657
+ /*
658
+ * call-seq:
659
+ * put(parameters)
660
+ *
661
+ * Put a message to the queue without having to first open the queue
662
+ * Recommended for reply queues that change frequently
663
+ *
664
+ * * parameters: a Hash consisting of one or more of the following parameters
665
+ *
666
+ * Summary of parameters and their WebSphere MQ equivalents
667
+ * queue.get( # WebSphere MQ Equivalents:
668
+ * :q_name => 'Queue Name', # MQOD.ObjectName
669
+ * :q_name => { queue_manager=>'QMGR_name', # MQOD.ObjectQMgrName
670
+ * q_name =>'q_name'}
671
+ * :message => my_message, # n/a : Instance of Message
672
+ * :data => "Hello World", # n/a : Data to send
673
+ * :sync => false, # MQGMO_SYNCPOINT
674
+ * :new_id => true, # MQPMO_NEW_MSG_ID & MQPMO_NEW_CORREL_ID
675
+ * :new_msg_id => true, # MQPMO_NEW_MSG_ID
676
+ * :new_correl_id => true, # MQPMO_NEW_CORREL_ID
677
+ * :fail_if_quiescing => true, # MQOO_FAIL_IF_QUIESCING
678
+ * :options => WMQ::MQPMO_FAIL_IF_QUIESCING # MQPMO_*
679
+ * )
680
+ *
681
+ * Mandatory Parameters
682
+ * * :q_name => String
683
+ * * Name of the existing WebSphere MQ local queue, model queue or remote queue to open
684
+ * * To open remote queues for which a local remote queue definition is not available
685
+ * pass a Hash as q_name (see q_name => Hash)
686
+ * OR
687
+ * * :q_name => Hash
688
+ * * q_name => String
689
+ * * Name of the existing WebSphere MQ local queue, model queue or remote queue to open
690
+ * * :q_mgr_name => String
691
+ * * Name of the remote WebSphere MQ queue manager to send the message to.
692
+ * * This allows a message to be written to a queue on a remote queue manager
693
+ * where a remote queue definition is not defined locally
694
+ * * Commonly used to reply to messages from remote systems
695
+ * * If q_mgr_name is the same as the local queue manager name then the message
696
+ * is merely written to the local queue.
697
+ * * Note: q_mgr_name should only be supplied when putting messages to the queue.
698
+ * It is not possible to get messages from a queue on a queue manager other
699
+ * than the currently connected queue manager
700
+ *
701
+ * * Either :message or :data must be supplied
702
+ * * If both are supplied, then :data will be written to the queue. The data in :message
703
+ * will be ignored
704
+ *
705
+ * Optional Parameters
706
+ * * :data => String
707
+ * * Data to be written to the queue. Can be binary or text data
708
+ *
709
+ * * :message => Message
710
+ * * An instance of the WMQ::Message
711
+ * * The Message descriptor, headers and data is retrieved from :message
712
+ * * message.data is ignored if :data is supplied
713
+ *
714
+ * * :sync => true or false
715
+ * * Determines whether the get is performed under synchpoint.
716
+ * I.e. Under the current unit of work
717
+ * Default: false
718
+ *
719
+ * * :new_id => true or false
720
+ * * Generate a new message id and correlation id for this
721
+ * message. :new_msg_id and :new_correl_id will be ignored
722
+ * if this parameter is true
723
+ * Default: false
724
+ *
725
+ * * :new_msg_id => true or false
726
+ * * Generate a new message id for this message
727
+ * * Note: A blank message id will result in a new message id anyway.
728
+ * However, for subsequent puts using the same message descriptor, the same
729
+ * message id will be used.
730
+ * Default: false
731
+ *
732
+ * * :new_correl_id => true or false
733
+ * * Generate a new correlation id for this message
734
+ * Default: false
735
+ *
736
+ * * :fail_if_quiescing => true or false
737
+ * * Determines whether the WMQ::Queue#put call will fail if the queue manager is
738
+ * in the process of being quiesced.
739
+ * * Note: This interface differs from other WebSphere MQ interfaces,
740
+ * they do not default to true.
741
+ * Default: true
742
+ * Equivalent to: MQGMO_FAIL_IF_QUIESCING
743
+ *
744
+ * * Note: As part of the application design, carefull consideration
745
+ * should be given as to when to allow a transaction or
746
+ * unit of work to complete or fail under this condition.
747
+ * As such it is important to include this option where
748
+ * appropriate so that MQ Administrators can shutdown the
749
+ * queue managers without having to resort to the 'immediate'
750
+ * shutdown option.
751
+ *
752
+ * * :options => Fixnum (Advanced MQ Use only)
753
+ * * Numeric field containing any of the MQ Put message options or'd together
754
+ * * E.g. :options => WMQ::MQPMO_PASS_IDENTITY_CONTEXT | WMQ::MQPMO_ALTERNATE_USER_AUTHORITY
755
+ * * Note: If :options is supplied, it is applied first, then the above parameters are
756
+ * applied afterwards.
757
+ * * One or more of the following values:
758
+ * WMQ::MQPMO_NO_SYNCPOINT
759
+ * WMQ::MQPMO_LOGICAL_ORDER
760
+ * WMQ::MQPMO_NO_CONTEXT
761
+ * WMQ::MQPMO_DEFAULT_CONTEXT
762
+ * WMQ::MQPMO_PASS_IDENTITY_CONTEXT
763
+ * WMQ::MQPMO_PASS_ALL_CONTEXT
764
+ * WMQ::MQPMO_SET_IDENTITY_CONTEXT
765
+ * WMQ::MQPMO_SET_ALL_CONTEXT
766
+ * WMQ::MQPMO_ALTERNATE_USER_AUTHORITY
767
+ * WMQ::MQPMO_RESOLVE_LOCAL_Q
768
+ * WMQ::MQPMO_NONE
769
+ * * Please see the WebSphere MQ documentation for more details on the above options
770
+ * Default: WMQ::MQPMO_NONE
771
+ *
772
+ * Returns:
773
+ * * true : On Success
774
+ * * false: On Failure
775
+ *
776
+ * comp_code and reason_code are also updated.
777
+ * reason will return a text description of the reason_code
778
+ *
779
+ * Throws:
780
+ * * WMQ::WMQException if comp_code == MQCC_FAILED
781
+ * * Except if :exception_on_error => false was supplied as a parameter
782
+ * to QueueManager.new
783
+ */
784
+ VALUE QueueManager_put(VALUE self, VALUE hash)
785
+ {
786
+ MQLONG BufferLength; /* Length of the message in Buffer */
787
+ PMQVOID pBuffer; /* Message data */
788
+ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */
789
+ MQPMO pmo = {MQPMO_DEFAULT}; /* put message options */
790
+ MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */
791
+ VALUE q_name;
792
+ VALUE str;
793
+ size_t size;
794
+ size_t length;
795
+ VALUE val;
796
+
797
+ PQUEUE_MANAGER pqm;
798
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
799
+
800
+ Check_Type(hash, T_HASH);
801
+
802
+ q_name = rb_hash_aref(hash, ID2SYM(ID_q_name));
803
+
804
+ if (NIL_P(q_name))
805
+ {
806
+ rb_raise(rb_eArgError,
807
+ "Mandatory parameter :q_name is missing from WMQ::QueueManager::put1()");
808
+ }
809
+
810
+ /* --------------------------------------------------
811
+ * If :q_name is a hash, extract :q_name and :q_mgr_name
812
+ * --------------------------------------------------*/
813
+ if(TYPE(q_name) == T_HASH)
814
+ {
815
+ WMQ_HASH2MQCHARS(q_name, q_mgr_name, od.ObjectQMgrName)
816
+
817
+ q_name = rb_hash_aref(val, ID2SYM(ID_q_name));
818
+ if (NIL_P(q_name))
819
+ {
820
+ rb_raise(rb_eArgError,
821
+ "Mandatory parameter :q_name missing from :q_name hash passed to WMQ::QueueManager#put");
822
+ }
823
+ }
824
+
825
+ WMQ_STR2MQCHARS(q_name,od.ObjectName)
826
+
827
+ Queue_extract_put_message_options(hash, &pmo);
828
+ Message_build(&pqm->p_buffer, &pqm->buffer_size, pqm->trace_level,
829
+ hash, &pBuffer, &BufferLength, &md);
830
+
831
+ if(pqm->trace_level) printf("WMQ::QueueManager#put Queue Manager Handle:%ld\n", (long)pqm->hcon);
832
+
833
+ pqm->MQPUT1(
834
+ pqm->hcon, /* connection handle */
835
+ &od, /* object descriptor */
836
+ &md, /* message descriptor */
837
+ &pmo, /* put message options */
838
+ BufferLength, /* message length */
839
+ pBuffer, /* message buffer */
840
+ &pqm->comp_code, /* completion code */
841
+ &pqm->reason_code); /* reason code */
842
+
843
+ if(pqm->trace_level) printf("WMQ::QueueManager#put MQPUT1 ended with reason:%s\n", wmq_reason(pqm->reason_code));
844
+
845
+ if (pqm->reason_code != MQRC_NONE)
846
+ {
847
+ if (pqm->exception_on_error)
848
+ {
849
+ VALUE qmgr_name = QueueManager_name(self);
850
+
851
+ rb_raise(wmq_exception,
852
+ "WMQ::QueueManager.put(). Error writing a message to Queue:%s on Queue Manager:%s reason:%s",
853
+ RSTRING_PTR(q_name),
854
+ RSTRING_PTR(qmgr_name),
855
+ wmq_reason(pqm->reason_code));
856
+ }
857
+ return Qfalse;
858
+ }
859
+ else
860
+ {
861
+ VALUE message = rb_hash_aref(hash, ID2SYM(ID_message));
862
+ if(!NIL_P(message))
863
+ {
864
+ VALUE descriptor = rb_funcall(message, ID_descriptor, 0);
865
+ Message_from_mqmd(descriptor, &md); /* This could be optimized to output only fields */
866
+ }
867
+ }
868
+
869
+ return Qtrue;
870
+ }
871
+
872
+ /*
873
+ * Return the completion code for the last MQ operation
874
+ *
875
+ * Returns => FixNum
876
+ * * WMQ::MQCC_OK 0
877
+ * * WMQ::MQCC_WARNING 1
878
+ * * WMQ::MQCC_FAILED 2
879
+ * * WMQ::MQCC_UNKNOWN -1
880
+ *
881
+ */
882
+ VALUE QueueManager_comp_code(VALUE self)
883
+ {
884
+ PQUEUE_MANAGER pqm;
885
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
886
+ return LONG2NUM(pqm->comp_code);
887
+ }
888
+
889
+ /*
890
+ * Return the reason code for the last MQ operation
891
+ *
892
+ * Returns => FixNum
893
+ * * For a complete list of reason codes, please see WMQ Constants or
894
+ * the WebSphere MQ documentation for Reason Codes
895
+ *
896
+ * Note
897
+ * * The list of Reason Codes varies depending on the version of WebSphere MQ
898
+ * and the operating system on which Ruby WMQ was compiled
899
+ */
900
+ VALUE QueueManager_reason_code(VALUE self)
901
+ {
902
+ PQUEUE_MANAGER pqm;
903
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
904
+ return LONG2NUM(pqm->reason_code);
905
+ }
906
+
907
+ /*
908
+ * Returns a textual representation of the reason_code for the last MQ operation
909
+ *
910
+ * Returns => String
911
+ * * For a complete list of reasons, please see WMQ Constants or
912
+ * the WebSphere MQ documentation for Reason Codes
913
+ *
914
+ * Note
915
+ * * The list of Reason Codes varies depending on the version of WebSphere MQ
916
+ * and the operating system on which Ruby WMQ was compiled
917
+ */
918
+ VALUE QueueManager_reason(VALUE self)
919
+ {
920
+ PQUEUE_MANAGER pqm;
921
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
922
+ return rb_str_new2(wmq_reason(pqm->reason_code));
923
+ }
924
+
925
+ /*
926
+ * Returns whether this QueueManager instance is set
927
+ * to throw a WMQ::WMQException whenever an MQ operation fails
928
+ *
929
+ * Returns:
930
+ * * true : This QueueManager instance will throw a WMQ::WMQException whenever
931
+ * an MQ operation fails. I.e. if comp_code != WMQ::OK.
932
+ * * false: WMQ::WMQException will not be thrown
933
+ *
934
+ * Note:
935
+ * * RuntimeError and ArgumentError exceptions are always thrown regardless of the
936
+ * value of exception_on_error
937
+ */
938
+ VALUE QueueManager_exception_on_error(VALUE self)
939
+ {
940
+ PQUEUE_MANAGER pqm;
941
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
942
+ if (pqm->exception_on_error)
943
+ {
944
+ return Qtrue;
945
+ }
946
+
947
+ return Qfalse;
948
+ }
949
+
950
+ /*
951
+ * Returns whether this QueueManager instance is currently
952
+ * connected to a WebSphere MQ queue manager
953
+ *
954
+ * Returns:
955
+ * * true : This QueueManager instance is connected to a local or remote queue manager
956
+ * * false: This QueueManager instance is not currently connected to a local or
957
+ * remote queue manager
958
+ */
959
+ VALUE QueueManager_connected_q(VALUE self)
960
+ {
961
+ PQUEUE_MANAGER pqm;
962
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
963
+ if (pqm->hcon)
964
+ {
965
+ return Qtrue;
966
+ }
967
+ return Qfalse;
968
+ }
969
+
970
+ /*
971
+ * Returns the QueueManager name => String
972
+ */
973
+ VALUE QueueManager_name(VALUE self)
974
+ {
975
+ return rb_iv_get(self,"@name");
976
+ }
977
+
978
+ static VALUE QueueManager_open_queue_block(VALUE message, VALUE proc)
979
+ {
980
+ return rb_funcall(proc, ID_call, 1, message);
981
+ }
982
+
983
+ static VALUE QueueManager_open_queue_each(VALUE parameters)
984
+ {
985
+ return Queue_singleton_open(1, &parameters, wmq_queue);
986
+ }
987
+
988
+ /*
989
+ * call-seq:
990
+ * open_queue(...)
991
+ * access_queue(...)
992
+ *
993
+ * Open the specified queue, then close it once the
994
+ * supplied code block has completed
995
+ *
996
+ * Parameters:
997
+ * * Since the number of parameters can vary dramatically, all parameters are passed by name in a hash
998
+ * * See Queue.open for the complete list of parameters, except that :queue_manager is *not* required
999
+ * since it is supplied automatically by this method
1000
+ *
1001
+ * Example:
1002
+ * require 'wmq/wmq_client'
1003
+ *
1004
+ * WMQ::QueueManager.connect(:q_mgr_name=>'REID', :connection_name=>'localhost(1414)') do |qmgr|
1005
+ * qmgr.open_queue(:q_name=>'TEST.QUEUE', :mode=>:output) do |queue|
1006
+ * queue.put(:data => 'Hello World')
1007
+ * end
1008
+ * end
1009
+ */
1010
+ VALUE QueueManager_open_queue(int argc, VALUE *argv, VALUE self)
1011
+ {
1012
+ VALUE parameters;
1013
+ VALUE proc;
1014
+
1015
+ /* Extract parameters and code block (Proc) */
1016
+ rb_scan_args(argc, argv, "1&", &parameters, &proc);
1017
+
1018
+ Check_Type(parameters, T_HASH);
1019
+ rb_hash_aset(parameters, ID2SYM(ID_queue_manager), self);
1020
+
1021
+ return rb_iterate(QueueManager_open_queue_each, parameters, QueueManager_open_queue_block, proc);
1022
+ }
1023
+
1024
+ struct QueueManager_singleton_connect_arg {
1025
+ VALUE self;
1026
+ VALUE proc;
1027
+ };
1028
+
1029
+ static VALUE QueueManager_singleton_connect_body2(struct QueueManager_singleton_connect_arg* arg)
1030
+ {
1031
+ return rb_funcall(arg->proc, ID_call, 1, arg->self);
1032
+ }
1033
+
1034
+ static VALUE QueueManager_singleton_connect_rescue(VALUE self)
1035
+ {
1036
+ PQUEUE_MANAGER pqm;
1037
+ VALUE exception;
1038
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
1039
+
1040
+ if(pqm->trace_level) printf("WMQ::QueueManager.connect() Backing out due to unhandled exception\n");
1041
+ //exception = rb_gvar_get("$!");
1042
+ exception = rb_eval_string("$!"); /* $! holds the current exception */
1043
+ if(pqm->trace_level > 1) printf("WMQ::QueueManager.connect() Exception $! extracted\n");
1044
+ QueueManager_backout(self); /* Backout Unit of work */
1045
+ if(pqm->trace_level > 1) printf("WMQ::QueueManager.connect() Rethrowing Exception\n");
1046
+ rb_exc_raise(exception); /* Re-Raise Exception */
1047
+ return Qnil;
1048
+ }
1049
+
1050
+ static VALUE QueueManager_singleton_connect_body(struct QueueManager_singleton_connect_arg* arg)
1051
+ {
1052
+ return rb_rescue2(QueueManager_singleton_connect_body2, (VALUE)arg,
1053
+ QueueManager_singleton_connect_rescue, arg->self,
1054
+ rb_eException, 0);
1055
+ }
1056
+
1057
+ static VALUE QueueManager_singleton_connect_ensure(VALUE self)
1058
+ {
1059
+ return QueueManager_disconnect(self);
1060
+ }
1061
+
1062
+ /*
1063
+ * call-seq:
1064
+ * connect(...)
1065
+ *
1066
+ * Connect to the queue manager, then disconnect once the supplied code block completes
1067
+ *
1068
+ * Parameters:
1069
+ * * Since the number of parameters can vary dramatically, all parameters are passed by name in a hash
1070
+ * * Summary of parameters and their WebSphere MQ equivalents:
1071
+ * WMQ::QueueManager.connect( # WebSphere MQ Equivalents:
1072
+ * :q_mgr_name => 'queue_manager name',
1073
+ * :exception_on_error => true, # n/a
1074
+ * :connect_options => WMQ::MQCNO_FASTBATH_BINDING # MQCNO.Options
1075
+ *
1076
+ * :trace_level => 0, # n/a
1077
+ *
1078
+ * # Common client connection parameters
1079
+ * :channel_name => 'svrconn channel name', # MQCD.ChannelName
1080
+ * :connection_name => 'localhost(1414)', # MQCD.ConnectionName
1081
+ * :transport_type => WMQ::MQXPT_TCP, # MQCD.TransportType
1082
+ *
1083
+ * # Advanced client connections parameters
1084
+ * :max_msg_length => 65535, # MQCD.MaxMsgLength
1085
+ * :security_exit => 'Name of security exit', # MQCD.SecurityExit
1086
+ * :send_exit => 'Name of send exit', # MQCD.SendExit
1087
+ * :receive_exit => 'Name of receive exit', # MQCD.ReceiveExit
1088
+ * :security_user_data => 'Security exit User data', # MQCD.SecurityUserData
1089
+ * :send_user_data => 'Send exit user data', # MQCD.SendUserData
1090
+ * :receive_user_data => 'Receive exit user data', # MQCD.ReceiveUserData
1091
+ * :heartbeat_interval => 1, # MQCD.HeartbeatInterval
1092
+ * :remote_security_id => 'Remote Security id', # MQCD.RemoteSecurityId
1093
+ * :ssl_cipher_spec => 'SSL Cipher Spec', # MQCD.SSLCipherSpec
1094
+ * :keep_alive_interval=> -1, # MQCD.KeepAliveInterval
1095
+ * :mode_name => 'LU6.2 Mode Name', # MQCD.ModeName
1096
+ * :tp_name => 'LU6.2 Transaction pgm name', # MQCD.TpName
1097
+ * :user_identifier => 'LU 6.2 Userid', # MQCD.UserIdentifier
1098
+ * :password => 'LU6.2 Password', # MQCD.Password
1099
+ * :long_remote_user_id=> 'Long remote user identifier', # MQCD.LongRemoteUserId (Ptr, Length)
1100
+ * :ssl_peer_name => 'SSL Peer name', # MQCD.SSLPeerName (Ptr, Length)
1101
+ *
1102
+ * # SSL Options
1103
+ * :key_repository => '/var/mqm/qmgrs/.../key', # MQSCO.KeyRepository
1104
+ * :crypto_hardware => 'GSK_ACCELERATOR_NCIPHER_NF_ON', # MQSCO.CryptoHardware
1105
+ * )
1106
+ *
1107
+ * Optional Parameters
1108
+ * * :q_mgr_name => String
1109
+ * * Name of the existing WebSphere MQ Queue Manager to connect to
1110
+ *
1111
+ * * Default:
1112
+ * - Server connections will connect to the default queue manager
1113
+ * - Client connections will connect to whatever queue
1114
+ * manager is found at the host and port number as specified
1115
+ * by the connection_name
1116
+ *
1117
+ * * :exception_on_error => true or false
1118
+ * Determines whether WMQ::WMQExceptions are thrown whenever
1119
+ * an error occurs during a WebSphere MQ operation (connect, put, get, etc..)
1120
+ *
1121
+ * Default: true
1122
+ *
1123
+ * * :connect_options => FixNum
1124
+ * * One or more of the following values:
1125
+ * WMQ::MQCNO_STANDARD_BINDING
1126
+ * WMQ::MQCNO_FASTPATH_BINDING
1127
+ * WMQ::MQCNO_SHARED_BINDING
1128
+ * WMQ::MQCNO_ISOLATED_BINDING
1129
+ * WMQ::MQCNO_ACCOUNTING_MQI_ENABLED
1130
+ * WMQ::MQCNO_ACCOUNTING_MQI_DISABLED
1131
+ * WMQ::MQCNO_ACCOUNTING_Q_ENABLED
1132
+ * WMQ::MQCNO_ACCOUNTING_Q_DISABLED
1133
+ * WMQ::MQCNO_NONE
1134
+ *
1135
+ * * Multiple values can be or'd together. E.g.
1136
+ * :connect_options=>WMQ::MQCNO_FASTPATH_BINDING | WMQ::MQCNO_ACCOUNTING_MQI_ENABLED
1137
+ *
1138
+ * * Please see the WebSphere MQ MQCNO data type documentation for more details
1139
+ * Default: WMQ::MQCNO_NONE
1140
+ *
1141
+ * * :trace_level => FixNum
1142
+ * * Turns on low-level tracing of the WebSphere MQ API calls to stdout.
1143
+ * * 0: No tracing
1144
+ * * 1: MQ API tracing only (MQCONNX, MQOPEN, MQPUT, etc..)
1145
+ * * 2: Include Ruby WMQ tracing
1146
+ * * 3: Verbose logging (Recommended for when reporting problems in Ruby WMQ)
1147
+ * Default: 0
1148
+ *
1149
+ * Common Client Connection Parameters (Client connections only)
1150
+ * * :connection_name => String (Mandatory for client connections)
1151
+ * * Connection name, made up of the host name (or ip address) and the port number
1152
+ * * E.g.
1153
+ * 'mymachine.domain.com(1414)'
1154
+ * '192.168.0.1(1417)'
1155
+ *
1156
+ * * :channel_name => String
1157
+ * * Name of SVRCONN channel defined on the QueueManager for Client Connections
1158
+ * * Default Value:
1159
+ * 'SYSTEM.DEF.SVRCONN'
1160
+ *
1161
+ * * :transport_type => WMQ::MQXPT_TCP, # MQCD.TransportType
1162
+ * * Valid Values:
1163
+ * WMQ::MQXPT_LOCAL
1164
+ * WMQ::MQXPT_LU62
1165
+ * WMQ::MQXPT_TCP
1166
+ * WMQ::MQXPT_NETBIOS
1167
+ * WMQ::MQXPT_SPX
1168
+ * WMQ::MQXPT_DECNET
1169
+ * WMQ::MQXPT_UDP
1170
+ *
1171
+ * * Default Value:
1172
+ * WMQ::MQXPT_TCP
1173
+ *
1174
+ * For the Advanced Client Connection parameters, please see the WebSphere MQ documentation
1175
+ *
1176
+ * Note:
1177
+ * * If an exception is not caught in the code block, the current unit of work is
1178
+ * automatically backed out, before disconnecting from the queue manager.
1179
+ *
1180
+ * Local Server Connection Example:
1181
+ * require 'wmq/wmq'
1182
+ *
1183
+ * WMQ::QueueManager.connect(:q_mgr_name=>'REID') do |qmgr|
1184
+ * qmgr.put(:q_name=>'TEST.QUEUE', :data => 'Hello World')
1185
+ * end
1186
+ *
1187
+ * Client Connection Example:
1188
+ * require 'wmq/wmq_client'
1189
+ *
1190
+ * WMQ::QueueManager.connect(
1191
+ * :channel_name => 'SYSTEM.DEF.SVRCONN',
1192
+ * :transport_type => WMQ::MQXPT_TCP,
1193
+ * :connection_name => 'localhost(1414)' ) do |qmgr|
1194
+ * qmgr.open_queue(:q_name=>'TEST.QUEUE', :mode=>:input) do |queue|
1195
+ *
1196
+ * message = WMQ::Message.new
1197
+ * if queue.get(:message => message)
1198
+ * puts "Data Received: #{message.data}"
1199
+ * else
1200
+ * puts 'No message available'
1201
+ * end
1202
+ * end
1203
+ * end
1204
+ */
1205
+ VALUE QueueManager_singleton_connect(int argc, VALUE *argv, VALUE self)
1206
+ {
1207
+ VALUE proc, parameters, queue_manager;
1208
+
1209
+ /* Extract parameters and code block (Proc) */
1210
+ rb_scan_args(argc, argv, "1&", &parameters, &proc);
1211
+
1212
+ queue_manager = rb_funcall(wmq_queue_manager, ID_new, 1, parameters);
1213
+ if(!NIL_P(proc))
1214
+ {
1215
+ if(Qtrue == QueueManager_connect(queue_manager))
1216
+ {
1217
+ struct QueueManager_singleton_connect_arg arg;
1218
+ arg.self = queue_manager;
1219
+ arg.proc = proc;
1220
+ rb_ensure(QueueManager_singleton_connect_body, (VALUE)&arg,
1221
+ QueueManager_singleton_connect_ensure, queue_manager);
1222
+ }
1223
+ else
1224
+ {
1225
+ return Qfalse;
1226
+ }
1227
+ }
1228
+ return queue_manager;
1229
+ }
1230
+
1231
+ /* What can I say, Ruby blocks have spoilt me :) */
1232
+ #define CHECK_COMPLETION_CODE(ACTION) \
1233
+ if(pqm->trace_level > 1) \
1234
+ printf ("WMQ::QueueManager#execute() %s:%s\n", ACTION, wmq_reason(pqm->reason_code)); \
1235
+ if(pqm->comp_code != MQCC_OK) \
1236
+ { \
1237
+ if (pqm->exception_on_error) \
1238
+ { \
1239
+ if(pqm->trace_level) \
1240
+ printf ("WMQ::QueueManager#execute() raise WMQ::WMQException\n"); \
1241
+ \
1242
+ rb_raise(wmq_exception, \
1243
+ "WMQ::QueueManager#execute(). Failed:%s, reason:%s", \
1244
+ ACTION, \
1245
+ wmq_reason(pqm->reason_code)); \
1246
+ } \
1247
+ return Qfalse; \
1248
+ }
1249
+
1250
+ static int QueueManager_execute_each (VALUE key, VALUE value, PQUEUE_MANAGER pqm)
1251
+ {
1252
+ MQLONG selector_type, selector;
1253
+ VALUE str;
1254
+ ID selector_id = rb_to_id(key);
1255
+
1256
+ if(pqm->trace_level > 1)
1257
+ {
1258
+ str = rb_funcall(key, rb_intern("to_s"), 0);
1259
+ printf ("WMQ::QueueManager#execute_each Key:%s\n", RSTRING_PTR(str));
1260
+ }
1261
+
1262
+ if (ID_command == selector_id) // Skip :command
1263
+ {
1264
+ return 0;
1265
+ }
1266
+
1267
+ wmq_selector(selector_id, &selector_type, &selector);
1268
+ if(NIL_P(value))
1269
+ {
1270
+ pqm->mqAddInquiry(pqm->admin_bag, selector, &pqm->comp_code, &pqm->reason_code);
1271
+ CHECK_COMPLETION_CODE("Adding Inquiry to the admin bag")
1272
+ return 0;
1273
+ }
1274
+
1275
+ switch (selector_type)
1276
+ {
1277
+ case MQIT_INTEGER:
1278
+ if(TYPE(value) == T_SYMBOL) /* Translate symbol to MQ selector value */
1279
+ {
1280
+ MQLONG val_selector, val_selector_type;
1281
+ wmq_selector(rb_to_id(value), &val_selector_type, &val_selector);
1282
+
1283
+ pqm->mqAddInteger(pqm->admin_bag, selector, val_selector, &pqm->comp_code, &pqm->reason_code);
1284
+ }
1285
+ else
1286
+ {
1287
+ pqm->mqAddInteger(pqm->admin_bag, selector, NUM2LONG(value), &pqm->comp_code, &pqm->reason_code);
1288
+ }
1289
+ CHECK_COMPLETION_CODE("Adding Queue Type to the admin bag")
1290
+ break;
1291
+
1292
+ case MQIT_STRING:
1293
+ str = StringValue(value);
1294
+ pqm->mqAddString(pqm->admin_bag, selector, MQBL_NULL_TERMINATED, RSTRING_PTR(str), &pqm->comp_code, &pqm->reason_code);
1295
+ CHECK_COMPLETION_CODE("Adding Queue name to the admin bag")
1296
+ break;
1297
+
1298
+ default:
1299
+ rb_raise(rb_eArgError, "WMQ::QueueManager#execute_each Unknown selector type returned by wmq_selector()");
1300
+ break;
1301
+ }
1302
+ return 0;
1303
+ }
1304
+
1305
+ /*
1306
+ * call-seq:
1307
+ * execute(...)
1308
+ *
1309
+ * Execute an Administration command against the local queue manager
1310
+ *
1311
+ * Parameters:
1312
+ * * Since the number of parameters can vary dramatically, all parameters are passed by name in a hash
1313
+ * * The entire MQ Administration interface has been implemented.
1314
+ * Rather than re-documentation the hundreds of options, a standard
1315
+ * convention has been used to map the MQ constants to Symbols in Ruby.
1316
+ *
1317
+ * For all MQ Admin commands, just drop the MQAI_ off the front and
1318
+ * convert the command name to lower case.
1319
+ * * E.g. MQAI_INQUIRE_Q becomes inquire_q
1320
+ *
1321
+ * For the hundreds of parameters, a similiar technique is followed.
1322
+ * Remove the prefixes: MQCA_, MQIA_, etc.. and convert to lowercase
1323
+ * * E.g. MQCA_Q_NAME becomes :q_name
1324
+ *
1325
+ * Example
1326
+ * WMQ::QueueManager.connect do |qmgr|
1327
+ * result = qmgr.execute(
1328
+ * :command => :inquire_q,
1329
+ * :q_name => 'MY.LOCAL.QUEUE',
1330
+ * :q_type => WMQ::MQQT_LOCAL,
1331
+ * :current_q_depth => nil
1332
+ * )
1333
+ * # OR, we can replace the method name execute with the MQAI command:
1334
+ * result = qmgr.inquire_q(
1335
+ * :q_name => 'MY.LOCAL.QUEUE',
1336
+ * :q_type => WMQ::MQQT_LOCAL,
1337
+ * :current_q_depth => nil
1338
+ * )
1339
+ *
1340
+ * Complete Example:
1341
+ * require 'wmq/wmq'
1342
+ * require 'wmq/wmq_const_admin'
1343
+ * WMQ::QueueManager.connect(:q_mgr_name=>'REID', :connection_name=>'localhost(1414)') do |qmgr|
1344
+ * qmgr.reset_q_stats(:q_name=>'*').each {|item| p item }
1345
+ * end
1346
+ *
1347
+ * Some one line examples
1348
+ * qmgr.inquire_q(:q_name=>'TEST*').each {|item| p item }
1349
+ *
1350
+ * qmgr.inquire_q(:q_name=>'TEST*', :q_type=>WMQ::MQQT_LOCAL, :current_q_depth=>nil).each {|item| p item }
1351
+ *
1352
+ * qmgr.inquire_process(:process_name=>'*').each {|item| p item }
1353
+ *
1354
+ * qmgr.ping_q_mgr.each {|item| p item }
1355
+ *
1356
+ * qmgr.refresh_security.each {|item| p item }
1357
+ *
1358
+ * qmgr.inquire_q_status(:q_name=>'TEST*', :q_status_type=>:q_status, :q_status_attrs=>:process_id).each {|item| p item }
1359
+ *
1360
+ * qmgr.start_channel_listener.each {|item| p item }
1361
+ *
1362
+ * qmgr.inquire_channel_status(:channel_name=>'*').each {|item| p item }
1363
+ */
1364
+ VALUE QueueManager_execute(VALUE self, VALUE hash)
1365
+ {
1366
+ #ifdef MQHB_UNUSABLE_HBAG
1367
+ VALUE val;
1368
+ PQUEUE_MANAGER pqm;
1369
+ Data_Get_Struct(self, QUEUE_MANAGER, pqm);
1370
+
1371
+ Check_Type(hash, T_HASH);
1372
+
1373
+ if (pqm->admin_bag == MQHB_UNUSABLE_HBAG) /* Lazy create admin bag */
1374
+ {
1375
+ pqm->mqCreateBag(MQCBO_ADMIN_BAG, &pqm->admin_bag, &pqm->comp_code, &pqm->reason_code);
1376
+ CHECK_COMPLETION_CODE("Creating the admin bag")
1377
+ }
1378
+ else
1379
+ {
1380
+ pqm->mqClearBag(pqm->admin_bag, &pqm->comp_code, &pqm->reason_code);
1381
+ CHECK_COMPLETION_CODE("Clearing the admin bag")
1382
+ }
1383
+
1384
+ if (pqm->reply_bag == MQHB_UNUSABLE_HBAG) /* Lazy create reply bag */
1385
+ {
1386
+ pqm->mqCreateBag(MQCBO_ADMIN_BAG, &pqm->reply_bag, &pqm->comp_code, &pqm->reason_code);
1387
+ CHECK_COMPLETION_CODE("Creating the reply bag")
1388
+ }
1389
+ else
1390
+ {
1391
+ pqm->mqClearBag(pqm->reply_bag, &pqm->comp_code, &pqm->reason_code);
1392
+ CHECK_COMPLETION_CODE("Clearing the reply bag")
1393
+ }
1394
+
1395
+ val = rb_hash_aref(hash, ID2SYM(ID_command)); /* :command */
1396
+ if (NIL_P(val))
1397
+ {
1398
+ rb_raise(rb_eArgError, "WMQ::QueueManager#execute Mandatory parameter :command missing");
1399
+ }
1400
+ rb_hash_foreach(hash, QueueManager_execute_each, (VALUE)pqm);
1401
+ if(pqm->trace_level) printf ("WMQ::QueueManager#execute() Queue Manager Handle:%ld\n", (long)pqm->hcon);
1402
+
1403
+ pqm->mqExecute(
1404
+ pqm->hcon, /* MQ connection handle */
1405
+ wmq_command_lookup(rb_to_id(val)), /* Command to be executed */
1406
+ MQHB_NONE, /* No options bag */
1407
+ pqm->admin_bag, /* Handle to bag containing commands */
1408
+ pqm->reply_bag, /* Handle to bag to receive the response*/
1409
+ MQHO_NONE, /* Put msg on SYSTEM.ADMIN.COMMAND.QUEUE*/
1410
+ MQHO_NONE, /* Create a dynamic q for the response */
1411
+ &pqm->comp_code, /* Completion code from the mqexecute */
1412
+ &pqm->reason_code); /* Reason code from mqexecute call */
1413
+
1414
+ if(pqm->trace_level) printf("WMQ::QueueManager#execute() completed with reason:%s\n", wmq_reason(pqm->reason_code));
1415
+
1416
+ if (pqm->comp_code == MQCC_OK)
1417
+ {
1418
+ MQLONG numberOfBags; /* number of bags in response bag */
1419
+ MQHBAG qAttrsBag; /* bag containing q attributes */
1420
+ VALUE array;
1421
+ MQLONG size;
1422
+ MQLONG length;
1423
+ MQCHAR inquiry_buffer[WMQ_EXEC_STRING_INQ_BUFFER_SIZE];
1424
+ PMQCHAR pChar;
1425
+
1426
+ MQLONG qDepth; /* depth of queue */
1427
+ MQLONG item_type;
1428
+ MQLONG selector;
1429
+ MQLONG number_of_items;
1430
+ int bag_index, items, k;
1431
+
1432
+ pqm->mqCountItems(pqm->reply_bag, MQHA_BAG_HANDLE, &numberOfBags, &pqm->comp_code, &pqm->reason_code);
1433
+ CHECK_COMPLETION_CODE("Counting number of bags returned from the command server")
1434
+
1435
+ if(pqm->trace_level > 1) printf("WMQ::QueueManager#execute() %ld bags returned\n", (long)numberOfBags);
1436
+ array = rb_ary_new2(numberOfBags);
1437
+
1438
+ for ( bag_index=0; bag_index<numberOfBags; bag_index++) /* For each bag, extract the queue depth */
1439
+ {
1440
+ hash = rb_hash_new();
1441
+
1442
+ pqm->mqInquireBag(pqm->reply_bag, MQHA_BAG_HANDLE, bag_index, &qAttrsBag, &pqm->comp_code, &pqm->reason_code);
1443
+ CHECK_COMPLETION_CODE("Inquiring for the attribute bag handle")
1444
+
1445
+ pqm->mqCountItems(qAttrsBag, MQSEL_ALL_SELECTORS, &number_of_items, &pqm->comp_code, &pqm->reason_code);
1446
+ CHECK_COMPLETION_CODE("Counting number of items in this bag")
1447
+
1448
+ if(pqm->trace_level > 1) printf("WMQ::QueueManager#execute() Bag %d contains %ld items\n", bag_index, (long)number_of_items);
1449
+
1450
+ for (items=0; items<number_of_items; items++) /* For each item, extract it's value */
1451
+ {
1452
+ pqm->mqInquireItemInfo(
1453
+ qAttrsBag, /* I: Bag handle */
1454
+ MQSEL_ANY_SELECTOR, /* I: Item selector */
1455
+ items, /* I: Item index */
1456
+ &selector, /* O: Selector of item */
1457
+ &item_type, /* O: Data type of item */
1458
+ &pqm->comp_code,
1459
+ &pqm->reason_code);
1460
+ CHECK_COMPLETION_CODE("Inquiring Item details")
1461
+
1462
+ if (selector > 0) /* Skip system selectors */
1463
+ {
1464
+ switch (item_type)
1465
+ {
1466
+ case MQIT_INTEGER:
1467
+ pqm->mqInquireInteger(qAttrsBag, MQSEL_ALL_SELECTORS, items, &qDepth, &pqm->comp_code, &pqm->reason_code);
1468
+ CHECK_COMPLETION_CODE("Inquiring Integer item")
1469
+
1470
+ if(pqm->trace_level > 1)
1471
+ printf("WMQ::QueueManager#execute() Item %d: Integer:%ld, selector:%ld\n", items, (long)qDepth, (long)selector);
1472
+
1473
+ rb_hash_aset(hash, ID2SYM(wmq_selector_id(selector)), LONG2NUM(qDepth));
1474
+ break;
1475
+
1476
+ case MQIT_STRING:
1477
+ pqm->mqInquireString(qAttrsBag, MQSEL_ALL_SELECTORS, items, WMQ_EXEC_STRING_INQ_BUFFER_SIZE-1, inquiry_buffer,
1478
+ &size, NULL, &pqm->comp_code, &pqm->reason_code);
1479
+ if(pqm->trace_level > 2)
1480
+ printf("WMQ::QueueManager#execute() mqInquireString buffer size: %d, string size:%ld\n",
1481
+ WMQ_EXEC_STRING_INQ_BUFFER_SIZE,(long)size);
1482
+ CHECK_COMPLETION_CODE("Inquiring String item")
1483
+
1484
+ length = 0;
1485
+ pChar = inquiry_buffer + size-1;
1486
+ for (k = size; k > 0; k--)
1487
+ {
1488
+ if (*pChar != ' ' && *pChar != 0)
1489
+ {
1490
+ length = k;
1491
+ break;
1492
+ }
1493
+ pChar--;
1494
+ }
1495
+ rb_hash_aset(hash, ID2SYM(wmq_selector_id(selector)), rb_str_new(inquiry_buffer, length));
1496
+
1497
+ if(pqm->trace_level > 1)
1498
+ {
1499
+ inquiry_buffer[length] = '\0';
1500
+ printf("WMQ::QueueManager#execute() Item %d: String:'%s', selector:%ld\n",
1501
+ items, inquiry_buffer, (long)selector);
1502
+ }
1503
+ break;
1504
+
1505
+ case MQIT_BAG:
1506
+ printf("Ignoring Bag at this level\n");
1507
+ break;
1508
+
1509
+ default:
1510
+ printf("Ignoring Unknown type:%ld\n", (long)item_type);
1511
+ break;
1512
+ }
1513
+ }
1514
+ }
1515
+ rb_ary_push(array, hash);
1516
+ }
1517
+ return array;
1518
+ }
1519
+ else
1520
+ {
1521
+ VALUE name = rb_iv_get(self,"@name");
1522
+ name = StringValue(name);
1523
+
1524
+ if (pqm->reason_code == MQRCCF_COMMAND_FAILED)
1525
+ {
1526
+ /* Find out why admin command failed */
1527
+ MQLONG result_comp_code, result_reason_code;
1528
+ MQHBAG result_bag;
1529
+
1530
+ pqm->mqInquireBag(pqm->reply_bag, MQHA_BAG_HANDLE, 0, &result_bag, &pqm->comp_code, &pqm->reason_code);
1531
+ CHECK_COMPLETION_CODE("Getting the result bag handle")
1532
+
1533
+ pqm->mqInquireInteger(result_bag, MQIASY_COMP_CODE, MQIND_NONE, &result_comp_code, &pqm->comp_code, &pqm->reason_code);
1534
+ CHECK_COMPLETION_CODE("Getting the completion code from the result bag")
1535
+
1536
+ pqm->mqInquireInteger(result_bag, MQIASY_REASON, MQIND_NONE, &result_reason_code, &pqm->comp_code, &pqm->reason_code);
1537
+ CHECK_COMPLETION_CODE("Getting the reason code from the result bag")
1538
+
1539
+ pqm->comp_code = result_comp_code;
1540
+ pqm->reason_code = result_reason_code;
1541
+
1542
+ if(pqm->trace_level)
1543
+ printf("WMQ::QueueManager#execute() Error returned by command server:%s\n", wmq_reason(pqm->reason_code));
1544
+ }
1545
+
1546
+ if (pqm->exception_on_error)
1547
+ {
1548
+ if (pqm->reason_code == MQRC_CMD_SERVER_NOT_AVAILABLE)
1549
+ {
1550
+ rb_raise(wmq_exception,
1551
+ "WMQ::QueueManager#execute(). Please start the WebSphere MQ Command Server : 'strmqcsv %s', reason:%s",
1552
+ RSTRING_PTR(name),
1553
+ wmq_reason(pqm->reason_code));
1554
+ }
1555
+ else
1556
+ {
1557
+ rb_raise(wmq_exception,
1558
+ "WMQ::QueueManager#execute(). Error executing admin command on Queue Manager:%s, reason:%s",
1559
+ RSTRING_PTR(name),
1560
+ wmq_reason(pqm->reason_code));
1561
+ }
1562
+ }
1563
+ return Qfalse;
1564
+ }
1565
+ return Qnil;
1566
+ #else
1567
+ rb_notimplement();
1568
+ return Qfalse;
1569
+ #endif
1570
+ }