ekaranto-rubywmq 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/.document +4 -0
  2. data/LICENSE.txt +201 -0
  3. data/README.md +408 -0
  4. data/Rakefile +87 -0
  5. data/examples/each_a.rb +16 -0
  6. data/examples/each_b.rb +25 -0
  7. data/examples/each_header.rb +22 -0
  8. data/examples/files_to_q.cfg +24 -0
  9. data/examples/files_to_q.rb +31 -0
  10. data/examples/get_a.rb +19 -0
  11. data/examples/get_client.rb +35 -0
  12. data/examples/put1_a.rb +9 -0
  13. data/examples/put1_b.rb +17 -0
  14. data/examples/put1_c.rb +16 -0
  15. data/examples/put_a.rb +19 -0
  16. data/examples/put_b.rb +27 -0
  17. data/examples/put_dlh.rb +25 -0
  18. data/examples/put_dynamic_q.rb +22 -0
  19. data/examples/put_group_a.rb +35 -0
  20. data/examples/put_group_b.rb +37 -0
  21. data/examples/put_rfh.rb +51 -0
  22. data/examples/put_rfh2_a.rb +27 -0
  23. data/examples/put_rfh2_b.rb +27 -0
  24. data/examples/put_xmit_q.rb +17 -0
  25. data/examples/q_to_files.cfg +17 -0
  26. data/examples/q_to_files.rb +32 -0
  27. data/examples/request.rb +44 -0
  28. data/examples/server.rb +81 -0
  29. data/ext/decode_rfh.c +348 -0
  30. data/ext/decode_rfh.h +45 -0
  31. data/ext/extconf.rb +30 -0
  32. data/ext/extconf_client.rb +24 -0
  33. data/ext/generate/generate_const.rb +140 -0
  34. data/ext/generate/generate_reason.rb +233 -0
  35. data/ext/generate/generate_structs.rb +82 -0
  36. data/ext/generate/wmq_structs.erb +341 -0
  37. data/ext/wmq.c +90 -0
  38. data/ext/wmq.h +371 -0
  39. data/ext/wmq_message.c +671 -0
  40. data/ext/wmq_mq_load.c +217 -0
  41. data/ext/wmq_queue.c +1411 -0
  42. data/ext/wmq_queue_manager.c +1570 -0
  43. data/lib/rubywmq.rb +1 -0
  44. data/lib/wmq/message.rb +70 -0
  45. data/lib/wmq/queue_manager.rb +110 -0
  46. data/lib/wmq/version.rb +3 -0
  47. data/lib/wmq.rb +16 -0
  48. data/nbproject/project.properties +11 -0
  49. data/nbproject/project.xml +17 -0
  50. data/tests/test.rb +318 -0
  51. metadata +115 -0
