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