ferocia-rubywmq 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.document +8 -0
  2. data/LICENSE +13 -0
  3. data/Manifest.txt +20 -0
  4. data/README +73 -0
  5. data/examples/each_a.rb +32 -0
  6. data/examples/each_b.rb +41 -0
  7. data/examples/each_header.rb +38 -0
  8. data/examples/files_to_q.cfg +24 -0
  9. data/examples/files_to_q.rb +47 -0
  10. data/examples/get_a.rb +35 -0
  11. data/examples/get_client.rb +51 -0
  12. data/examples/put1_a.rb +25 -0
  13. data/examples/put1_b.rb +33 -0
  14. data/examples/put1_c.rb +32 -0
  15. data/examples/put_a.rb +35 -0
  16. data/examples/put_b.rb +43 -0
  17. data/examples/put_dlh.rb +41 -0
  18. data/examples/put_dynamic_q.rb +38 -0
  19. data/examples/put_group_a.rb +51 -0
  20. data/examples/put_group_b.rb +53 -0
  21. data/examples/put_rfh.rb +67 -0
  22. data/examples/put_rfh2_a.rb +43 -0
  23. data/examples/put_rfh2_b.rb +43 -0
  24. data/examples/put_xmit_q.rb +33 -0
  25. data/examples/q_to_files.cfg +17 -0
  26. data/examples/q_to_files.rb +48 -0
  27. data/examples/request.rb +60 -0
  28. data/examples/server.rb +97 -0
  29. data/ext/build.bat +3 -0
  30. data/ext/build.sh +6 -0
  31. data/ext/decode_rfh.c +348 -0
  32. data/ext/decode_rfh.h +45 -0
  33. data/ext/extconf.rb +44 -0
  34. data/ext/extconf_client.rb +40 -0
  35. data/ext/generate/generate_const.rb +167 -0
  36. data/ext/generate/generate_reason.rb +246 -0
  37. data/ext/generate/generate_structs.rb +97 -0
  38. data/ext/generate/wmq_structs.erb +371 -0
  39. data/ext/lib/wmq_temp.rb +197 -0
  40. data/ext/wmq.c +93 -0
  41. data/ext/wmq.h +367 -0
  42. data/ext/wmq_message.c +671 -0
  43. data/ext/wmq_mq_load.c +217 -0
  44. data/ext/wmq_queue.c +1411 -0
  45. data/ext/wmq_queue_manager.c +1587 -0
  46. data/lib/wmq.rb +25 -0
  47. data/rubywmq.binary.gemspec +32 -0
  48. data/rubywmq.gemspec +33 -0
  49. data/tests/test.rb +328 -0
  50. metadata +124 -0
@@ -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
+ }