rubywmq 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,213 @@
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
+ #if defined _WIN32 && !defined __CYGWIN__
20
+ /*
21
+ * WINDOWS 32 BIT
22
+ */
23
+
24
+ #define MQ_LOAD(LIBRARY) \
25
+ HINSTANCE handle = LoadLibrary(LIBRARY); \
26
+ if (!handle) \
27
+ { \
28
+ rb_raise(wmq_exception, \
29
+ "WMQ::QueueManager#connect(). Failed to load MQ Library:%s, rc=%ld", \
30
+ LIBRARY, \
31
+ GetLastError()); \
32
+ }
33
+
34
+ #define MQ_RELEASE FreeLibrary((HINSTANCE)pqm->mq_lib_handle);
35
+
36
+ #define MQ_FUNCTION(FUNC, CAST) \
37
+ pqm->FUNC = (CAST)GetProcAddress(handle, #FUNC); \
38
+ if (!pqm->FUNC) \
39
+ { \
40
+ rb_raise(wmq_exception, "Failed to find API "#FUNC" in MQ Library"); \
41
+ }
42
+
43
+ #define MQ_LIBRARY_SERVER "mqm"
44
+ #define MQ_LIBRARY_CLIENT "mqic32"
45
+ #elif defined(SOLARIS) || defined(__SVR4) || defined(__linux__) || defined(LINUX)
46
+ /*
47
+ * SOLARIS, LINUX
48
+ */
49
+
50
+ #ifndef RTLD_LAZY
51
+ #define RTLD_LAZY 1
52
+ #endif
53
+ #ifndef RTLD_GLOBAL
54
+ #define RTLD_GLOBAL 0
55
+ #endif
56
+
57
+ #define MQ_LOAD(LIBRARY) \
58
+ void* handle = (void*)dlopen(LIBRARY, RTLD_LAZY|RTLD_GLOBAL); \
59
+ if (!handle) \
60
+ { \
61
+ rb_raise(wmq_exception, \
62
+ "WMQ::QueueManager#connect(). Failed to load MQ Library:%s, rc=%s", \
63
+ LIBRARY, \
64
+ dlerror()); \
65
+ }
66
+
67
+ #define MQ_RELEASE dlclose(pqm->mq_lib_handle);
68
+
69
+ #define MQ_FUNCTION(FUNC, CAST) \
70
+ pqm->FUNC = (CAST)dlsym(handle, #FUNC); \
71
+ if (!pqm->FUNC) \
72
+ { \
73
+ rb_raise(wmq_exception, "Failed to find API "#FUNC" in MQ Library"); \
74
+ }
75
+
76
+ #if defined(SOLARIS) || defined(__SVR4)
77
+ #define MQ_LIBRARY_SERVER "libmqm.so"
78
+ #define MQ_LIBRARY_CLIENT "libmqic.so"
79
+ #else
80
+ #define MQ_LIBRARY_SERVER "libmqm_r.so"
81
+ #define MQ_LIBRARY_CLIENT "libmqic_r.so"
82
+ #endif
83
+ #elif defined(__hpux)
84
+ /*
85
+ * HP-UX
86
+ */
87
+
88
+ #define MQ_LOAD(LIBRARY) \
89
+ shl_t handle = shl_load(file, BIND_DEFERRED, 0); \
90
+ if (!handle) \
91
+ { \
92
+ rb_raise(wmq_exception, \
93
+ "WMQ::QueueManager#connect(). Failed to load MQ Library:%s, rc=%s", \
94
+ LIBRARY, \
95
+ strerror(errno)); \
96
+ }
97
+
98
+ #define MQ_RELEASE shl_unload((shl_t)pqm->mq_lib_handle);
99
+
100
+ #define MQ_FUNCTION(FUNC, CAST) \
101
+ pqm->FUNC = NULL; \
102
+ shl_findsym(&handle,FUNC,TYPE_PROCEDURE,(void*)&(pqm->FUNC)); \
103
+ if(pqm->FUNC == NULL) \
104
+ { \
105
+ shl_findsym(&handle,FUNC,TYPE_UNDEFINED,(void*)&(pqm->FUNC)); \
106
+ if(pqm->FUNC == NULL) \
107
+ { \
108
+ rb_raise(wmq_exception, "Failed to find API "#FUNC" in MQ Library"); \
109
+ } \
110
+ }
111
+
112
+ #define MQ_LIBRARY_SERVER "libmqm_r.sl"
113
+ #define MQ_LIBRARY_CLIENT "libmqic_r.sl"
114
+ #endif
115
+
116
+ void Queue_manager_mq_load(PQUEUE_MANAGER pqm)
117
+ {
118
+ #if defined MQ_FUNCTION
119
+ PMQCHAR library;
120
+ if(pqm->is_client_conn)
121
+ {
122
+ library = MQ_LIBRARY_CLIENT;
123
+ if(pqm->trace_level) printf("WMQ::QueueManager#connect() Loading MQ Client Library:%s\n", library);
124
+ }
125
+ else
126
+ {
127
+ library = MQ_LIBRARY_SERVER;
128
+ if(pqm->trace_level) printf("WMQ::QueueManager#connect() Loading MQ Server Library:%s\n", library);
129
+ }
130
+
131
+ {
132
+ MQ_LOAD(library)
133
+
134
+ if(pqm->trace_level>1) printf("WMQ::QueueManager#connect() MQ Library:%s Loaded successfully\n", library);
135
+
136
+ MQ_FUNCTION(MQCONNX,void(*)(PMQCHAR,PMQCNO,PMQHCONN,PMQLONG,PMQLONG))
137
+ MQ_FUNCTION(MQCONN, void(*)(PMQCHAR,PMQHCONN,PMQLONG,PMQLONG))
138
+ MQ_FUNCTION(MQDISC,void(*) (PMQHCONN,PMQLONG,PMQLONG))
139
+ MQ_FUNCTION(MQBEGIN,void(*)(MQHCONN,PMQVOID,PMQLONG,PMQLONG))
140
+ MQ_FUNCTION(MQBACK,void(*) (MQHCONN,PMQLONG,PMQLONG))
141
+ MQ_FUNCTION(MQCMIT,void(*) (MQHCONN,PMQLONG,PMQLONG))
142
+ MQ_FUNCTION(MQPUT1,void(*) (MQHCONN,PMQVOID,PMQVOID,PMQVOID,MQLONG,PMQVOID,PMQLONG,PMQLONG))
143
+
144
+ MQ_FUNCTION(MQOPEN,void(*) (MQHCONN,PMQVOID,MQLONG,PMQHOBJ,PMQLONG,PMQLONG))
145
+ MQ_FUNCTION(MQCLOSE,void(*)(MQHCONN,PMQHOBJ,MQLONG,PMQLONG,PMQLONG))
146
+ MQ_FUNCTION(MQGET,void(*) (MQHCONN,MQHOBJ,PMQVOID,PMQVOID,MQLONG,PMQVOID,PMQLONG,PMQLONG,PMQLONG))
147
+ MQ_FUNCTION(MQPUT,void(*) (MQHCONN,MQHOBJ,PMQVOID,PMQVOID,MQLONG,PMQVOID,PMQLONG,PMQLONG))
148
+
149
+ MQ_FUNCTION(MQINQ,void(*) (MQHCONN,MQHOBJ,MQLONG,PMQLONG,MQLONG,PMQLONG,MQLONG,PMQCHAR,PMQLONG,PMQLONG))
150
+ MQ_FUNCTION(MQSET,void(*) (MQHCONN,MQHOBJ,MQLONG,PMQLONG,MQLONG,PMQLONG,MQLONG,PMQCHAR,PMQLONG,PMQLONG))
151
+
152
+ MQ_FUNCTION(mqCreateBag,void(*)(MQLONG,PMQHBAG,PMQLONG,PMQLONG))
153
+ MQ_FUNCTION(mqDeleteBag,void(*)(PMQHBAG,PMQLONG,PMQLONG))
154
+ MQ_FUNCTION(mqClearBag,void(*)(MQHBAG,PMQLONG,PMQLONG))
155
+ MQ_FUNCTION(mqExecute,void(*)(MQHCONN,MQLONG,MQHBAG,MQHBAG,MQHBAG,MQHOBJ,MQHOBJ,PMQLONG,PMQLONG))
156
+ MQ_FUNCTION(mqCountItems,void(*)(MQHBAG,MQLONG,PMQLONG,PMQLONG,PMQLONG))
157
+ MQ_FUNCTION(mqInquireBag,void(*)(MQHBAG,MQLONG,MQLONG,PMQHBAG,PMQLONG,PMQLONG))
158
+ MQ_FUNCTION(mqInquireItemInfo,void(*)(MQHBAG,MQLONG,MQLONG,PMQLONG,PMQLONG,PMQLONG,PMQLONG))
159
+ MQ_FUNCTION(mqInquireInteger,void(*)(MQHBAG,MQLONG,MQLONG,PMQLONG,PMQLONG,PMQLONG))
160
+ MQ_FUNCTION(mqInquireString,void(*)(MQHBAG,MQLONG,MQLONG,MQLONG,PMQCHAR,PMQLONG,PMQLONG,PMQLONG,PMQLONG))
161
+ MQ_FUNCTION(mqAddInquiry,void(*)(MQHBAG,MQLONG,PMQLONG,PMQLONG))
162
+ MQ_FUNCTION(mqAddInteger,void(*)(MQHBAG,MQLONG,MQLONG,PMQLONG,PMQLONG))
163
+ MQ_FUNCTION(mqAddString,void(*)(MQHBAG,MQLONG,MQLONG,PMQCHAR,PMQLONG,PMQLONG))
164
+
165
+ pqm->mq_lib_handle = (void*)handle;
166
+
167
+ if(pqm->trace_level>1) printf("WMQ::QueueManager#connect() MQ API's loaded successfully\n");
168
+ }
169
+ #else
170
+ /*
171
+ * For all the other platforms were we have to have two versions of Ruby WMQ
172
+ * 1: Linked with MQ Server Library
173
+ * 2: Linked with MQ Client Library
174
+ *
175
+ * As a result to use the client library:
176
+ * require 'wmq/wmq_client'
177
+ */
178
+ pqm->MQCONNX = &MQCONNX;
179
+ pqm->MQCONN = &MQCONN;
180
+ pqm->MQDISC = &MQDISC;
181
+ pqm->MQBEGIN = &MQBEGIN;
182
+ pqm->MQBACK = &MQBACK;
183
+ pqm->MQCMIT = &MQCMIT;
184
+ pqm->MQPUT1 = &MQPUT1;
185
+
186
+ pqm->MQOPEN = &MQOPEN;
187
+ pqm->MQCLOSE = &MQCLOSE;
188
+ pqm->MQGET = &MQGET;
189
+ pqm->MQPUT = &MQPUT;
190
+
191
+ pqm->MQINQ = &MQINQ;
192
+ pqm->MQSET = &MQSET;
193
+
194
+ pqm->mqCreateBag = &mqCreateBag;
195
+ pqm->mqClearBag = &mqClearBag;
196
+ pqm->mqExecute = &mqExecute;
197
+ pqm->mqCountItems = &mqCountItems;
198
+ pqm->mqInquireBag = &mqInquireBag;
199
+ pqm->mqInquireItemInfo= &mqInquireItemInfo;
200
+ pqm->mqInquireInteger = &mqInquireInteger;
201
+ pqm->mqInquireString = &mqInquireString;
202
+ #endif
203
+ }
204
+
205
+ void Queue_manager_mq_free(PQUEUE_MANAGER pqm)
206
+ {
207
+ if(pqm->mq_lib_handle)
208
+ {
209
+ if(pqm->trace_level>1) printf("WMQ::QueueManager#gc() Releasing MQ Library\n");
210
+ MQ_RELEASE
211
+ pqm->mq_lib_handle = 0;
212
+ }
213
+ }
@@ -0,0 +1,1410 @@
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
+ * Initialize Ruby ID's for Queue Class
20
+ *
21
+ * This function is called when the library is loaded
22
+ * by ruby
23
+ * --------------------------------------------------*/
24
+ static ID ID_new;
25
+ static ID ID_call;
26
+ static ID ID_close;
27
+ static ID ID_input;
28
+ static ID ID_input_shared;
29
+ static ID ID_input_exclusive;
30
+ static ID ID_output;
31
+ static ID ID_browse;
32
+ static ID ID_sync;
33
+ static ID ID_new_id;
34
+ static ID ID_new_msg_id;
35
+ static ID ID_new_correl_id;
36
+ static ID ID_convert;
37
+ static ID ID_wait;
38
+ static ID ID_q_name;
39
+ static ID ID_q_mgr_name;
40
+ static ID ID_match;
41
+ static ID ID_options;
42
+ static ID ID_open_options;
43
+ static ID ID_mode;
44
+ static ID ID_fail_if_quiescing;
45
+ static ID ID_queue_manager;
46
+ static ID ID_dynamic_q_name;
47
+ static ID ID_close_options;
48
+ static ID ID_fail_if_exists;
49
+ static ID ID_alternate_user_id;
50
+ static ID ID_alternate_security_id;
51
+ static ID ID_message;
52
+ static ID ID_descriptor;
53
+
54
+ void Queue_id_init()
55
+ {
56
+ ID_new = rb_intern("new");
57
+ ID_call = rb_intern("call");
58
+ ID_close = rb_intern("close");
59
+
60
+ ID_input = rb_intern("input");
61
+ ID_input_shared = rb_intern("input_shared");
62
+ ID_input_exclusive = rb_intern("input_exclusive");
63
+ ID_output = rb_intern("output");
64
+ ID_browse = rb_intern("browse");
65
+ ID_q_name = rb_intern("q_name");
66
+ ID_q_mgr_name = rb_intern("q_mgr_name");
67
+ ID_queue_manager = rb_intern("queue_manager");
68
+
69
+ ID_sync = rb_intern("sync");
70
+ ID_new_id = rb_intern("new_id");
71
+ ID_new_msg_id = rb_intern("new_msg_id");
72
+ ID_new_correl_id = rb_intern("new_correl_id");
73
+ ID_convert = rb_intern("convert");
74
+ ID_wait = rb_intern("wait");
75
+ ID_match = rb_intern("match");
76
+ ID_options = rb_intern("options");
77
+ ID_open_options = rb_intern("open_options");
78
+ ID_mode = rb_intern("mode");
79
+
80
+ ID_message = rb_intern("message");
81
+ ID_descriptor = rb_intern("descriptor");
82
+
83
+ ID_fail_if_quiescing = rb_intern("fail_if_quiescing");
84
+ ID_dynamic_q_name = rb_intern("dynamic_q_name");
85
+ ID_close_options = rb_intern("close_options");
86
+ ID_fail_if_exists = rb_intern("fail_if_exists");
87
+ ID_alternate_security_id = rb_intern("alternate_security_id");
88
+ ID_alternate_user_id = rb_intern("alternate_user_id");
89
+ }
90
+
91
+ typedef struct tagQUEUE QUEUE;
92
+ typedef QUEUE MQPOINTER PQUEUE;
93
+
94
+ struct tagQUEUE {
95
+ MQHOBJ hobj; /* object handle */
96
+ MQHCONN hcon; /* connection handle */
97
+ MQOD od; /* Object Descriptor */
98
+ MQLONG comp_code; /* completion code */
99
+ MQLONG reason_code; /* reason code for MQCONN */
100
+ MQLONG open_options; /* MQOPEN options */
101
+ MQLONG close_options; /* MQCLOSE options */
102
+ MQLONG exception_on_error; /* Non-Zero means throw exception*/
103
+ MQLONG fail_if_exists; /* Non-Zero means open dynamic_q_name directly */
104
+ MQLONG trace_level; /* Trace level. 0==None, 1==Info 2==Debug ..*/
105
+ MQCHAR q_name[MQ_Q_NAME_LENGTH+1]; /* queue name plus null character */
106
+ PMQBYTE p_buffer; /* message buffer */
107
+ MQLONG buffer_size; /* Allocated size of buffer */
108
+
109
+ void(*MQCLOSE)(MQHCONN,PMQHOBJ,MQLONG,PMQLONG,PMQLONG);
110
+ void(*MQGET) (MQHCONN,MQHOBJ,PMQVOID,PMQVOID,MQLONG,PMQVOID,PMQLONG,PMQLONG,PMQLONG);
111
+ void(*MQPUT) (MQHCONN,MQHOBJ,PMQVOID,PMQVOID,MQLONG,PMQVOID,PMQLONG,PMQLONG);
112
+ };
113
+
114
+ /* --------------------------------------------------
115
+ * C Structure to store MQ data types and other
116
+ * C internal values
117
+ * --------------------------------------------------*/
118
+ void QUEUE_free(void* p)
119
+ {
120
+ PQUEUE pq = (PQUEUE)p;
121
+ if(pq->trace_level) printf("WMQ::Queue Freeing QUEUE structure\n");
122
+
123
+ if (pq->hobj) /* Valid Q handle means MQCLOSE was not called */
124
+ {
125
+ printf("WMQ::Queue#close was not called. Automatically calling close()\n");
126
+ pq->MQCLOSE(pq->hcon, &pq->hobj, pq->close_options, &pq->comp_code, &pq->reason_code);
127
+ }
128
+ free(pq->p_buffer);
129
+ free(p);
130
+ }
131
+
132
+ VALUE QUEUE_alloc(VALUE klass)
133
+ {
134
+ static MQOD default_MQOD = {MQOD_DEFAULT};
135
+ PQUEUE pq = ALLOC(QUEUE);
136
+
137
+ pq->hobj = 0;
138
+ pq->hcon = 0;
139
+ memcpy(&pq->od, &default_MQOD, sizeof(MQOD));
140
+ pq->comp_code = 0;
141
+ pq->reason_code = 0;
142
+ pq->open_options = 0;
143
+ pq->close_options = MQCO_NONE;
144
+ pq->exception_on_error = 1;
145
+ pq->trace_level = 0;
146
+ pq->fail_if_exists = 1;
147
+ memset(&pq->q_name, 0, sizeof(pq->q_name));
148
+ pq->buffer_size = 16384;
149
+ pq->p_buffer = ALLOC_N(char, pq->buffer_size);
150
+
151
+ return Data_Wrap_Struct(klass, 0, QUEUE_free, pq);
152
+ }
153
+
154
+ static MQLONG Queue_extract_open_options(VALUE hash, VALUE name)
155
+ {
156
+ VALUE val;
157
+ MQLONG flag;
158
+ MQLONG mq_open_options = 0;
159
+
160
+ WMQ_HASH2MQLONG(hash,open_options, mq_open_options)
161
+
162
+ val = rb_hash_aref(hash, ID2SYM(ID_mode)); /* :mode */
163
+ if (!NIL_P(val))
164
+ {
165
+ ID mode_id = rb_to_id(val);
166
+
167
+ if(mode_id == ID_output) mq_open_options |= MQOO_OUTPUT;
168
+ else if(mode_id == ID_input) mq_open_options |= MQOO_INPUT_AS_Q_DEF;
169
+ else if(mode_id == ID_input_shared) mq_open_options |= MQOO_INPUT_SHARED;
170
+ else if(mode_id == ID_input_exclusive) mq_open_options |= MQOO_INPUT_EXCLUSIVE;
171
+ else if(mode_id == ID_browse) mq_open_options |= MQOO_BROWSE;
172
+ else
173
+ {
174
+ rb_raise(rb_eArgError,
175
+ "Unknown mode supplied for Queue:%s",
176
+ RSTRING(name)->ptr);
177
+ }
178
+ }
179
+ else if (!mq_open_options)
180
+ {
181
+ rb_raise(rb_eArgError,
182
+ "Either :mode or :options is required. Both are missing from hash passed to initialize() for Queue: %s",
183
+ RSTRING(name)->ptr);
184
+ }
185
+
186
+ IF_TRUE(fail_if_quiescing, 1) /* Defaults to true */
187
+ {
188
+ mq_open_options |= MQOO_FAIL_IF_QUIESCING;
189
+ }
190
+
191
+ return mq_open_options;
192
+ }
193
+
194
+ void Queue_extract_put_message_options(VALUE hash, PMQPMO ppmo)
195
+ {
196
+ VALUE val;
197
+ MQLONG flag;
198
+
199
+ WMQ_HASH2MQLONG(hash,options, ppmo->Options)
200
+
201
+ IF_TRUE(sync, 0) /* :sync */
202
+ {
203
+ ppmo->Options |= MQPMO_SYNCPOINT;
204
+ }
205
+
206
+ IF_TRUE(new_id, 0) /* :new_id */
207
+ {
208
+ ppmo->Options |= MQPMO_NEW_MSG_ID;
209
+ ppmo->Options |= MQPMO_NEW_CORREL_ID;
210
+ }
211
+ else
212
+ {
213
+ IF_TRUE(new_msg_id, 0) /* :new_msg_id */
214
+ {
215
+ ppmo->Options |= MQPMO_NEW_MSG_ID;
216
+ }
217
+
218
+ IF_TRUE(new_correl_id, 0) /* new_correl_id */
219
+ {
220
+ ppmo->Options |= MQPMO_NEW_CORREL_ID;
221
+ }
222
+ }
223
+ return;
224
+ }
225
+
226
+ /* Future Use:
227
+ * *:q_name => ['q_name1', 'q_name2'] # Not implemented: Future Use!!
228
+ * *:q_name => [ {queue_manager=>'QMGR_name',
229
+ * queue =>'queue name1'}, # Future Use!!
230
+ * { ... }
231
+ * ]
232
+ * *:resolved => { queue => 'Resolved queue name',
233
+ * queue_manager => 'Resolved queue manager name' }
234
+ */
235
+
236
+ /*
237
+ * call-seq:
238
+ * new(...)
239
+ *
240
+ * Note:
241
+ * * It is _not_ recommended to create instances of Queue directly, rather user Queue.open. Which
242
+ * creates the queue, opens the queue, executes a supplied code block and then ensures the queue
243
+ * is closed.
244
+ *
245
+ * Parameters:
246
+ * * Since the number of parameters can vary dramatically, all parameters are passed by name in a hash
247
+ * * See Queue.open for details on all parameters
248
+ *
249
+ */
250
+ VALUE Queue_initialize(VALUE self, VALUE hash)
251
+ {
252
+ VALUE str;
253
+ size_t size;
254
+ size_t length;
255
+ VALUE val;
256
+ VALUE q_name;
257
+ PQUEUE pq;
258
+
259
+ Check_Type(hash, T_HASH);
260
+
261
+ Data_Get_Struct(self, QUEUE, pq);
262
+
263
+ val = rb_hash_aref(hash, ID2SYM(ID_queue_manager)); /* :queue_manager */
264
+ if (NIL_P(val))
265
+ {
266
+ rb_raise(rb_eArgError, "Mandatory parameter :queue_manager missing from WMQ::Queue::new");
267
+ }
268
+ else
269
+ {
270
+ PQUEUE_MANAGER pqm;
271
+ Data_Get_Struct(val, QUEUE_MANAGER, pqm);
272
+ pq->exception_on_error = pqm->exception_on_error; /* Copy exception_on_error from Queue Manager setting */
273
+ pq->trace_level = pqm->trace_level; /* Copy trace_level from Queue Manager setting */
274
+
275
+ rb_iv_set(self, "@queue_manager", val);
276
+ }
277
+
278
+ q_name = rb_hash_aref(hash, ID2SYM(ID_q_name)); /* :q_name */
279
+ if (NIL_P(q_name))
280
+ {
281
+ rb_raise(rb_eArgError, "Mandatory parameter :q_name missing from WMQ::Queue::new");
282
+ }
283
+
284
+ /* --------------------------------------------------
285
+ * If :q_name is a hash, extract :q_name and :q_mgr_name
286
+ * --------------------------------------------------*/
287
+ if(TYPE(q_name) == T_HASH)
288
+ {
289
+ if(pq->trace_level)
290
+ printf ("WMQ::Queue::new q_name is a hash\n");
291
+
292
+ WMQ_HASH2MQCHARS(q_name,q_mgr_name, pq->od.ObjectQMgrName)
293
+
294
+ q_name = rb_hash_aref(q_name, ID2SYM(ID_q_name));
295
+ if (NIL_P(q_name))
296
+ {
297
+ rb_raise(rb_eArgError,
298
+ "Mandatory parameter :q_name missing from :q_name hash passed to WMQ::Queue::new");
299
+ }
300
+ }
301
+
302
+ str = StringValue(q_name);
303
+ rb_iv_set(self, "@original_name", str); /* Store original queue name */
304
+ strncpy(pq->q_name, RSTRING(str)->ptr, sizeof(pq->q_name));
305
+
306
+ pq->open_options = Queue_extract_open_options(hash, q_name);
307
+
308
+ if(pq->trace_level > 1) printf("WMQ::Queue::new Queue:%s\n", pq->q_name);
309
+
310
+ val = rb_hash_aref(hash, ID2SYM(ID_dynamic_q_name)); /* :dynamic_q_name */
311
+ if (!NIL_P(val))
312
+ {
313
+ rb_iv_set(self, "@dynamic_q_name", val);
314
+ }
315
+
316
+ WMQ_HASH2MQBYTES(hash,alternate_security_id, pq->od.AlternateSecurityId)
317
+ WMQ_HASH2MQLONG(hash,close_options, pq->close_options)
318
+ WMQ_HASH2BOOL(hash,fail_if_exists, pq->fail_if_exists)
319
+
320
+ val = rb_hash_aref(hash, ID2SYM(ID_alternate_user_id)); /* :alternate_user_id */
321
+ if (!NIL_P(val))
322
+ {
323
+ WMQ_HASH2MQCHARS(hash,alternate_user_id, pq->od.AlternateUserId)
324
+ pq->open_options |= MQOO_ALTERNATE_USER_AUTHORITY;
325
+ }
326
+
327
+ return Qnil;
328
+ }
329
+
330
+ /*
331
+ * call-seq:
332
+ * open()
333
+ *
334
+ * Open the queue
335
+ *
336
+ * Note:
337
+ * * It is not recommended to use this method to open a queue, since the queue will
338
+ * have to be closed explicitly.
339
+ * * Rather use WMQ::QueueManager#open_queue
340
+ * * If the queue is already open, it will be closed and re-opened.
341
+ * Any errors that occur while closing the queue are ignored.
342
+ * * Custom behavior for Dynamic Queues:
343
+ * When :dynamic_q_name is supplied and MQ fails to
344
+ * open the queue with MQRC_OBJECT_ALREADY_EXISTS,
345
+ * this method will automatically open the existing
346
+ * queue by replacing the queue name with :dynamic_q_name
347
+ *
348
+ * This technique allows programs to dynamically create
349
+ * queues, without being concerned with first checking if
350
+ * the queue is already defined.
351
+ * I.e. Removes the need to have to explicitly create
352
+ * required queues in advance
353
+ * However, in order for this approach to work a
354
+ * Permanent model queue must be used. A Temporary
355
+ * model queue is automatically erased by WMQ when the
356
+ * queue is closed.
357
+ *
358
+ * Persistent messages cannot be put to a
359
+ * temporary dynamic queue!
360
+ *
361
+ * Returns:
362
+ * * true : On Success
363
+ * * false: On Failure
364
+ *
365
+ * comp_code and reason_code are also updated.
366
+ * reason will return a text description of the reason_code
367
+ *
368
+ * Throws:
369
+ * * WMQ::WMQException if comp_code == MQCC_FAILED
370
+ * * Except if :exception_on_error => false was supplied as a parameter
371
+ * to QueueManager.new
372
+ *
373
+ * Example:
374
+ * require 'wmq/wmq_client'
375
+ * queue_manager = WMQ::QueueManager.new(:q_mgr_name =>'REID',
376
+ * :connection_name=>'localhost(1414)')
377
+ * begin
378
+ * queue_manager.connect
379
+ *
380
+ * # Create Queue and clear any messages from the queue
381
+ * in_queue = WMQ::Queue.new(:queue_manager =>queue_manager,
382
+ * :mode =>:input,
383
+ * :dynamic_q_name=>'UNIT.TEST',
384
+ * :q_name =>'SYSTEM.DEFAULT.MODEL.QUEUE',
385
+ * :fail_if_exists=>false)
386
+ * begin
387
+ * in_queue.open
388
+ * in_queue.each { |message| p message.data }
389
+ * ensure
390
+ * # Note: Very important: Must close the queue explicitly
391
+ * in_queue.close
392
+ * end
393
+ * rescue => exc
394
+ * queue_manager.backout
395
+ * raise exc
396
+ * ensure
397
+ * # Note: Very important: Must disconnect from the queue manager explicitly
398
+ * queue_manager.disconnect
399
+ * end
400
+ */
401
+ VALUE Queue_open(VALUE self)
402
+ {
403
+ VALUE name;
404
+ VALUE val;
405
+ VALUE dynamic_q_name;
406
+ MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */
407
+ VALUE queue_manager;
408
+ PQUEUE_MANAGER pqm;
409
+ PQUEUE pq;
410
+ Data_Get_Struct(self, QUEUE, pq);
411
+
412
+ name = rb_iv_get(self,"@original_name"); /* Always open original name */
413
+ if (NIL_P(name))
414
+ {
415
+ rb_raise(rb_eRuntimeError, "Fatal: Queue Name not found in Queue instance");
416
+ }
417
+ name = StringValue(name);
418
+
419
+ strncpy(od.ObjectName, RSTRING(name)->ptr, (size_t)MQ_Q_NAME_LENGTH);
420
+
421
+ dynamic_q_name = rb_iv_get(self,"@dynamic_q_name");
422
+ if (!NIL_P(dynamic_q_name))
423
+ {
424
+ val = StringValue(dynamic_q_name);
425
+ strncpy(od.DynamicQName, RSTRING(dynamic_q_name)->ptr, (size_t) MQ_Q_NAME_LENGTH);
426
+ if(pq->trace_level>1) printf("WMQ::Queue#open() Using dynamic queue name:%s\n", RSTRING(dynamic_q_name)->ptr);
427
+ }
428
+
429
+ queue_manager = rb_iv_get(self,"@queue_manager");
430
+ if (NIL_P(queue_manager))
431
+ {
432
+ rb_raise(rb_eRuntimeError, "Fatal: Queue Manager object not found in Queue instance");
433
+ }
434
+ Data_Get_Struct(queue_manager, QUEUE_MANAGER, pqm);
435
+ pq->MQCLOSE= pqm->MQCLOSE;
436
+ pq->MQGET = pqm->MQGET;
437
+ pq->MQPUT = pqm->MQPUT;
438
+
439
+ pq->hcon = pqm->hcon; /* Store Queue Manager handle for subsequent calls */
440
+
441
+ if(pq->trace_level)
442
+ printf ("WMQ::Queue#open() Opening Queue:%s, Queue Manager Handle:%d\n", RSTRING(name)->ptr, pq->hcon);
443
+
444
+ if(pq->hobj) /* Close queue if already open, ignore errors */
445
+ {
446
+ if(pq->trace_level)
447
+ printf ("WMQ::Queue#open() Queue:%s Already open, closing it!\n", RSTRING(name)->ptr);
448
+
449
+ pqm->MQCLOSE(pq->hcon, &pq->hobj, pq->close_options, &pq->comp_code, &pq->reason_code);
450
+ }
451
+
452
+ pqm->MQOPEN(pq->hcon, &od, pq->open_options, &pq->hobj, &pq->comp_code, &pq->reason_code);
453
+
454
+ /* --------------------------------------------------
455
+ * If the Dynamic Queue already exists, just open the
456
+ * dynamic queue name directly
457
+ * --------------------------------------------------*/
458
+ if (pq->reason_code == MQRC_OBJECT_ALREADY_EXISTS &&
459
+ !pq->fail_if_exists &&
460
+ !NIL_P(dynamic_q_name))
461
+ {
462
+ strncpy(od.ObjectName, od.DynamicQName, (size_t) MQ_Q_MGR_NAME_LENGTH);
463
+ od.DynamicQName[0] = 0;
464
+
465
+ if(pq->trace_level)
466
+ printf("WMQ::Queue#open() Queue already exists, re-trying with queue name:%s\n",
467
+ RSTRING(dynamic_q_name)->ptr);
468
+
469
+ pqm->MQOPEN(pq->hcon, &od, pq->open_options, &pq->hobj, &pq->comp_code, &pq->reason_code);
470
+ }
471
+
472
+ if(pq->trace_level)
473
+ printf("WMQ::Queue#open() MQOPEN completed with reason:%s, Handle:%d\n",
474
+ wmq_reason(pq->reason_code),
475
+ pq->hobj);
476
+
477
+ if (pq->comp_code == MQCC_FAILED)
478
+ {
479
+ pq->hobj = 0;
480
+ pq->hcon = 0;
481
+
482
+ if (pq->exception_on_error)
483
+ {
484
+ VALUE name = rb_iv_get(self,"@original_name");
485
+ name = StringValue(name);
486
+
487
+ rb_raise(wmq_exception,
488
+ "WMQ::Queue#open(). Error opening Queue:%s, reason:%s",
489
+ RSTRING(name)->ptr,
490
+ wmq_reason(pq->reason_code));
491
+ }
492
+ return Qfalse;
493
+ }
494
+ else
495
+ {
496
+ size_t size;
497
+ size_t length;
498
+ size_t i;
499
+ char* pChar;
500
+
501
+ WMQ_MQCHARS2STR(od.ObjectName, val)
502
+ rb_iv_set(self, "@name", val); /* Store actual queue name E.g. Dynamic Queue */
503
+
504
+ if(pq->trace_level>1) printf("WMQ::Queue#open() Actual Queue Name opened:%s\n", RSTRING(val)->ptr);
505
+ }
506
+
507
+ /* Future Use:
508
+ WMQ_MQCHARS2HASH(hash,resolved_q_name, pmqod->ResolvedQName)
509
+ WMQ_MQCHARS2HASH(hash,resolved_q_mgr_name, pmqod->ResolvedQMgrName)
510
+ */
511
+
512
+ return Qtrue;
513
+ }
514
+
515
+ /*
516
+ * Close the queue
517
+ *
518
+ * Returns:
519
+ * * true : On Success
520
+ * * false: On Failure
521
+ *
522
+ * comp_code and reason_code are also updated.
523
+ * reason will return a text description of the reason_code
524
+ *
525
+ * Throws:
526
+ * * WMQ::WMQException if comp_code == MQCC_FAILED
527
+ * * Except if :exception_on_error => false was supplied as a parameter
528
+ * to QueueManager.new
529
+ */
530
+ VALUE Queue_close(VALUE self)
531
+ {
532
+ PQUEUE pq;
533
+ Data_Get_Struct(self, QUEUE, pq);
534
+
535
+ /* Check if queue is open */
536
+ if (!pq->hcon)
537
+ {
538
+ if(pq->trace_level) printf ("WMQ::Queue#close() Queue not open\n");
539
+ return Qtrue;
540
+ }
541
+
542
+ if(pq->trace_level) printf ("WMQ::Queue#close() Queue Handle:%ld, Queue Manager Handle:%ld\n", pq->hobj, pq->hcon);
543
+
544
+ pq->MQCLOSE(pq->hcon, &pq->hobj, pq->close_options, &pq->comp_code, &pq->reason_code);
545
+
546
+ pq->hcon = 0; /* Every time the queue is opened, the qmgr handle must be fetched again! */
547
+ pq->hobj = 0;
548
+
549
+ if(pq->trace_level) printf("WMQ::Queue#close() MQCLOSE ended with reason:%s\n", wmq_reason(pq->reason_code));
550
+
551
+ if (pq->comp_code == MQCC_FAILED)
552
+ {
553
+ if (pq->exception_on_error)
554
+ {
555
+ VALUE name = Queue_name(self);
556
+
557
+ rb_raise(wmq_exception,
558
+ "WMQ::Queue#close(). Error closing Queue:%s, reason:%s",
559
+ RSTRING(name)->ptr,
560
+ wmq_reason(pq->reason_code));
561
+ }
562
+ return Qfalse;
563
+ }
564
+
565
+ return Qtrue;
566
+ }
567
+
568
+ /*
569
+ * call-seq:
570
+ * get(...)
571
+ *
572
+ * Get a message from the opened queue
573
+ *
574
+ * Parameters:
575
+ * * a Hash consisting of one or more of the named parameters
576
+ * * Summary of parameters and their WebSphere MQ equivalents:
577
+ * queue.get( # WebSphere MQ Equivalents:
578
+ * :message => my_message, # n/a : Instance of Message
579
+ * :sync => false, # MQGMO_SYNCPOINT
580
+ * :wait => 0, # MQGMO_WAIT, duration in ms
581
+ * :match => WMQ::MQMO_NONE, # MQMO_*
582
+ * :convert => false, # MQGMO_CONVERT
583
+ * :fail_if_quiescing => true # MQOO_FAIL_IF_QUIESCING
584
+ * :options => WMQ::MQGMO_FAIL_IF_QUIESCING # MQGMO_*
585
+ * )
586
+ *
587
+ * Mandatory Parameters
588
+ * * :message => Message
589
+ * * An instance of the WMQ::Message
590
+ *
591
+ * Optional Parameters
592
+ * * :sync => true or false
593
+ * * Determines whether the get is performed under synchpoint.
594
+ * I.e. Under the current unit of work
595
+ * Default: false
596
+ *
597
+ * * :wait => FixNum
598
+ * * The time in milli-seconds to wait for a message if one is not immediately available
599
+ * on the queue
600
+ * * Note: Under the covers the put option MQGMO_WAIT is automatically set when :wait
601
+ * is supplied
602
+ * Default: Wait forever
603
+ *
604
+ * * :match => FixNum
605
+ * * One or more of the following values:
606
+ * WMQ::MQMO_MATCH_MSG_ID
607
+ * WMQ::MQMO_MATCH_CORREL_ID
608
+ * WMQ::MQMO_MATCH_GROUP_ID
609
+ * WMQ::MQMO_MATCH_MSG_SEQ_NUMBER
610
+ * WMQ::MQMO_MATCH_OFFSET
611
+ * WMQ::MQMO_MATCH_MSG_TOKEN
612
+ * WMQ::MQMO_NONE
613
+ * * Multiple values can be or'd together. E.g.
614
+ * :match=>WMQ::MQMO_MATCH_MSG_ID | WMQ::MQMO_MATCH_CORREL_ID
615
+ * * Please see the WebSphere MQ documentation for more details on the above options
616
+ * Default: WMQ::MQMO_MATCH_MSG_ID | WMQ::MQMO_MATCH_CORREL_ID
617
+ *
618
+ * * :convert => true or false
619
+ * * When true, convert results in messages being converted to the local code page.
620
+ * E.g. When an EBCDIC text message from a mainframe is received, it will be converted
621
+ * to ASCII before passing the message data to the application.
622
+ * Default: false
623
+ *
624
+ * * :fail_if_quiescing => true or false
625
+ * * Determines whether the WMQ::Queue#get call will fail if the queue manager is
626
+ * in the process of being quiesced.
627
+ * * Note: This interface differs from other WebSphere MQ interfaces,
628
+ * they do not default to true.
629
+ * Default: true
630
+ *
631
+ * * :options => Fixnum (Advanced MQ Use only)
632
+ * * Numeric field containing any of the MQ Get message options or'd together
633
+ * * E.g. :options => WMQ::MQGMO_SYNCPOINT_IF_PERSISTENT | WMQ::MQGMO_MARK_SKIP_BACKOUT
634
+ * * Note: If :options is supplied, it is applied first, then the above parameters are
635
+ * applied afterwards.
636
+ * * One or more of the following values:
637
+ * WMQ::MQGMO_SYNCPOINT_IF_PERSISTENT
638
+ * WMQ::MQGMO_NO_SYNCPOINT
639
+ * WMQ::MQGMO_MARK_SKIP_BACKOUT
640
+ * WMQ::MQGMO_BROWSE_FIRST
641
+ * WMQ::MQGMO_BROWSE_NEXT
642
+ * WMQ::MQGMO_BROWSE_MSG_UNDER_CURSOR
643
+ * WMQ::MQGMO_MSG_UNDER_CURSOR
644
+ * WMQ::MQGMO_LOCK
645
+ * WMQ::MQGMO_UNLOCK
646
+ * WMQ::MQGMO_LOGICAL_ORDER
647
+ * WMQ::MQGMO_COMPLETE_MSG
648
+ * WMQ::MQGMO_ALL_MSGS_AVAILABLE
649
+ * WMQ::MQGMO_ALL_SEGMENTS_AVAILABLE
650
+ * WMQ::MQGMO_DELETE_MSG
651
+ * WMQ::MQGMO_NONE
652
+ * * Please see the WebSphere MQ documentation for more details on the above options
653
+ * Default: WMQ::MQGMO_NONE
654
+ *
655
+ * Returns:
656
+ * * true : On Success
657
+ * * false: On Failure, or if no message was found on the queue during the wait interval
658
+ *
659
+ * comp_code and reason_code are also updated.
660
+ * reason will return a text description of the reason_code
661
+ *
662
+ * Throws:
663
+ * * WMQ::WMQException if comp_code == MQCC_FAILED
664
+ * * Except if :exception_on_error => false was supplied as a parameter
665
+ * to QueueManager.new
666
+ *
667
+ * Example:
668
+ * require 'wmq/wmq'
669
+ *
670
+ * WMQ::QueueManager.connect(:q_mgr_name=>'REID') do |qmgr|
671
+ * qmgr.open_queue(:q_name=>'TEST.QUEUE', :mode=>:input) do |queue|
672
+ * message = WMQ::Message.new
673
+ * if queue.get(:message => message)
674
+ * puts "Data Received: #{message.data}"
675
+ * else
676
+ * puts 'No message available'
677
+ * end
678
+ * end
679
+ * end
680
+ */
681
+ VALUE Queue_get(VALUE self, VALUE hash)
682
+ {
683
+ VALUE handle;
684
+ VALUE val;
685
+ VALUE str;
686
+ VALUE descriptor;
687
+ VALUE data;
688
+ VALUE message;
689
+ PQUEUE pq;
690
+ MQLONG flag;
691
+ MQLONG messlen; /* message length received */
692
+
693
+ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */
694
+ MQGMO gmo = {MQGMO_DEFAULT}; /* get message options */
695
+
696
+ gmo.Version = MQGMO_CURRENT_VERSION; /* Allow MatchOptions */
697
+
698
+ Check_Type(hash, T_HASH);
699
+
700
+ Data_Get_Struct(self, QUEUE, pq);
701
+
702
+ /* Automatically open the queue if not already open */
703
+ if (!pq->hcon && (Queue_open(self) == Qfalse))
704
+ {
705
+ return Qfalse;
706
+ }
707
+
708
+ message = rb_hash_aref(hash, ID2SYM(ID_message));
709
+ if (NIL_P(message))
710
+ {
711
+ VALUE name = Queue_name(self);
712
+
713
+ rb_raise(rb_eArgError,
714
+ "Mandatory key :message is missing from hash passed to get() for Queue: %s",
715
+ RSTRING(name)->ptr);
716
+ }
717
+
718
+ Message_build_mqmd(message, &md);
719
+
720
+ WMQ_HASH2MQLONG(hash,options, gmo.Options) /* :options */
721
+
722
+ IF_TRUE(sync, 0) /* :sync defaults to false */
723
+ {
724
+ gmo.Options |= MQGMO_SYNCPOINT;
725
+ }
726
+
727
+ IF_TRUE(fail_if_quiescing, 1) /* :fail_if_quiescing defaults to true */
728
+ {
729
+ gmo.Options |= MQGMO_FAIL_IF_QUIESCING;
730
+ }
731
+
732
+ IF_TRUE(convert, 0) /* :convert defaults to false */
733
+ {
734
+ gmo.Options |= MQGMO_CONVERT;
735
+ }
736
+
737
+ val = rb_hash_aref(hash, ID2SYM(ID_wait)); /* :wait */
738
+ if (!NIL_P(val))
739
+ {
740
+ gmo.Options |= MQGMO_WAIT;
741
+ gmo.WaitInterval = NUM2LONG(val);
742
+ }
743
+
744
+ WMQ_HASH2MQLONG(hash,match, gmo.MatchOptions) /* :match */
745
+
746
+ if(pq->trace_level > 1) printf("WMQ::Queue#get() Get Message Option: MatchOptions=%ld\n", gmo.MatchOptions);
747
+ if(pq->trace_level) printf("WMQ::Queue#get() Queue Handle:%ld, Queue Manager Handle:%ld\n", pq->hobj, pq->hcon);
748
+
749
+ /* If descriptor is re-used
750
+
751
+ md.Encoding = MQENC_NATIVE;
752
+ md.CodedCharSetId = MQCCSI_Q_MGR;
753
+ */
754
+
755
+ /*
756
+ * Auto-Grow buffer size
757
+ *
758
+ * Note: If msg size is 70,000, we grow to 70,000, but then another program gets that
759
+ * message. The next message could be say 80,000 bytes in size, we need to
760
+ * grow the buffer again.
761
+ */
762
+ do
763
+ {
764
+ pq->MQGET(
765
+ pq->hcon, /* connection handle */
766
+ pq->hobj, /* object handle */
767
+ &md, /* message descriptor */
768
+ &gmo, /* get message options */
769
+ pq->buffer_size, /* message buffer size */
770
+ pq->p_buffer, /* message buffer */
771
+ &messlen, /* message length */
772
+ &pq->comp_code, /* completion code */
773
+ &pq->reason_code); /* reason code */
774
+
775
+ /* report reason, if any */
776
+ if (pq->reason_code != MQRC_NONE)
777
+ {
778
+ if(pq->trace_level>1) printf("WMQ::Queue#get() Growing buffer size from %ld to %ld\n", pq->buffer_size, messlen);
779
+ /* TODO: Add support for autogrow buffer here */
780
+ if (pq->reason_code == MQRC_TRUNCATED_MSG_FAILED)
781
+ {
782
+ if(pq->trace_level>2)
783
+ printf ("WMQ::Queue#reallocate Resizing buffer from %ld to %ld bytes\n", pq->buffer_size, messlen);
784
+
785
+ free(pq->p_buffer);
786
+ pq->buffer_size = messlen;
787
+ pq->p_buffer = ALLOC_N(char, messlen);
788
+ }
789
+ }
790
+ }
791
+ while (pq->reason_code == MQRC_TRUNCATED_MSG_FAILED);
792
+
793
+ if(pq->trace_level) printf("WMQ::Queue#get() MQGET ended with reason:%s\n", wmq_reason(pq->reason_code));
794
+
795
+ if (pq->comp_code != MQCC_FAILED)
796
+ {
797
+ Message_deblock(message, &md, pq->p_buffer, messlen, pq->trace_level); /* Extract MQMD and any other known MQ headers */
798
+ return Qtrue;
799
+ }
800
+ else
801
+ {
802
+ Message_clear(message);
803
+
804
+ /* --------------------------------------------------
805
+ * Do not throw exception when no more messages to be read
806
+ * --------------------------------------------------*/
807
+ if (pq->exception_on_error && (pq->reason_code != MQRC_NO_MSG_AVAILABLE))
808
+ {
809
+ VALUE name = Queue_name(self);
810
+
811
+ rb_raise(wmq_exception,
812
+ "WMQ::Queue#get(). Error reading a message from Queue:%s, reason:%s",
813
+ RSTRING(name)->ptr,
814
+ wmq_reason(pq->reason_code));
815
+ }
816
+ return Qfalse;
817
+ }
818
+ }
819
+
820
+ /*
821
+ * call-seq:
822
+ * put(...)
823
+ *
824
+ * Put a message to the WebSphere MQ queue
825
+ *
826
+ * Parameters:
827
+ * * A Hash consisting of one or more of the named parameters
828
+ * * Summary of parameters and their WebSphere MQ equivalents
829
+ * queue.put( # WebSphere MQ Equivalents:
830
+ * :message => my_message, # n/a : Instance of Message
831
+ * :data => "Hello World", # n/a : Data to send
832
+ * :sync => false, # MQGMO_SYNCPOINT
833
+ * :new_id => true, # MQPMO_NEW_MSG_ID & MQPMO_NEW_CORREL_ID
834
+ * :new_msg_id => true, # MQPMO_NEW_MSG_ID
835
+ * :new_correl_id => true, # MQPMO_NEW_CORREL_ID
836
+ * :fail_if_quiescing => true, # MQOO_FAIL_IF_QUIESCING
837
+ * :options => WMQ::MQPMO_FAIL_IF_QUIESCING # MQPMO_*
838
+ * )
839
+ *
840
+ * Mandatory Parameters:
841
+ *
842
+ * * Either :message or :data must be supplied
843
+ * * If both are supplied, then :data will be written to the queue. The data in :message
844
+ * will be ignored
845
+ *
846
+ * Optional Parameters:
847
+ * * :data => String
848
+ * * Data to be written to the queue. Can be binary or text data
849
+ * * Takes precendence over the data in :message
850
+ *
851
+ * * :message => Message
852
+ * * An instance of the WMQ::Message
853
+ * * The Message descriptor, headers and data is retrieved from :message
854
+ * * message.data is ignored if :data is supplied
855
+ *
856
+ * * :sync => true or false
857
+ * * Determines whether the get is performed under synchpoint.
858
+ * I.e. Under the current unit of work
859
+ * Default: false
860
+ *
861
+ * * :new_id => true or false
862
+ * * Generate a new message id and correlation id for this
863
+ * message. :new_msg_id and :new_correl_id will be ignored
864
+ * if this parameter is true
865
+ * Default: false
866
+ *
867
+ * * :new_msg_id => true or false
868
+ * * Generate a new message id for this message
869
+ * * Note: A blank message id will result in a new message id anyway.
870
+ * However, for subsequent puts using the same message descriptor, the same
871
+ * message id will be used.
872
+ * Default: false
873
+ *
874
+ * * :new_correl_id => true or false
875
+ * * Generate a new correlation id for this message
876
+ * Default: false
877
+ *
878
+ * * :fail_if_quiescing => true or false
879
+ * * Determines whether the WMQ::Queue#put call will fail if the queue manager is
880
+ * in the process of being quiesced.
881
+ * * Note: This interface differs from other WebSphere MQ interfaces,
882
+ * they do not default to true.
883
+ * Default: true
884
+ * Equivalent to: MQGMO_FAIL_IF_QUIESCING
885
+ *
886
+ * * Note: As part of the application design, carefull consideration
887
+ * should be given as to when to allow a transaction or
888
+ * unit of work to complete or fail under this condition.
889
+ * As such it is important to include this option where
890
+ * appropriate so that MQ Administrators can shutdown the
891
+ * queue managers without having to resort to the 'immediate'
892
+ * shutdown option.
893
+ *
894
+ * * :options => Fixnum (Advanced MQ Use only)
895
+ * * Numeric field containing any of the MQ Put message options or'd together
896
+ * * E.g. :options => WMQ::MQPMO_PASS_IDENTITY_CONTEXT | WMQ::MQPMO_ALTERNATE_USER_AUTHORITY
897
+ * * Note: If :options is supplied, it is applied first, then the above parameters are
898
+ * applied afterwards.
899
+ * * One or more of the following values:
900
+ * WMQ::MQPMO_NO_SYNCPOINT
901
+ * WMQ::MQPMO_LOGICAL_ORDER
902
+ * WMQ::MQPMO_NO_CONTEXT
903
+ * WMQ::MQPMO_DEFAULT_CONTEXT
904
+ * WMQ::MQPMO_PASS_IDENTITY_CONTEXT
905
+ * WMQ::MQPMO_PASS_ALL_CONTEXT
906
+ * WMQ::MQPMO_SET_IDENTITY_CONTEXT
907
+ * WMQ::MQPMO_SET_ALL_CONTEXT
908
+ * WMQ::MQPMO_ALTERNATE_USER_AUTHORITY
909
+ * WMQ::MQPMO_RESOLVE_LOCAL_Q
910
+ * WMQ::MQPMO_NONE
911
+ * * Please see the WebSphere MQ documentation for more details on the above options
912
+ * Default: WMQ::MQPMO_NONE
913
+ *
914
+ * Returns:
915
+ * * true : On Success
916
+ * * false: On Failure
917
+ *
918
+ * comp_code and reason_code are also updated.
919
+ * reason will return a text description of the reason_code
920
+ *
921
+ * Throws:
922
+ * * WMQ::WMQException if comp_code == MQCC_FAILED
923
+ * * Except if :exception_on_error => false was supplied as a parameter
924
+ * to QueueManager.new
925
+ *
926
+ * Example:
927
+ * require 'wmq/wmq_client'
928
+ *
929
+ * WMQ::QueueManager.connect(:q_mgr_name=>'REID', :connection_name=>'localhost(1414)') do |qmgr|
930
+ * qmgr.open_queue(:q_name=>'TEST.QUEUE', :mode=>:output) do |queue|
931
+ *
932
+ * # First message
933
+ * queue.put(:data => 'Hello World')
934
+ *
935
+ * # Set Format of message to string
936
+ * message = WMQ::Message.new
937
+ * message.descriptor[:format] = WMQ::MQFMT_STRING
938
+ * queue.put(:message=>message, :data => 'Hello Again')
939
+ *
940
+ * # Or, pass the data in the message
941
+ * message = WMQ::Message.new
942
+ * message.descriptor[:format] = WMQ::MQFMT_STRING
943
+ * message.data = 'Hello Again'
944
+ * queue.put(:message=>message)
945
+ * end
946
+ * end
947
+ */
948
+ VALUE Queue_put(VALUE self, VALUE hash)
949
+ {
950
+ MQPMO pmo = {MQPMO_DEFAULT}; /* put message options */
951
+ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */
952
+ PQUEUE pq;
953
+ MQLONG BufferLength = 0; /* Length of the message in Buffer */
954
+ PMQVOID pBuffer = 0; /* Message data */
955
+
956
+ Check_Type(hash, T_HASH);
957
+
958
+ Data_Get_Struct(self, QUEUE, pq);
959
+
960
+ /* Automatically open the queue if not already open */
961
+ if (!pq->hcon && (Queue_open(self) == Qfalse))
962
+ {
963
+ return Qfalse;
964
+ }
965
+
966
+ Queue_extract_put_message_options(hash, &pmo);
967
+ Message_build(&pq->p_buffer, &pq->buffer_size, pq->trace_level,
968
+ hash, &pBuffer, &BufferLength, &md);
969
+
970
+ if(pq->trace_level) printf("WMQ::Queue#put() Queue Handle:%ld, Queue Manager Handle:%ld\n", pq->hobj, pq->hcon);
971
+
972
+ pq->MQPUT(
973
+ pq->hcon, /* connection handle */
974
+ pq->hobj, /* object handle */
975
+ &md, /* message descriptor */
976
+ &pmo, /* put message options */
977
+ BufferLength, /* message length */
978
+ pBuffer, /* message buffer */
979
+ &pq->comp_code, /* completion code */
980
+ &pq->reason_code); /* reason code */
981
+
982
+ if(pq->trace_level) printf("WMQ::Queue#put() MQPUT ended with reason:%s\n", wmq_reason(pq->reason_code));
983
+
984
+ if (pq->reason_code != MQRC_NONE)
985
+ {
986
+ if (pq->exception_on_error)
987
+ {
988
+ VALUE name = Queue_name(self);
989
+
990
+ rb_raise(wmq_exception,
991
+ "WMQ::Queue#put(). Error writing a message to Queue:%s, reason:%s",
992
+ RSTRING(name)->ptr,
993
+ wmq_reason(pq->reason_code));
994
+ }
995
+ return Qfalse;
996
+ }
997
+ else
998
+ {
999
+ VALUE message = rb_hash_aref(hash, ID2SYM(ID_message));
1000
+ if(!NIL_P(message))
1001
+ {
1002
+ VALUE descriptor = rb_funcall(message, ID_descriptor, 0);
1003
+ Message_from_mqmd(descriptor, &md); /* This should be optimized to output only fields */
1004
+ }
1005
+ }
1006
+
1007
+ return Qtrue;
1008
+ }
1009
+
1010
+ /*
1011
+ * Returns the queue name => String
1012
+ */
1013
+ VALUE Queue_name(VALUE self)
1014
+ {
1015
+ /* If Queue is open, return opened name, otherwise return original name */
1016
+ PQUEUE pq;
1017
+ Data_Get_Struct(self, QUEUE, pq);
1018
+ if (pq->hobj)
1019
+ {
1020
+ return rb_iv_get(self,"@name");
1021
+ }
1022
+ return rb_iv_get(self,"@original_name");
1023
+ }
1024
+
1025
+ struct Queue_singleton_open_arg {
1026
+ VALUE queue;
1027
+ VALUE proc;
1028
+ };
1029
+
1030
+ static VALUE Queue_singleton_open_body(struct Queue_singleton_open_arg* arg)
1031
+ {
1032
+ rb_funcall(arg->proc, ID_call, 1, arg->queue);
1033
+ return Qnil;
1034
+ }
1035
+
1036
+ static VALUE Queue_singleton_open_ensure(VALUE queue)
1037
+ {
1038
+ return Queue_close(queue);
1039
+ }
1040
+
1041
+ /*
1042
+ * call-seq:
1043
+ * open(...)
1044
+ *
1045
+ * Open a queue, then close the queue once the supplied code block completes
1046
+ *
1047
+ * Parameters:
1048
+ * * Since the number of parameters can vary dramatically, all parameters are passed by name in a hash
1049
+ * * Summary of parameters and their WebSphere MQ equivalents:
1050
+ * queue = Queue.new( # WebSphere MQ Equivalents:
1051
+ * :queue_manager => queue_manager, # n/a : Instance of QueueManager
1052
+ * :q_name => 'Queue Name', # MQOD.ObjectName
1053
+ * :q_name => { queue_manager=>'QMGR_name', # MQOD.ObjectQMgrName
1054
+ * q_name =>'q_name'}
1055
+ * :mode => :input or :input_shared or :input_exclusive or :output,
1056
+ * :fail_if_quiescing => true # MQOO_FAIL_IF_QUIESCING
1057
+ * :fail_if_exists => true, # For dynamic queues, fail if it already exists
1058
+ * :open_options => WMQ::MQOO_BIND_ON_OPEN | ... # MQOO_*
1059
+ * :close_options => WMQ::MQCO_DELETE_PURGE # MQCO_*
1060
+ * :dynamic_q_name => 'Name of Dynamic Queue' # MQOD.DynamicQName
1061
+ * :alternate_user_id => 'userid', # MQOD.AlternateUserId
1062
+ * :alternate_security_id => '' # MQOD.AlternateSecurityId
1063
+ * )
1064
+ *
1065
+ * Mandatory Parameters
1066
+ * * :queue_manager
1067
+ * * An instance of the WMQ::QueueManager class. E.g. QueueManager.new
1068
+ * * Note: This is _not_ the queue manager name!
1069
+ *
1070
+ * * :q_name => String
1071
+ * * Name of the existing WebSphere MQ local queue, model queue or remote queue to open
1072
+ * * To open remote queues for which a local remote queue definition is not available
1073
+ * pass a Hash as q_name (see q_name => Hash)
1074
+ * OR
1075
+ * * :q_name => Hash
1076
+ * * q_name => String
1077
+ * * Name of the existing WebSphere MQ local queue, model queue or remote queue to open
1078
+ * * :q_mgr_name => String
1079
+ * * Name of the remote WebSphere MQ queue manager to send the message to.
1080
+ * * This allows a message to be written to a queue on a remote queue manager
1081
+ * where a remote queue definition is not defined locally
1082
+ * * Commonly used to reply to messages from remote systems
1083
+ * * If q_mgr_name is the same as the local queue manager name then the message
1084
+ * is merely written to the local queue.
1085
+ * * Note: q_mgr_name should only be supplied when putting messages to the queue.
1086
+ * It is not possible to get messages from a queue on a queue manager other
1087
+ * than the currently connected queue manager
1088
+ *
1089
+ * * :mode => Symbol
1090
+ * * Specify how the queue is to be opened
1091
+ * * :output
1092
+ * * Open the queue for output. I.e. WMQ::Queue#put will be called
1093
+ * Equivalent to: MQOO_OUTPUT
1094
+ * * :input
1095
+ * * Open the queue for input. I.e. WMQ::Queue#get will be called.
1096
+ * * Queue sharing for reading from the queue is defined by the queue itself.
1097
+ * By default most queues are set to shared. I.e. Multiple applications
1098
+ * can read and/or write from the queue at the same time
1099
+ * Equivalent to: MQOO_INPUT_AS_Q_DEF
1100
+ * * :input_shared
1101
+ * * Open the queue for input. I.e. WMQ::Queue#get will be called.
1102
+ * * Explicitly open the queue so that other applications can read or write
1103
+ * from the same queue
1104
+ * Equivalent to: MQOO_INPUT_SHARED
1105
+ * * :input_exclusive
1106
+ * * Open the queue for input. I.e. WMQ::Queue#get will be called.
1107
+ * * Explicitly open the queue so that other applications cannot read
1108
+ * from the same queue. Does _not_ affect applications writing to the queue.
1109
+ * * Note: If :input_exclusive is used and connectivity the queue manager is lost.
1110
+ * Upon restart the queue can still be "locked". The application should retry
1111
+ * every minute or so until the queue becomes available. Otherwise, of course,
1112
+ * another application has the queue open exclusively.
1113
+ * Equivalent to: MQOO_INPUT_EXCLUSIVE
1114
+ * * :browse
1115
+ * * Browse the messages on the queue _without_ removing them from the queue
1116
+ * * Open the queue for input. I.e. WMQ::Queue#get will be called.
1117
+ * * Note: It is necessary to specify WMQ::MQGMO_BROWSE_FIRST before the
1118
+ * first get, then set WMQ::MQGMO_BROWSE_NEXT for subsequent calls.
1119
+ * * Note: For now it is also necessary to specify these options when calling
1120
+ * WMQ::Queue#each. A change will be made to each to address this.
1121
+ * Equivalent to: MQOO_BROWSE
1122
+ *
1123
+ * Optional Parameters
1124
+ * * :fail_if_quiescing => true or false
1125
+ * * Determines whether the WMQ::Queue#open call will fail if the queue manager is
1126
+ * in the process of being quiesced.
1127
+ * * Note: If set to false, the MQOO_FAIL_IF_QUIESCING flag will not be removed if
1128
+ * it was also supplied in :open_options. However, if set to true it will override
1129
+ * this value in :open_options
1130
+ * * Note: This interface differs from other WebSphere MQ interfaces,
1131
+ * they do not default to true.
1132
+ * Default: true
1133
+ * Equivalent to: MQOO_FAIL_IF_QUIESCING
1134
+ *
1135
+ * * :open_options => FixNum
1136
+ * * One or more of the following values:
1137
+ * WMQ::MQOO_INQUIRE
1138
+ * WMQ::MQOO_SET
1139
+ * WMQ::MQOO_BIND_ON_OPEN
1140
+ * WMQ::MQOO_BIND_NOT_FIXED
1141
+ * WMQ::MQOO_BIND_AS_Q_DEF
1142
+ * WMQ::MQOO_SAVE_ALL_CONTEXT
1143
+ * WMQ::MQOO_PASS_IDENTITY_CONTEXT
1144
+ * WMQ::MQOO_PASS_ALL_CONTEXT
1145
+ * WMQ::MQOO_SET_IDENTITY_CONTEXT
1146
+ * WMQ::MQOO_SET_ALL_CONTEXT
1147
+ * * Multiple values can be or'd together. E.g.
1148
+ * :open_options=>WMQ::MQOO_BIND_ON_OPEN | WMQ::MQOO_SAVE_ALL_CONTEXT
1149
+ * * Please see the WebSphere MQ documentation for more details on the above options
1150
+ *
1151
+ * * :close_options => FixNum
1152
+ * * One of the following values:
1153
+ * WMQ::MQCO_DELETE
1154
+ * WMQ::MQCO_DELETE_PURGE
1155
+ * * Please see the WebSphere MQ documentation for more details on the above options
1156
+ *
1157
+ * * :dynamic_q_name => String
1158
+ * * If a model queue name is supplied to :q_name then the final queue name that is
1159
+ * created is specified using :dynamic_q_name
1160
+ * * A complete queue name can be specified. E.g. 'MY.LOCAL.QUEUE'
1161
+ * * Or, a partial queue name can be supplied. E.g. 'MY.REPLY.QUEUE.*'
1162
+ * In this case WebSphere MQ will automatically add numbers to the end
1163
+ * of 'MY.REPLY.QUEUE.' to ensure this queue name is unique.
1164
+ * * The most common use of :dynamic_q_name is to create a temporary dynamic queue
1165
+ * to which replies can be posted for this instance of the program
1166
+ * * When opening a model queue, :dynamic_q_name is optional. However it's use is
1167
+ * recommended in order to make it easier to identify which application a
1168
+ * dynamic queue belongs to.
1169
+ *
1170
+ * * :fail_if_exists => true or false
1171
+ * * Only applicable when opening a model queue
1172
+ * * When opening a queue dynamically, sometimes the :dynamic_q_name already
1173
+ * exists. Under this condition, if :fail_if_exists is false, the queue is
1174
+ * automatically re-opened using the :dynamic_q_name. The :q_name field is ignored.
1175
+ * * This feature is usefull when creating _permanent_ dynamic queues.
1176
+ * (The model queue has the definition type set to Permanent: DEFTYPE(PERMDYN) ).
1177
+ * * In this way it is not necessary to create the queues before running the program.
1178
+ * Default: true
1179
+ *
1180
+ * * :alternate_user_id [String]
1181
+ * * Sets the alternate userid to use when messages are put to the queue
1182
+ * * Note: It is not necessary to supply WMQ::MQOO_ALTERNATE_USER_AUTHORITY
1183
+ * since it is automatically added to the :open_options when :alternate_user_id
1184
+ * is supplied
1185
+ * * See WebSphere MQ Application Programming Reference: MQOD.AlternateUserId
1186
+ *
1187
+ * * :alternate_security_id [String]
1188
+ * * Sets the alternate security id to use when messages are put to the queue
1189
+ * * See WebSphere MQ Application Programming Reference: MQOD.AlternateSecurityId
1190
+ *
1191
+ * Note:
1192
+ * * It is more convenient to use WMQ::QueueManager#open_queue, since it automatically supplies
1193
+ * the parameter :queue_manager
1194
+ * * That way :queue_manager parameter is _not_ required
1195
+ *
1196
+ * Example:
1197
+ * # Put 10 Hello World messages onto a queue
1198
+ * require 'wmq/wmq_client'
1199
+ *
1200
+ * WMQ::QueueManager.connect(:q_mgr_name=>'REID', :connection_name=>'localhost(1414)') do |qmgr|
1201
+ * WMQ::Queue.open(:queue_manager=>qmgr,
1202
+ * :q_name =>'TEST.QUEUE',
1203
+ * :mode =>:output) do |queue|
1204
+ * 10.times { |counter| queue.put(:data => "Hello World #{counter}") }
1205
+ * end
1206
+ * end
1207
+ */
1208
+ VALUE Queue_singleton_open(int argc, VALUE *argv, VALUE self)
1209
+ {
1210
+ VALUE proc, parameters, queue;
1211
+
1212
+ /* Extract parameters and code block (Proc) */
1213
+ rb_scan_args(argc, argv, "1&", &parameters, &proc);
1214
+
1215
+ queue = rb_funcall(wmq_queue, ID_new, 1, parameters);
1216
+ if(!NIL_P(proc))
1217
+ {
1218
+ if(Qtrue == Queue_open(queue))
1219
+ {
1220
+ struct Queue_singleton_open_arg arg;
1221
+ arg.queue = queue;
1222
+ arg.proc = proc;
1223
+ rb_ensure(Queue_singleton_open_body, (VALUE)&arg, Queue_singleton_open_ensure, queue);
1224
+ }
1225
+ else
1226
+ {
1227
+ return Qfalse;
1228
+ }
1229
+ }
1230
+ return queue;
1231
+ }
1232
+
1233
+ /*
1234
+ * For each message found on the queue, the supplied block is executed
1235
+ *
1236
+ * Note:
1237
+ * * If no messages are found on the queue during the supplied wait interval,
1238
+ * then the supplied block will not be called at all
1239
+ * * If :mode=>:browse is supplied when opening the queue then Queue#each will automatically
1240
+ * set MQGMO_BROWSE_FIRST and MQGMO_BROWSE_NEXT as required
1241
+ *
1242
+ * Returns:
1243
+ * * true: If at least one message was succesfully processed
1244
+ * * false: If no messages were retrieved from the queue
1245
+ *
1246
+ * Example:
1247
+ * require 'wmq/wmq'
1248
+ *
1249
+ * WMQ::QueueManager.connect(:q_mgr_name=>'REID') do |qmgr|
1250
+ * qmgr.open_queue(:q_name=>'TEST.QUEUE', :mode=>:input) do |queue|
1251
+ * queue.each do |message|
1252
+ * puts "Data Received: #{message.data}"
1253
+ * end
1254
+ * end
1255
+ * puts 'Completed.'
1256
+ * end
1257
+ */
1258
+ VALUE Queue_each(int argc, VALUE *argv, VALUE self)
1259
+ {
1260
+ VALUE message = Qnil;
1261
+ VALUE match = Qnil;
1262
+ VALUE options = Qnil;
1263
+ VALUE result = Qfalse;
1264
+ VALUE proc, hash;
1265
+ MQLONG browse = 0;
1266
+
1267
+ PQUEUE pq;
1268
+ Data_Get_Struct(self, QUEUE, pq);
1269
+
1270
+ /* Extract parameters and code block (Proc) */
1271
+ rb_scan_args(argc, argv, "01&", &hash, &proc);
1272
+
1273
+ if(NIL_P(hash))
1274
+ {
1275
+ hash = rb_hash_new();
1276
+ }
1277
+ else
1278
+ {
1279
+ message = rb_hash_aref(hash, ID2SYM(ID_message));
1280
+ match = rb_hash_aref(hash, ID2SYM(ID_match));
1281
+ options = rb_hash_aref(hash, ID2SYM(ID_options));
1282
+ }
1283
+
1284
+ if (NIL_P(message))
1285
+ {
1286
+ message = rb_funcall(wmq_message, ID_new, 0);
1287
+ rb_hash_aset(hash, ID2SYM(ID_message), message);
1288
+ }
1289
+
1290
+ if (NIL_P(match))
1291
+ {
1292
+ rb_hash_aset(hash, ID2SYM(ID_match), LONG2NUM(MQMO_NONE));
1293
+ }
1294
+
1295
+ /* If queue is open for browse, set Borwse first indicator */
1296
+ if(pq->open_options & MQOO_BROWSE)
1297
+ {
1298
+ MQLONG get_options;
1299
+ if(NIL_P(options))
1300
+ {
1301
+ get_options = MQGMO_BROWSE_FIRST;
1302
+ }
1303
+ else
1304
+ {
1305
+ get_options = NUM2LONG(options) | MQGMO_BROWSE_FIRST;
1306
+ }
1307
+ rb_hash_aset(hash, ID2SYM(ID_options), LONG2NUM(get_options));
1308
+
1309
+ if(pq->trace_level>1) printf("WMQ::Queue#each MQGMO_BROWSE_FIRST set, get options:%ld\n", get_options);
1310
+ browse = 1;
1311
+ }
1312
+
1313
+ while(Queue_get(self, hash))
1314
+ {
1315
+ result = Qtrue;
1316
+
1317
+ /* Call code block passing in message */
1318
+ rb_funcall( proc, ID_call, 1, message );
1319
+
1320
+ if(browse)
1321
+ {
1322
+ MQLONG get_options;
1323
+ if(NIL_P(options))
1324
+ {
1325
+ get_options = MQGMO_BROWSE_NEXT;
1326
+ }
1327
+ else
1328
+ {
1329
+ get_options = (NUM2LONG(options) - MQGMO_BROWSE_FIRST) | MQGMO_BROWSE_NEXT;
1330
+ }
1331
+ rb_hash_aset(hash, ID2SYM(ID_options), LONG2NUM(get_options));
1332
+
1333
+ if(pq->trace_level>1) printf("WMQ::Queue#each MQGMO_BROWSE_NEXT set, get options:%ld\n", get_options);
1334
+ }
1335
+ }
1336
+
1337
+ return result;
1338
+ }
1339
+
1340
+ /*
1341
+ * Return the completion code for the last MQ operation on this queue instance
1342
+ *
1343
+ * Returns => FixNum
1344
+ * * WMQ::MQCC_OK 0
1345
+ * * WMQ::MQCC_WARNING 1
1346
+ * * WMQ::MQCC_FAILED 2
1347
+ * * WMQ::MQCC_UNKNOWN -1
1348
+ *
1349
+ */
1350
+ VALUE Queue_comp_code(VALUE self)
1351
+ {
1352
+ PQUEUE pq;
1353
+ Data_Get_Struct(self, QUEUE, pq);
1354
+ return LONG2NUM(pq->comp_code);
1355
+ }
1356
+
1357
+ /*
1358
+ * Return the reason code for the last MQ operation on this queue instance
1359
+ *
1360
+ * Returns => FixNum
1361
+ * * For a complete list of reason codes, please see WMQ Constants or
1362
+ * the WebSphere MQ documentation for Reason Codes
1363
+ *
1364
+ * Note
1365
+ * * The list of Reason Codes varies depending on the version of WebSphere MQ
1366
+ * and the operating system on which Ruby WMQ was compiled
1367
+ */
1368
+ VALUE Queue_reason_code(VALUE self)
1369
+ {
1370
+ PQUEUE pq;
1371
+ Data_Get_Struct(self, QUEUE, pq);
1372
+ return LONG2NUM(pq->reason_code);
1373
+ }
1374
+
1375
+ /*
1376
+ * Returns a textual representation of the reason_code for the last MQ operation on this queue instance
1377
+ *
1378
+ * Returns => String
1379
+ * * For a complete list of reasons, please see WMQ Constants or
1380
+ * the WebSphere MQ documentation for Reason Codes
1381
+ *
1382
+ * Note
1383
+ * * The list of Reason Codes varies depending on the version of WebSphere MQ
1384
+ * and the operating system on which Ruby WMQ was compiled
1385
+ */
1386
+ VALUE Queue_reason(VALUE self)
1387
+ {
1388
+ PQUEUE pq;
1389
+ Data_Get_Struct(self, QUEUE, pq);
1390
+ return rb_str_new2(wmq_reason(pq->reason_code));
1391
+ }
1392
+
1393
+ /*
1394
+ * Returns whether this queue is currently open
1395
+ *
1396
+ * Returns:
1397
+ * * true : The queue is open
1398
+ * * false: The queue is _not_ open
1399
+ */
1400
+ VALUE Queue_open_q(VALUE self)
1401
+ {
1402
+ PQUEUE pq;
1403
+ Data_Get_Struct(self, QUEUE, pq);
1404
+ if (pq->hobj)
1405
+ {
1406
+ return Qtrue;
1407
+ }
1408
+ return Qfalse;
1409
+ }
1410
+