rubywmq 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }