ferocia-rubywmq 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. data/.document +8 -0
  2. data/LICENSE +13 -0
  3. data/Manifest.txt +20 -0
  4. data/README +73 -0
  5. data/examples/each_a.rb +32 -0
  6. data/examples/each_b.rb +41 -0
  7. data/examples/each_header.rb +38 -0
  8. data/examples/files_to_q.cfg +24 -0
  9. data/examples/files_to_q.rb +47 -0
  10. data/examples/get_a.rb +35 -0
  11. data/examples/get_client.rb +51 -0
  12. data/examples/put1_a.rb +25 -0
  13. data/examples/put1_b.rb +33 -0
  14. data/examples/put1_c.rb +32 -0
  15. data/examples/put_a.rb +35 -0
  16. data/examples/put_b.rb +43 -0
  17. data/examples/put_dlh.rb +41 -0
  18. data/examples/put_dynamic_q.rb +38 -0
  19. data/examples/put_group_a.rb +51 -0
  20. data/examples/put_group_b.rb +53 -0
  21. data/examples/put_rfh.rb +67 -0
  22. data/examples/put_rfh2_a.rb +43 -0
  23. data/examples/put_rfh2_b.rb +43 -0
  24. data/examples/put_xmit_q.rb +33 -0
  25. data/examples/q_to_files.cfg +17 -0
  26. data/examples/q_to_files.rb +48 -0
  27. data/examples/request.rb +60 -0
  28. data/examples/server.rb +97 -0
  29. data/ext/build.bat +3 -0
  30. data/ext/build.sh +6 -0
  31. data/ext/decode_rfh.c +348 -0
  32. data/ext/decode_rfh.h +45 -0
  33. data/ext/extconf.rb +44 -0
  34. data/ext/extconf_client.rb +40 -0
  35. data/ext/generate/generate_const.rb +167 -0
  36. data/ext/generate/generate_reason.rb +246 -0
  37. data/ext/generate/generate_structs.rb +97 -0
  38. data/ext/generate/wmq_structs.erb +371 -0
  39. data/ext/lib/wmq_temp.rb +197 -0
  40. data/ext/wmq.c +93 -0
  41. data/ext/wmq.h +367 -0
  42. data/ext/wmq_message.c +671 -0
  43. data/ext/wmq_mq_load.c +217 -0
  44. data/ext/wmq_queue.c +1411 -0
  45. data/ext/wmq_queue_manager.c +1587 -0
  46. data/lib/wmq.rb +25 -0
  47. data/rubywmq.binary.gemspec +32 -0
  48. data/rubywmq.gemspec +33 -0
  49. data/tests/test.rb +328 -0
  50. metadata +124 -0