@@ -0,0 +1,341 @@
1
+ <%
2
+ symbols = {
3
+ 'descriptor='=>nil,
4
+ 'headers='=>nil,
5
+ 'data='=>nil,
6
+ 'header_type'=>nil,
7
+ 'to_s'=>nil,
8
+ 'xml'=>nil,
9
+ 'name_value'=>nil,
10
+ }
11
+ wmq_structs = [
12
+ # Message Descriptor
13
+ {:file=>'cmqc.h', :struct=>'MQMD'},
14
+
15
+ # Message Descriptor 1
16
+ {:file=>'cmqc.h', :struct=>'MQMD1', :other_keys=>[:remote_q_name, :remote_q_mgr_name]},
17
+
18
+ # Rules and formatting header2
19
+ {:file=>'cmqc.h', :struct=>'MQRFH2', :header=>'rf_header_2', :struct_id=>'MQRFH_STRUC_ID',
20
+ :other_keys=>[:xml],
21
+ :custom=>true }, # Implement custom Message_build_rf_header_2 and Message_deblock_rf_header_2
22
+
23
+ # Rules and formatting header
24
+ {:file=>'cmqc.h', :struct=>'MQRFH', :header=>'rf_header', :other_keys=>[:name_value],
25
+ :custom=>true }, # Implement custom Message_build_rf_header and Message_deblock_rf_header
26
+
27
+ # Dead Letter Header
28
+ {:file=>'cmqc.h', :struct=>'MQDLH', :header=>'dead_letter_header',
29
+ :defaults=>'MQDLH_DEF.CodedCharSetId = MQCCSI_INHERIT;'},
30
+
31
+ # CICS bridge header
32
+ {:file=>'cmqc.h', :struct=>'MQCIH', :header=>'cics'},
33
+
34
+ # Distribution header
35
+ {:file=>'cmqc.h', :struct=>'MQDH', :header=>'dist_header'},
36
+
37
+ # IMS information header
38
+ {:file=>'cmqc.h', :struct=>'MQIIH', :header=>'ims'},
39
+
40
+ # Reference message header (send large files over channels)
41
+ {:file=>'cmqc.h', :struct=>'MQRMH', :header=>'ref_msg_header'},
42
+
43
+ # Trigger Message
44
+ {:file=>'cmqc.h', :struct=>'MQTM', :header=>'trigger', :format=>false},
45
+
46
+ # Trigger Message 2 (character format)
47
+ {:file=>'cmqc.h', :struct=>'MQTMC2'},
48
+
49
+ # Work Information header
50
+ {:file=>'cmqc.h', :struct=>'MQWIH', :header=>'work_info_header'},
51
+
52
+ # Transmission-queue header - Todo: Need to deal with MQMDE
53
+ {:file=>'cmqc.h', :struct=>'MQXQH', :header=>'xmit_q_header', :format=>'MsgDesc.Format'},
54
+ ]
55
+
56
+ wmq_structs.each do |struct|
57
+ # Parse WebSphere MQ 'C' Header file and extract elements
58
+ elements = extract_struct(@path+'/'+struct[:file], struct[:struct])
59
+ struct[:elements] = elements
60
+
61
+ # Add symbol for each struct name
62
+ symbols[struct[:header]]=nil if struct[:header]
63
+
64
+ # Add symbols for each element in C Struct
65
+ elements.each do |item|
66
+ symbols[rubyize_name(item[1])] = nil unless @@field_ignore_list.include?(item[1])
67
+ end
68
+ end
69
+ %>
70
+ /* --------------------------------------------------------------------------
71
+ *
72
+ * WARNING: DO NOT MODIFY THIS FILE
73
+ *
74
+ * This file was generated by generate_structs.rb.
75
+ *
76
+ * --------------------------------------------------------------------------*/
77
+
78
+ #include "wmq.h"
79
+
80
+ /* --------------------------------------------------------------------------
81
+ * Static's to hold Symbols
82
+ * --------------------------------------------------------------------------*/
83
+ <%
84
+ header_file = 'cmqc.h'
85
+ struct = 'MQMD'
86
+
87
+ # Define static variables to hold Ruby symbols
88
+ key_list = symbols.keys.sort
89
+ key_list.each do |key, value|
90
+ %><%="static ID ID_#{key.sub('=', '_set')};\n" %><%
91
+ end
92
+
93
+ # initialize symbols
94
+ %>
95
+ /* --------------------------------------------------------------------------
96
+ * Initialize Symbols
97
+ * --------------------------------------------------------------------------*/
98
+ void wmq_structs_id_init()
99
+ {
100
+ <% key_list.each do |key, value|
101
+ %><%=" ID_%-20s = rb_intern(\"%s\");\n"% [key.sub('=', '_set'), key] %><%
102
+ end
103
+ %>}
104
+ <%
105
+ # Generate functions to move to/from a Ruby Hash of the symbols defined above
106
+ wmq_structs.each do |struct|
107
+ elements = struct[:elements]
108
+ struct_name = struct[:struct]
109
+ variable = 'p'+struct_name.downcase
110
+ %>
111
+ /* --------------------------------------------------------------------------
112
+ * Convert between <%=struct_name%> and Hash
113
+ * --------------------------------------------------------------------------*/
114
+ void Message_from_<%=struct_name.downcase%>(VALUE hash, <%=struct_name%>* <%=variable%>)
115
+ {
116
+ VALUE str;
117
+ size_t size;
118
+ size_t length;
119
+ size_t i;
120
+ char* pChar;
121
+
122
+ <%
123
+ elements.each do |item|
124
+ type = item[0]
125
+ name = item[1]
126
+
127
+ next if @@field_ignore_list.include?(name) ||
128
+ (name=='Format' && struct[:header])
129
+
130
+ match = /(MQ\D+)/.match(type)
131
+ type = "#{match[1]}S" if match[1] != type
132
+ %><%= if type == 'MQMDS'
133
+ " %-16s(hash, &#{variable}->%s);\n" % ['Message_from_mqmd1', name]
134
+ else
135
+ " %-16s(hash, %-30s #{variable}->%s)\n" % ["WMQ_#{type}2HASH", rubyize_name(name)+',',name]
136
+ end %><%
137
+ end
138
+ %>}
139
+
140
+ static int Message_to_<%=struct_name.downcase%>_each (VALUE key, VALUE value, <%=struct_name%>* p<%=struct_name.downcase%>)
141
+ {
142
+ VALUE str;
143
+ size_t size;
144
+ size_t length;
145
+ VALUE val;
146
+ ID id = rb_to_id(key);
147
+
148
+ <% contains = nil
149
+ elements.each do |item|
150
+ type = item[0]
151
+ name = item[1]
152
+
153
+ next if @@field_ignore_list.include?(name) ||
154
+ (name=='Format' && struct[:header])
155
+
156
+ match = /(MQ\D+)/.match(type)
157
+ type = "#{match[1]}S" if match[1] != type
158
+ %><%= if type == 'MQMDS'
159
+ contains = 'mqmd1'
160
+ ""
161
+ else
162
+ "%-35s { %-16s(value,#{variable}->#{name}) }\n else" % [" if(id == ID_#{rubyize_name(name)})", "WMQ_STR2#{type}"]
163
+ end%><%
164
+ end
165
+ if struct[:other_keys]
166
+ struct[:other_keys].each do |key|
167
+ %> if(id == ID_<%=key.to_s%>) {}
168
+ else<% end
169
+ end
170
+ %><%=struct[:header]?" if(id != ID_header_type)":""%><%
171
+ if contains
172
+ %> {
173
+ Message_to_<%= contains%>_each(key, value, &pmqxqh->MsgDesc);
174
+ }<%
175
+ else%>
176
+ {
177
+ val = rb_funcall(key, ID_to_s, 0);
178
+ rb_raise(rb_eArgError, "WMQ::Message#to_<%=struct_name.downcase%> Unknown symbol :%s supplied", RSTRING_PTR(val));
179
+ }
180
+ <% end%>
181
+ return 0;
182
+ }
183
+
184
+ void Message_to_<%=struct_name.downcase%>(VALUE hash, <%=struct_name%>* p<%=struct_name.downcase%>)
185
+ {
186
+ rb_hash_foreach(hash, Message_to_<%=struct_name.downcase%>_each, (VALUE)p<%=struct_name.downcase%>);
187
+ }
188
+ <% end # wmq_structs.each
189
+ %>
190
+
191
+ /* --------------------------------------------------------------------------
192
+ * Extract message data and headers
193
+ * --------------------------------------------------------------------------*/
194
+ void Message_deblock(VALUE self, PMQMD pmqmd, PMQBYTE p_buffer, MQLONG total_length, MQLONG trace_level)
195
+ {
196
+ PMQCHAR p_format = pmqmd->Format; /* Start with format in MQMD */
197
+ PMQBYTE p_data = p_buffer; /* Pointer to start of data */
198
+ MQLONG data_length= total_length; /* length of data portion */
199
+ VALUE headers = rb_ary_new();
200
+ VALUE descriptor = rb_hash_new();
201
+ MQLONG size = 0;
202
+
203
+ while (p_format)
204
+ {
205
+ <%
206
+ wmq_structs.each do |struct|
207
+ if struct[:header]
208
+ %> /* <%=struct[:struct]%>: <%=struct[:header]%> */
209
+ if(strncmp(p_format, MQFMT_<%=struct[:header].upcase%>, MQ_FORMAT_LENGTH) == 0)
210
+ {
211
+ VALUE hash = rb_hash_new();
212
+ P<%=struct[:struct]%> p_header = (P<%=struct[:struct]%>)p_data;
213
+
214
+ if(trace_level>2)
215
+ printf("WMQ::Message#deblock Found <%=struct[:header]%>\n");
216
+
217
+ if(memcmp(p_header->StrucId, <%=struct[:struct_id] || "#{struct[:struct].upcase}_STRUC_ID"%>, sizeof(p_header->StrucId)) != 0)
218
+ {
219
+ if(trace_level>1)
220
+ printf("WMQ::Message#deblock MQFMT_<%=struct[:header].upcase%> received, but message does not contain <%=struct[:struct].upcase%>\n");
221
+ break; /* Bad Message received, do not deblock headers */
222
+ }
223
+ else
224
+ {
225
+ Message_from_<%=struct[:struct].downcase%>(hash, p_header);
226
+ rb_hash_aset(hash, ID2SYM(ID_header_type), ID2SYM(ID_<%=struct[:header]%>));
227
+ rb_ary_push(headers, hash);
228
+ size = <%=if struct[:custom] then
229
+ "Message_deblock_#{struct[:header]} (hash, p_data, data_length);\n"+
230
+ " if (!size) break; /* Poison Message */"
231
+ elsif struct[:elements].include?(['MQLONG', 'StrucLength'])
232
+ 'p_header->StrucLength;'
233
+ else
234
+ "sizeof(#{struct[:struct]});"
235
+ end %>
236
+ p_data += size;
237
+ data_length -= size;
238
+ <%=if struct[:format] == nil
239
+ 'p_format = p_header->Format'
240
+ elsif struct[:format] == false
241
+ 'break'
242
+ else
243
+ "p_format = p_header->#{struct[:format]}"
244
+ end %>;
245
+ }
246
+ }
247
+ else
248
+ <%
249
+ end
250
+ end # wmq_structs.each
251
+ %> {
252
+ break;
253
+ }
254
+ }
255
+ /* Copy the last recognised header found to the Descriptor */
256
+ if(p_format && p_format != pmqmd->Format)
257
+ {
258
+ strncpy(pmqmd->Format, p_format, MQ_FORMAT_LENGTH);
259
+ }
260
+
261
+ Message_from_mqmd(descriptor, pmqmd);
262
+ rb_funcall(self, ID_descriptor_set, 1, descriptor);
263
+ rb_funcall(self, ID_headers_set, 1, headers);
264
+ rb_funcall(self, ID_data_set, 1, rb_str_new(p_data, data_length));
265
+ }
266
+
267
+ void Message_build_set_format(ID header_type, PMQBYTE p_format)
268
+ {
269
+ <%
270
+ wmq_structs.each do |struct|
271
+ if struct[:header]
272
+ %> if(header_type == ID_<%=struct[:header]%>) { memcpy(p_format, MQFMT_<%=struct[:header].upcase%>, MQ_FORMAT_LENGTH); return;}
273
+ <%
274
+ end
275
+ end # wmq_structs.each
276
+
277
+ %>
278
+ rb_raise(rb_eArgError, "Invalid/Unknown header_type supplied in WMQ::Message#headers array");
279
+ }
280
+
281
+ /* --------------------------------------------------------------------------
282
+ * Build message headers
283
+ * --------------------------------------------------------------------------*/
284
+ int Message_build_header (VALUE hash, struct Message_build_header_arg* parg)
285
+ {
286
+ VALUE val = rb_hash_aref(hash, ID2SYM(ID_header_type));
287
+ PMQBYTE p_data = 0;
288
+
289
+ if (!NIL_P(val) && (TYPE(val) == T_SYMBOL))
290
+ {
291
+ ID header_id = rb_to_id(val);
292
+ <%
293
+ wmq_structs.each do |struct|
294
+ if struct[:header]
295
+ %> if (header_id == ID_<%=struct[:header]%>) /* Build <%=struct[:struct]%> */
296
+ { <%
297
+ if struct[:custom] %>
298
+ Message_build_<%=struct[:header]%> (hash, parg);
299
+ <% else %>
300
+ static <%=struct[:struct]%> <%=struct[:struct]%>_DEF = {<%=struct[:struct]%>_DEFAULT};
301
+ <%=struct[:defaults]%>
302
+
303
+ if(parg->trace_level>2)
304
+ printf ("WMQ::Message#build_header Found <%=struct[:header]%>\n");
305
+
306
+ p_data = Message_autogrow_data_buffer(parg, sizeof(<%=struct[:struct]%>));
307
+
308
+ memcpy(p_data, &<%=struct[:struct]%>_DEF, sizeof(<%=struct[:struct]%>));
309
+ Message_to_<%=struct[:struct].downcase%>(hash, (P<%=struct[:struct]%>)p_data);
310
+ <% if struct[:format] != false%>
311
+ if(parg->next_header_id)
312
+ {
313
+ Message_build_set_format(parg->next_header_id, ((P<%=struct[:struct]%>)p_data)-><%=struct[:format] || 'Format'%>);
314
+ }
315
+ else
316
+ {
317
+ memcpy(((P<%=struct[:struct]%>)p_data)-><%=struct[:format] || 'Format'%>, parg->data_format, MQ_FORMAT_LENGTH);
318
+ }
319
+ <% end %>
320
+ *(parg->p_data_offset) += sizeof(<%=struct[:struct]%>);
321
+
322
+ if(parg->trace_level>2)
323
+ printf ("WMQ::Message#build_header data offset:%ld\n", (long)(*(parg->p_data_offset)));
324
+ <% end
325
+ %> }
326
+ else
327
+ <%
328
+ end
329
+ end # wmq_structs.each
330
+
331
+ %> {
332
+ rb_raise(rb_eArgError, "Unknown :header_type supplied in WMQ::Message#headers array");
333
+ }
334
+ }
335
+ else
336
+ {
337
+ rb_raise(rb_eArgError, "Mandatory parameter :header_type missing from header entry in WMQ::Message#headers array");
338
+ }
339
+
340
+ return 0; /* Continue */
341
+ }
data/ext/wmq.c ADDED
@@ -0,0 +1,90 @@
1
+ /*
2
+ * Copyright 2006 J. Reid Morrison
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
+ VALUE wmq_queue;
20
+ VALUE wmq_queue_manager;
21
+ VALUE wmq_message;
22
+ VALUE wmq_exception;
23
+
24
+ void Init_wmq() {
25
+ VALUE wmq;
26
+
27
+ wmq = rb_define_module("WMQ");
28
+
29
+ wmq_queue_manager = rb_define_class_under(wmq, "QueueManager", rb_cObject);
30
+ rb_define_alloc_func(wmq_queue_manager, QUEUE_MANAGER_alloc);
31
+ rb_define_singleton_method(wmq_queue_manager, "connect", QueueManager_singleton_connect, -1); /* in wmq_queue_manager.c */
32
+ rb_define_method(wmq_queue_manager, "initialize", QueueManager_initialize, 1); /* in wmq_queue_manager.c */
33
+ rb_define_method(wmq_queue_manager, "connect", QueueManager_connect, 0); /* in wmq_queue_manager.c */
34
+ rb_define_method(wmq_queue_manager, "disconnect", QueueManager_disconnect, 0); /* in wmq_queue_manager.c */
35
+ rb_define_method(wmq_queue_manager, "open_queue", QueueManager_open_queue, -1); /* in wmq_queue_manager.c */
36
+ rb_define_method(wmq_queue_manager, "access_queue", QueueManager_open_queue, -1); /* in wmq_queue_manager.c */
37
+ rb_define_method(wmq_queue_manager, "begin", QueueManager_begin, 0); /* in wmq_queue_manager.c */
38
+ rb_define_method(wmq_queue_manager, "commit", QueueManager_commit, 0); /* in wmq_queue_manager.c */
39
+ rb_define_method(wmq_queue_manager, "backout", QueueManager_backout, 0); /* in wmq_queue_manager.c */
40
+ rb_define_method(wmq_queue_manager, "put", QueueManager_put, 1); /* in wmq_queue_manager.c */
41
+ rb_define_method(wmq_queue_manager, "comp_code", QueueManager_comp_code, 0); /* in wmq_queue_manager.c */
42
+ rb_define_method(wmq_queue_manager, "reason_code", QueueManager_reason_code, 0); /* in wmq_queue_manager.c */
43
+ rb_define_method(wmq_queue_manager, "reason", QueueManager_reason, 0); /* in wmq_queue_manager.c */
44
+ rb_define_method(wmq_queue_manager, "exception_on_error", QueueManager_exception_on_error, 0); /* in wmq_queue_manager.c */
45
+ rb_define_method(wmq_queue_manager, "connected?", QueueManager_connected_q, 0); /* in wmq_queue_manager.c */
46
+ rb_define_method(wmq_queue_manager, "name", QueueManager_name, 0); /* in wmq_queue_manager.c */
47
+ rb_define_method(wmq_queue_manager, "execute", QueueManager_execute, 1); /* in wmq_queue_manager.c */
48
+
49
+ wmq_queue = rb_define_class_under(wmq, "Queue", rb_cObject);
50
+ rb_define_alloc_func(wmq_queue, QUEUE_alloc);
51
+ rb_define_singleton_method(wmq_queue, "open", Queue_singleton_open, -1); /* in wmq_queue.c */
52
+ rb_define_method(wmq_queue, "initialize", Queue_initialize, 1); /* in wmq_queue.c */
53
+ rb_define_method(wmq_queue, "open", Queue_open, 0); /* in wmq_queue.c */
54
+ rb_define_method(wmq_queue, "close", Queue_close, 0); /* in wmq_queue.c */
55
+ rb_define_method(wmq_queue, "put", Queue_put, 1); /* in wmq_queue.c */
56
+ rb_define_method(wmq_queue, "get", Queue_get, 1); /* in wmq_queue.c */
57
+ rb_define_method(wmq_queue, "each", Queue_each, -1); /* in wmq_queue.c */
58
+ rb_define_method(wmq_queue, "name", Queue_name, 0); /* in wmq_queue.c */
59
+ rb_define_method(wmq_queue, "comp_code", Queue_comp_code, 0); /* in wmq_queue.c */
60
+ rb_define_method(wmq_queue, "reason_code", Queue_reason_code, 0); /* in wmq_queue.c */
61
+ rb_define_method(wmq_queue, "reason", Queue_reason, 0); /* in wmq_queue.c */
62
+ rb_define_method(wmq_queue, "open?", Queue_open_q, 0); /* in wmq_queue.c */
63
+
64
+ wmq_message = rb_define_class_under(wmq, "Message", rb_cObject);
65
+ rb_define_method(wmq_message, "initialize", Message_initialize, -1); /* in wmq_message.c */
66
+ rb_define_method(wmq_message, "clear", Message_clear, 0); /* in wmq_message.c */
67
+
68
+ /*
69
+ * WMQException is thrown whenever an MQ operation fails and
70
+ * exception_on_error is true
71
+ */
72
+ wmq_exception = rb_define_class_under(wmq, "WMQException", rb_eRuntimeError);
73
+
74
+ /*
75
+ * Initialize id fields
76
+ */
77
+ Message_id_init();
78
+ Queue_id_init();
79
+ QueueManager_id_init();
80
+ QueueManager_selector_id_init();
81
+ QueueManager_command_id_init();
82
+ wmq_structs_id_init();
83
+ }
84
+
85
+ /*
86
+ * For client build when dynamic loading is not being used E.g. Not Windows or Solaris ...
87
+ */
88
+ void Init_wmq_client() {
89
+ Init_wmq();
90
+ }