ferocia-rubywmq 1.1.0

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