@@ -0,0 +1,246 @@
1
+ class GenerateReason
2
+
3
+ #Extract Error Code Constants from Header files
4
+ def GenerateReason.extract_const(filename, const_prefix)
5
+ @constants = []
6
+ File.open(filename) do |file|
7
+ file.each do |line|
8
+ line.rstrip!
9
+ # Skip empty and comment lines
10
+ if line.length > 0 && line !~ /^\s*\/\*/
11
+ if match = /\s*#define\s+(#{const_prefix}\w+)[\(\s]+([-\dx]+)/.match(line)
12
+ @constants << [match[1], match[2]]
13
+ end
14
+ end
15
+ end
16
+ end
17
+ @constants
18
+ end
19
+
20
+ #Extract Error Code Constants from Header files
21
+ # Uses lazy print to collect duplicate values
22
+ def GenerateReason.reason_case(filename, prefix)
23
+ last_rc = nil
24
+ last_reason = nil
25
+ str = ''
26
+ GenerateReason.extract_const(filename,prefix).each do |item|
27
+ if last_rc == item[1]
28
+ str << " case %-30s: return \"#{item[0]} or #{last_reason}[#{item[1]}]\";\n" % item[0]
29
+ last_rc = nil
30
+ last_reason = nil
31
+ else
32
+ str << " case %-30s: return \"#{last_reason}[#{last_rc}]\";\n" % last_reason if last_rc
33
+ last_rc = item[1]
34
+ last_reason = item[0]
35
+ end
36
+ end
37
+ str
38
+ end
39
+
40
+ # The WebSphere MQ header files have several duplicate values,
41
+ # so need to exclude duplicates.
42
+ def GenerateReason.selector_case(filename, prefix, excludes=nil, &block)
43
+ GenerateReason.extract_const(filename,prefix).each do |item|
44
+ next if item[0].include?('FIRST') || item[0].include?('LAST')
45
+ next if excludes && excludes.include?(item[0])
46
+ block.call item
47
+ end
48
+ end
49
+
50
+ def GenerateReason.wmq_reason(path)
51
+ str = <<END_OF_STRING
52
+ /* --------------------------------------------------------------------------
53
+ * Copyright 2006 J. Reid Morrison. Dimension Solutions, Inc.
54
+ *
55
+ * Licensed under the Apache License, Version 2.0 (the "License");
56
+ * you may not use this file except in compliance with the License.
57
+ * You may obtain a copy of the License at
58
+ *
59
+ * http://www.apache.org/licenses/LICENSE-2.0
60
+ *
61
+ * Unless required by applicable law or agreed to in writing, software
62
+ * distributed under the License is distributed on an "AS IS" BASIS,
63
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64
+ * See the License for the specific language governing permissions and
65
+ * limitations under the License.
66
+ * --------------------------------------------------------------------------
67
+ *
68
+ * WARNING: DO NOT MODIFY THIS FILE
69
+ *
70
+ * This file was generated by generate_reason.rb.
71
+ *
72
+ * --------------------------------------------------------------------------*/
73
+
74
+ #include "wmq.h"
75
+
76
+ char* wmq_reason(MQLONG reason_code)
77
+ {
78
+ switch (reason_code)
79
+ {
80
+ END_OF_STRING
81
+
82
+ [['cmqc.h', 'MQRC_'],
83
+ ['cmqcfc.h', 'MQRCCF_']].each do |item|
84
+ str << GenerateReason.reason_case(path+item[0], item[1])
85
+ end
86
+ str << <<END_OF_STRING
87
+ }
88
+ printf("WMQ::wmq_reason Unknown Reason code:%ld\\n",(long)reason_code);
89
+ return "Unknown reason code";
90
+ }
91
+
92
+ END_OF_STRING
93
+
94
+ str_switch = ''
95
+ str_id_init = ''
96
+ # Integer Selectors for Object Attributes
97
+ [['cmqc.h', 'MQIA_'],
98
+ ['cmqcfc.h', 'MQIACF_', ['MQIACF_ERROR_ID',
99
+ 'MQIACF_QUIESCE']],
100
+ ['cmqcfc.h', 'MQIACH_', ['MQIACH_CURRENT_SEQ_NUMBER',
101
+ 'MQIACH_BYTES_RCVD',
102
+ 'MQIACH_BUFFERS_RCVD']],
103
+ ['cmqcfc.h', 'MQIAMO_'],
104
+ ['cmqcfc.h', 'MQIAMO64_', ['MQIAMO64_AVG_Q_TIME',
105
+ 'MQIAMO64_Q_TIME_AVG',
106
+ 'MQIAMO64_Q_TIME_MAX',
107
+ 'MQIAMO64_Q_TIME_MIN']],
108
+ # Integer System Selectors
109
+ ['cmqbc.h', 'MQIASY_'],
110
+ # Character Selectors for Object Attributes
111
+ ['cmqc.h', 'MQCA_',['MQCA_BASE_OBJECT_NAME']],
112
+ ['cmqcfc.h', 'MQCACF_'],
113
+ ['cmqcfc.h', 'MQCACH_'],
114
+ ['cmqcfc.h', 'MQCAMO_'],
115
+ # Byte String Selectors for Object Attributes
116
+ ['cmqc.h', 'MQBA_'],
117
+ ['cmqcfc.h', 'MQBACF_'],
118
+ # Group Selectors for Object Attributes
119
+ ['cmqcfc.h', 'MQGACF_'] ].each do |item|
120
+ str << "/* Constants #{item[1]}* from #{item[0]} */\n"
121
+ str_switch << " /* Constants #{item[1]}* from #{item[0]} */\n"
122
+ str_id_init << " /* Constants #{item[1]}* from #{item[0]} */\n"
123
+ GenerateReason.selector_case(path+item[0], item[1], item[2]) do |const|
124
+ id = const[0].gsub(item[1],'').downcase
125
+ str_switch << " case %-30s: return ID_#{id};\n" % const[0]
126
+ str_id_init << " ID_%-25s = rb_intern(\"#{id}\");\n" % id
127
+ str << "static ID ID_#{id};\n"
128
+ end
129
+ end
130
+
131
+ str << <<END_OF_STRING
132
+
133
+ void QueueManager_selector_id_init()
134
+ {
135
+ #{str_id_init}
136
+ }
137
+
138
+ ID wmq_selector_id(MQLONG selector)
139
+ {
140
+ switch (selector)
141
+ {
142
+ #{str_switch}
143
+ }
144
+ printf("WMQ::wmq_select_text Unknown Selector:%ld\\n",(long)selector);
145
+ return rb_intern("unknown_selector_code");
146
+ }
147
+
148
+ void wmq_selector(ID selector_id, PMQLONG selector_type, PMQLONG selector)
149
+ {
150
+ *selector_type = MQIT_INTEGER;
151
+ END_OF_STRING
152
+ first = true
153
+ str_if = ''
154
+ str_id_init = ''
155
+ # Integer Selectors for Object Attributes
156
+ [['cmqc.h', 'MQIA_'],
157
+ ['cmqcfc.h', 'MQIACF_', ['MQIACF_ERROR_ID',
158
+ 'MQIACF_QUIESCE']],
159
+ ['cmqcfc.h', 'MQIACH_', ['MQIACH_CURRENT_SEQ_NUMBER',
160
+ 'MQIACH_BYTES_RCVD',
161
+ 'MQIACH_BUFFERS_RCVD']],
162
+ ['cmqcfc.h', 'MQIAMO_'],
163
+ ['cmqcfc.h', 'MQIAMO64_', ['MQIAMO64_AVG_Q_TIME',
164
+ 'MQIAMO64_Q_TIME_AVG',
165
+ 'MQIAMO64_Q_TIME_MAX',
166
+ 'MQIAMO64_Q_TIME_MIN']],
167
+ # Integer System Selectors
168
+ # ['cmqbc.h', 'MQIASY_'],
169
+ ].each do |item|
170
+ str << " /* Consteants #{item[1]}* from #{item[0]} */\n"
171
+ GenerateReason.selector_case(path+item[0], item[1], item[2]) do |const|
172
+ str << " if(selector_id == %-32s{ *selector = #{const[0]}; return;}\n" % "ID_#{const[0].gsub(item[1],'').downcase})"
173
+ end
174
+ end
175
+ str << "\n *selector_type = MQIT_STRING;\n\n"
176
+ # Character Selectors for Object Attributes
177
+ [['cmqc.h', 'MQCA_',['MQCA_BASE_OBJECT_NAME']],
178
+ ['cmqcfc.h', 'MQCACF_'],
179
+ ['cmqcfc.h', 'MQCACH_'],
180
+ ['cmqcfc.h', 'MQCAMO_'],
181
+ # Byte String Selectors for Object Attributes
182
+ # ['cmqc.h', 'MQBA_'],
183
+ # ['cmqcfc.h', 'MQBACF_'],
184
+ # Group Selectors for Object Attributes
185
+ # ['cmqcfc.h', 'MQGACF_']
186
+ ].each do |item|
187
+ str << " /* Constants #{item[1]}* from #{item[0]} */\n"
188
+ GenerateReason.selector_case(path+item[0], item[1], item[2]) do |const|
189
+ str << " if(selector_id == %-32s{ *selector = #{const[0]}; return;}\n" % "ID_#{const[0].gsub(item[1],'').downcase})"
190
+ end
191
+ end
192
+
193
+ str << <<END_OF_STRING
194
+
195
+ rb_raise(rb_eArgError, "WMQ::QueueManager#execute [wmq_selector] Unknown selector supplied");
196
+ }
197
+
198
+ END_OF_STRING
199
+ first = true
200
+ str_if = ''
201
+ str_id_init = ''
202
+ GenerateReason.selector_case(path+'cmqcfc.h', 'MQCMD_') do |const|
203
+ if first
204
+ first = false
205
+ str_if << " "
206
+ else
207
+ str_if << " else "
208
+ end
209
+ id = const[0].gsub('MQCMD_','').downcase
210
+ str_id_init << " ID_%-25s = rb_intern(\"#{id}\");\n" % id
211
+ str_if << "if(command_id == %-28s{ command = #{const[0]}; }\n" % "ID_#{const[0].gsub('MQCMD_','').downcase})"
212
+ str << "static ID ID_#{id};\n"
213
+ end
214
+ str << <<END_OF_STRING
215
+
216
+ void QueueManager_command_id_init()
217
+ {
218
+ #{str_id_init}
219
+ }
220
+
221
+ MQLONG wmq_command_lookup(ID command_id)
222
+ {
223
+ MQLONG command = 0;
224
+ #{str_if}
225
+ else
226
+ {
227
+ rb_raise(rb_eArgError, "WMQ::QueueManager#execute [wmq_command_lookup] Unknown command supplied");
228
+ }
229
+
230
+ return command;
231
+ }
232
+ END_OF_STRING
233
+ str
234
+ end
235
+
236
+ def self.generate(path)
237
+ File.open('wmq_reason.c', 'w') {|file| file.write(GenerateReason.wmq_reason(path))}
238
+ puts 'Generated wmq_reason.c'
239
+ end
240
+ end
241
+
242
+ if $0 == __FILE__
243
+ path = ARGV[0] || raise("Mandatory parameter: 'WebSphere MQ Include path' is missing")
244
+ path = path + '/'
245
+ GenerateReason.generate(path)
246
+ end
@@ -0,0 +1,97 @@
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
+ require 'erb'
17
+
18
+ class GenerateStructs
19
+
20
+ @@field_ignore_list = [ 'StrucId', 'Version' , 'StrucLength']
21
+
22
+ # Store path to WebSphere MQ Structures
23
+ def initialize(wmq_includepath, templates_path='.')
24
+ @path = wmq_includepath
25
+ @templates_path = templates_path
26
+ end
27
+
28
+ def extract_struct (filename, struct_name)
29
+ properties_list = []
30
+ line_number = 0
31
+ found = false
32
+ File.open(filename) do |file|
33
+ file.each do |line|
34
+ line_number += 1
35
+ line.rstrip!
36
+ # Skip empty and comment lines
37
+ if line.length > 0 && line !~ /^\s*\/\*/
38
+ if !found
39
+ found = true if line =~ /^\s*struct\s*tag#{struct_name}/
40
+ else
41
+ return(properties_list) if line =~ /^\s*\};/
42
+ match = /\s*(MQ\w+)\s+(\w+);/.match(line)
43
+ if match
44
+ type = match[1]
45
+ element = match[2]
46
+ properties_list.push([type, element])
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ properties_list
53
+ end
54
+
55
+ def rubyize_name(name)
56
+ name.gsub(/::/, '/').
57
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
58
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
59
+ tr("-", "_").
60
+ downcase
61
+ end
62
+
63
+ def self.test_rubyize_name
64
+ test = self.new
65
+ [['a', 'a'],
66
+ ['A', 'a'],
67
+ ['Aa', 'aa'],
68
+ ['AA', 'aa'],
69
+ ['AaA', 'aa_a'],
70
+ ['MyFieldName', 'my_field_name'],
71
+ ['MMyFieldNName', 'm_my_field_n_name'],
72
+ ['ABCdefGHIjKlMnOPQrSTuvwxYz', 'ab_cdef_gh_ij_kl_mn_op_qr_s_tuvwx_yz']
73
+ ].each do |item|
74
+ str = test.rubyize_name(item[0])
75
+ raise("rubyize_name('#{item[0]}') == #{str} != '#{item[1]})") if str != item[1]
76
+ end
77
+ end
78
+
79
+ def generate_structs(erb)
80
+ erb.result(binding)
81
+ end
82
+
83
+ def generate(target_filename = 'wmq_structs.c')
84
+ erb = nil
85
+ File.open(@templates_path+'/wmq_structs.erb') { |file| erb = ERB.new(file.read) }
86
+ File.open(target_filename, 'w') {|file| file.write(generate_structs(erb)) }
87
+ puts "Generated #{target_filename}"
88
+ end
89
+ end
90
+
91
+ # TODO Auto Daisy-Chain Headers: Format, CodedCharSetId, Encoding
92
+ # TODO During Deblock validate that data size left at least matches struct size
93
+ if $0 == __FILE__
94
+ path = ARGV[0] || raise("Mandatory parameter: 'WebSphere MQ Include path' is missing")
95
+ path = path + '/'
96
+ GenerateStructs.new(path, 'generate').generate
97
+ end