metababel 0.1.0 → 1.0.2
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.
- checksums.yaml +4 -4
- data/README.md +13 -1
- data/bin/metababel +392 -165
- data/lib/metababel/bt2_generator_utils.rb +2 -2
- data/lib/metababel/bt2_matching_utils.rb +72 -0
- data/lib/metababel/{bt2_stream_classes_generator.rb → bt2_trace_class_generator.rb} +204 -20
- data/lib/metababel/bt2_values_generator.rb +3 -3
- data/lib/metababel/version.rb +1 -1
- data/lib/metababel.rb +1 -1
- data/template/component.c.erb +15 -49
- data/template/component.h.erb +43 -17
- data/template/downstream.c.erb +51 -20
- data/template/downstream.h.erb +11 -1
- data/template/filter.c.erb +49 -49
- data/template/sink.c.erb +23 -42
- data/template/source.c.erb +33 -20
- data/template/upstream.c.erb +63 -111
- data/template/upstream.h.erb +10 -36
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2300af1bdf99bcc52ff067a635c5272fb7b4f843faad18638b7587ee8f5693b9
|
|
4
|
+
data.tar.gz: 21ad38ee40814173d3fda727a03ad0492c04192f5506d445652417ad5f873bd2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 72b7df6f07c3cf3ca42702b00ce83e7dad7696f69388abe421141686301dd97989b44d68b02e3f61de05be5e867870d2b9968e35fde192f6832a9dd09109cbfa
|
|
7
|
+
data.tar.gz: c244c572f89da35cfdeae2793357ba0a31760f39b594cc0a98a36a6c15c27df21df9c466cc19da573f0fddbc114e958a41f915530e2bb88782f6fced17a862d9
|
data/README.md
CHANGED
|
@@ -57,4 +57,16 @@ stateDiagram-v2
|
|
|
57
57
|
|
|
58
58
|
At finalization we will call the `btx_user_finalization(struct xprof_common_data *common_data)`
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
# Callbacks Registration and Calling order
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
0 register_callback
|
|
64
|
+
1 call_initialize_component # Cannot Push
|
|
65
|
+
2 call_read_params
|
|
66
|
+
3 stream_begin
|
|
67
|
+
4 call_initialize_processing # Can Push
|
|
68
|
+
5 call_callbacks
|
|
69
|
+
5 call_finalize_processing # Can Push
|
|
70
|
+
6 stream_end
|
|
71
|
+
7 call_finalize_component # Cannot push
|
|
72
|
+
```
|
data/bin/metababel
CHANGED
|
@@ -5,19 +5,9 @@ require 'optparse'
|
|
|
5
5
|
require 'erb'
|
|
6
6
|
require 'metababel'
|
|
7
7
|
require 'fileutils'
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
raise "Missing 'name' attr in model #{yaml}" unless yaml[:stream_classes].all? do |d|
|
|
12
|
-
d.key?(:name) && d[:event_classes].all? do |d2|
|
|
13
|
-
d2.key?(:name)
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Event class name must be unique
|
|
18
|
-
events = yaml[:stream_classes].flat_map { |sc| sc[:event_classes] }.map { |e| e[:name] }
|
|
19
|
-
raise "Duplicated 'event' in model #{yaml}" unless events.length == events.uniq.length
|
|
20
|
-
end
|
|
8
|
+
require 'set'
|
|
9
|
+
require 'ostruct'
|
|
10
|
+
require 'abbrev'
|
|
21
11
|
|
|
22
12
|
class Array
|
|
23
13
|
def join_with_prefix(sep)
|
|
@@ -44,19 +34,114 @@ class Hash
|
|
|
44
34
|
end
|
|
45
35
|
end
|
|
46
36
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
class Babeltrace2Gen::BTTraceClass
|
|
38
|
+
def filter_map_event_classes_with_index
|
|
39
|
+
@stream_classes.map.with_index do |s, index_stream_class|
|
|
40
|
+
s.event_classes.filter_map.with_index do |e, index_event_class|
|
|
41
|
+
yield(e, index_stream_class, index_event_class, s.default_clock_class)
|
|
42
|
+
end
|
|
43
|
+
end.flatten(1)
|
|
51
44
|
end
|
|
52
45
|
end
|
|
53
46
|
|
|
54
|
-
|
|
47
|
+
def sanitize(str)
|
|
48
|
+
str.gsub(/[^0-9A-Za-z-]/, '_')
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class BaseDispatch
|
|
55
52
|
def name_sanitized
|
|
56
|
-
name
|
|
53
|
+
sanitize(@name)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# https://ruby-doc.org/3.2.2/Hash.html#class-Hash-label-User-Defined+Hash+Keys
|
|
57
|
+
def ==(other)
|
|
58
|
+
other.is_a?(self.class) and
|
|
59
|
+
instance_variables.all? { |s| instance_variable_get(s) == other.instance_variable_get(s) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
alias eql? ==
|
|
63
|
+
|
|
64
|
+
def hash
|
|
65
|
+
@hash ||=
|
|
66
|
+
instance_variables.reduce(0) { |a, b| a ^ instance_variable_get(b).hash }
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class StaticDispatcher < BaseDispatch
|
|
71
|
+
attr_reader :name, :args, :no_btx_handle
|
|
72
|
+
|
|
73
|
+
def initialize(name, args, no_btx_handle: false)
|
|
74
|
+
@name = name
|
|
75
|
+
@args = args
|
|
76
|
+
@no_btx_handle = no_btx_handle
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class DispatchType < BaseDispatch
|
|
81
|
+
attr_reader :name, :args, :id, :matched_dispatchers
|
|
82
|
+
|
|
83
|
+
def initialize(name, args, id, matched_dispatchers)
|
|
84
|
+
@name = name
|
|
85
|
+
@args = args
|
|
86
|
+
@id = id
|
|
87
|
+
@matched_dispatchers = matched_dispatchers
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class Dispatcher < BaseDispatch
|
|
92
|
+
attr_reader :event_nane, :event, :name,
|
|
93
|
+
:index_stream_class, :index_event_class,
|
|
94
|
+
:default_clock_class,
|
|
95
|
+
:dispatch_types
|
|
96
|
+
|
|
97
|
+
def initialize(event, event_name,
|
|
98
|
+
mode,
|
|
99
|
+
index_stream_class, index_event_class, default_clock_class)
|
|
100
|
+
@event = event
|
|
101
|
+
@event_name = event_name
|
|
102
|
+
@mode = mode
|
|
103
|
+
@index_stream_class = index_stream_class
|
|
104
|
+
@index_event_class = index_event_class
|
|
105
|
+
@default_clock_class = default_clock_class
|
|
106
|
+
@dispatch_types = []
|
|
107
|
+
@name = event.name
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def body_args
|
|
111
|
+
@body_args ||= begin
|
|
112
|
+
arg_variables = {}
|
|
113
|
+
body = Babeltrace2Gen.context(indent: 1) do
|
|
114
|
+
if @mode == 'setter'
|
|
115
|
+
@event.get_setter(event: @event_name, arg_variables: arg_variables)
|
|
116
|
+
elsif @mode == 'getter'
|
|
117
|
+
@event.get_getter(event: @event_name, arg_variables: arg_variables)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
[arg_variables, body]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# We preprent an empty new line from the body as a hack, to correct the indentation
|
|
125
|
+
# Indeeed the <%= body %> will be indented, but we don't don't want it,
|
|
126
|
+
# in the body string is already indented
|
|
127
|
+
# But we clean the white space empty line afterward \o/
|
|
128
|
+
def body
|
|
129
|
+
"\n" + body_args[1]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def args
|
|
133
|
+
evt_args = []
|
|
134
|
+
evt_args += [GeneratedArg.new('int64_t', '_timestamp')] if @default_clock_class
|
|
135
|
+
evt_args += body_args[0].fetch('outputs', [])
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def args_to_free
|
|
139
|
+
body_args[0].fetch('outputs_allocated', [])
|
|
57
140
|
end
|
|
58
141
|
end
|
|
59
142
|
|
|
143
|
+
GeneratedArg = Struct.new(:type, :name)
|
|
144
|
+
|
|
60
145
|
def erb_render_and_save(vars,
|
|
61
146
|
basename, out_folder, out_name: nil, prefix: 'btx_')
|
|
62
147
|
template = File.read(File.join(__dir__, "../template/#{basename}.erb"))
|
|
@@ -65,202 +150,344 @@ def erb_render_and_save(vars,
|
|
|
65
150
|
# The regex remove the lines who are not indented
|
|
66
151
|
# Maybe related to `https://github.com/ruby/erb/issues/24`
|
|
67
152
|
str = ERB.new(template, trim_mode: '<>').result_with_hash(vars).gsub(/^ +$\n/, '')
|
|
68
|
-
File.
|
|
69
|
-
f.write(str)
|
|
70
|
-
end
|
|
153
|
+
File.write(File.join(out_folder, "#{prefix}#{out_name || basename}"), str)
|
|
71
154
|
end
|
|
72
155
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
s.event_classes.map.with_index do |e, index_event_class|
|
|
77
|
-
yield(e, index_stream_class, index_event_class, s.default_clock_class)
|
|
78
|
-
end
|
|
79
|
-
end.flatten
|
|
80
|
-
end
|
|
81
|
-
end
|
|
156
|
+
def parse_argv
|
|
157
|
+
# Display help if no arguments.
|
|
158
|
+
ARGV << '-h' if ARGV.empty?
|
|
82
159
|
|
|
83
|
-
|
|
84
|
-
|
|
160
|
+
options = {}
|
|
161
|
+
|
|
162
|
+
options[:disable_callbaks] = ['on_downstream'].to_set
|
|
163
|
+
|
|
164
|
+
OptionParser.new do |opts|
|
|
165
|
+
opts.banner = 'Usage: example.rb [options]'
|
|
85
166
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
# But we clean the white space empty line afterward \o/
|
|
90
|
-
def wrote_event_dispatchers(folder, t)
|
|
91
|
-
event_name = 'event'
|
|
92
|
-
event_class_dispatchers = t.map_event_classes_with_index do |e, index_stream_class, index_event_class, default_clock_class|
|
|
93
|
-
arg_variables = {}
|
|
94
|
-
body = Babeltrace2Gen.context(indent: 1) do
|
|
95
|
-
e.get_getter(event: event_name, arg_variables: arg_variables)
|
|
167
|
+
opts.on('-h', '--help', 'Prints this help') do
|
|
168
|
+
puts opts
|
|
169
|
+
exit
|
|
96
170
|
end
|
|
97
|
-
EventClassInfo.new(e.name, arg_variables.fetch('outputs', []), body, index_stream_class, index_event_class, default_clock_class,
|
|
98
|
-
arg_variables.fetch('outputs_allocated', []))
|
|
99
|
-
end
|
|
100
171
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
body = Babeltrace2Gen.context(indent: 1) do
|
|
106
|
-
s.get_getter(event: event_name, arg_variables: arg_variables)
|
|
107
|
-
end
|
|
172
|
+
opts.on('-v', '--version', 'Prints this help') do
|
|
173
|
+
puts "Ruby: #{RUBY_VERSION}"
|
|
174
|
+
puts "Metababel: #{Metababel::VERSION}"
|
|
175
|
+
exit
|
|
108
176
|
end
|
|
109
|
-
StreamClassInfo.new(s.name, arg_variables.fetch('outputs', []), body, s.default_clock_class)
|
|
110
|
-
end
|
|
111
177
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
178
|
+
opts.on('-t', '--component TYPE',
|
|
179
|
+
'[Mandatory] Node within a trace processing graph [one of: SINK, SOURCE, FILTER].') do |p|
|
|
180
|
+
l = %w[SOURCE FILTER SINK]
|
|
181
|
+
h = Abbrev.abbrev(l)
|
|
182
|
+
raise "Invalid component type, should be #{l} (case insentitive)" unless h.include?(p.upcase)
|
|
115
183
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
184
|
+
options[:component_type] = h[p.upcase]
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
opts.on('-u', '--upstreams PATH', Array, '[Mandatory] Path to the bt2 YAML files for the upstream model.') do |p|
|
|
188
|
+
options[:upstreams] = p
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
opts.on('-d', '--downstream PATH', '[Optional] Path to the bt2 YAML file for the downstream model.') do |p|
|
|
192
|
+
options[:downstream] = p
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
opts.on('-p', '--plugin-name PATH', '[Optional] Name of the bt2 plugin created.') do |p|
|
|
196
|
+
options[:plugin_name] = p
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
opts.on('-c', '--component-name PATH', '[Optional] Name of the bt2 componant created.') do |p|
|
|
200
|
+
options[:component_name] = p
|
|
201
|
+
end
|
|
119
202
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
downstream_events = t.map_event_classes_with_index do |e, index_stream_class, index_event_class, default_clock_class|
|
|
123
|
-
arg_variables = {}
|
|
124
|
-
body = Babeltrace2Gen.context(indent: 1) do
|
|
125
|
-
e.get_setter(event: event_name, arg_variables: arg_variables)
|
|
203
|
+
opts.on('--params PATH', '[Optional] Paht to the bt2 YAML params definition.') do |p|
|
|
204
|
+
options[:params] = p
|
|
126
205
|
end
|
|
127
|
-
|
|
128
|
-
|
|
206
|
+
|
|
207
|
+
opts.on('-m', '--matching PATH', '[Optional] Path to bt2 YAML matching-callbacks definitions.') do |p|
|
|
208
|
+
options[:matching] = p
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
opts.on('-o', '--output FOLDER', '[Optional] Output folder path.') do |p|
|
|
212
|
+
options[:folder] = p
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
opts.on('-i', '--usr-data-header NAME', '[Optional] User datatypes definitions.') do |p|
|
|
216
|
+
options[:usr_data_header] = p
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
opts.on('--enable-callbacks NAME', Array, '[Optional] Enable some callbacks type') do |p|
|
|
220
|
+
options[:disable_callbaks] -= p.to_set
|
|
221
|
+
end
|
|
222
|
+
end.parse!
|
|
223
|
+
|
|
224
|
+
raise OptionParser::MissingArgument if options[:component_type].nil?
|
|
225
|
+
|
|
226
|
+
options[:plugin_name] ||= "metababel_#{options[:component_type].downcase}"
|
|
227
|
+
options[:component_name] ||= 'btx'
|
|
228
|
+
|
|
229
|
+
options
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def get_dispatch_type(em, default_clock_class, context)
|
|
233
|
+
|
|
234
|
+
begin
|
|
235
|
+
dispatchers = em.domain ? OpenStruct.new(context).instance_eval(em.domain) : context['all']
|
|
236
|
+
rescue StandardError
|
|
237
|
+
raise "Please ensure the domain '#{em.domain}' uses valid ruby expressions and all set_id have been previously defined. Current defined set_ids: #{context.keys}."
|
|
129
238
|
end
|
|
130
239
|
|
|
131
|
-
|
|
132
|
-
|
|
240
|
+
raise "Nil or empty event set for '#{em.set_id}'." unless dispatchers.is_a?(Set)
|
|
241
|
+
|
|
242
|
+
matched_dispatchers, signatures = dispatchers.filter_map do |dispatcher|
|
|
243
|
+
extracted_args = dispatcher.event.match?(em)
|
|
244
|
+
[dispatcher, extracted_args] if extracted_args
|
|
245
|
+
end.transpose
|
|
246
|
+
|
|
247
|
+
if !matched_dispatchers || matched_dispatchers.empty?
|
|
248
|
+
raise "No event matched '#{em.set_id}', at least one matching event required."
|
|
133
249
|
end
|
|
134
250
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
251
|
+
# Verify the uniqueness of signatures.
|
|
252
|
+
# Note that `s.type` takes into account the `cast_type`
|
|
253
|
+
# (see TestMatchingConflictingSignatures for more details)
|
|
254
|
+
unique_signatures = signatures.uniq
|
|
255
|
+
unless unique_signatures.size == 1
|
|
256
|
+
signatures_str = unique_signatures.map { |s| "(#{s.map(&:type).join(', ')})" }.join(', ')
|
|
257
|
+
raise "Conflicting signatures for '#{em.set_id}', found #{unique_signatures.size} signatures, only one allowed: '#{signatures_str}'"
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Modify the dispatcher to add the new dispatchType
|
|
261
|
+
name = em.set_id
|
|
262
|
+
dispatch_type_args = []
|
|
263
|
+
dispatch_type_args += [GeneratedArg.new('int64_t', '_timestamp')] if default_clock_class
|
|
264
|
+
dispatch_type_args += [GeneratedArg.new('const char *', '_event_class_name')]
|
|
265
|
+
dispatch_type_args += signatures.pop
|
|
266
|
+
|
|
267
|
+
dispatch_type = DispatchType.new(
|
|
268
|
+
name, dispatch_type_args, "matching_#{sanitize(name)}", matched_dispatchers
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
# Update context for further events filtering.
|
|
272
|
+
context[dispatch_type.name] = dispatch_type.matched_dispatchers.to_set
|
|
139
273
|
|
|
140
|
-
|
|
141
|
-
|
|
274
|
+
# Exclude unnecessary rendering.
|
|
275
|
+
return false unless em.register
|
|
276
|
+
|
|
277
|
+
matched_dispatchers.each { |dispatcher| dispatcher.dispatch_types << dispatch_type }
|
|
278
|
+
|
|
279
|
+
dispatch_type
|
|
142
280
|
end
|
|
143
281
|
|
|
144
|
-
def
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
GeneratedArg.new('btx_params_t *', 'usr_params')])]
|
|
152
|
-
|
|
153
|
-
if options[:component_type] == 'SOURCE'
|
|
154
|
-
component_dispatchers << EventClassInfo.new('push_usr_messages',
|
|
155
|
-
[GeneratedArg.new('void *', 'usr_data'),
|
|
156
|
-
GeneratedArg.new('btx_source_status_t*', 'status')])
|
|
157
|
-
end
|
|
282
|
+
def validate_model(yaml)
|
|
283
|
+
# Stream and event classes must have a 'name' as minimum requirement.
|
|
284
|
+
raise "Missing 'name' attr in model #{yaml}" unless yaml[:stream_classes].all? do |d|
|
|
285
|
+
d.key?(:name) && d[:event_classes].all? do |d2|
|
|
286
|
+
d2.key?(:name)
|
|
287
|
+
end
|
|
288
|
+
end
|
|
158
289
|
|
|
159
|
-
|
|
160
|
-
|
|
290
|
+
# Event class name must be unique
|
|
291
|
+
events = yaml[:stream_classes].flat_map { |sc| sc[:event_classes] }.map { |e| e[:name] }
|
|
292
|
+
raise "Duplicated 'event' in model #{yaml}" unless events.length == events.uniq.length
|
|
161
293
|
|
|
162
|
-
|
|
163
|
-
erb_render_and_save(d2.update(d).update(options: options), 'component.c', folder)
|
|
294
|
+
yaml
|
|
164
295
|
end
|
|
165
296
|
|
|
166
|
-
|
|
167
|
-
|
|
297
|
+
def load_models(models)
|
|
298
|
+
yaml = [models].flatten
|
|
299
|
+
.map { |f| YAML.load_file(f) }
|
|
300
|
+
.reduce({}) { |s, y| s.deep_merge(y) { |_key, old, new| old + new } }
|
|
301
|
+
validate_model(yaml)
|
|
302
|
+
end
|
|
168
303
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
opts.banner = 'Usage: example.rb [options]'
|
|
304
|
+
class ContextBuilder
|
|
305
|
+
attr_accessor :cli_options
|
|
172
306
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
exit
|
|
307
|
+
def initialize
|
|
308
|
+
@cli_options = parse_argv
|
|
176
309
|
end
|
|
177
310
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
311
|
+
def base_folder
|
|
312
|
+
@base_folder ||= begin
|
|
313
|
+
f = @cli_options[:folder] || "#{@cli_options[:component_type]}.#{@cli_options[:plugin_name]}.#{@cli_options[:component_name]}"
|
|
314
|
+
FileUtils.mkdir_p(f)
|
|
315
|
+
f
|
|
316
|
+
end
|
|
182
317
|
end
|
|
183
318
|
|
|
184
|
-
|
|
185
|
-
|
|
319
|
+
def folder
|
|
320
|
+
@folder ||= begin
|
|
321
|
+
f = "#{base_folder}/metababel"
|
|
322
|
+
FileUtils.mkdir_p(f)
|
|
323
|
+
f
|
|
324
|
+
end
|
|
186
325
|
end
|
|
187
326
|
|
|
188
|
-
|
|
189
|
-
options
|
|
327
|
+
def options
|
|
328
|
+
{ options: @cli_options }
|
|
190
329
|
end
|
|
191
330
|
|
|
192
|
-
|
|
193
|
-
|
|
331
|
+
def params
|
|
332
|
+
@params ||= if @cli_options.key?(:params)
|
|
333
|
+
y = YAML.load_file(@cli_options[:params])
|
|
334
|
+
c = Babeltrace2Gen::BTValueCLass.from_h(y)
|
|
335
|
+
body = Babeltrace2Gen.context(indent: 1) do
|
|
336
|
+
c.get('_usr_params', '_params')
|
|
337
|
+
end
|
|
338
|
+
{ params_declaration: c.get_struct_definition('_params'),
|
|
339
|
+
params_definition: body }
|
|
340
|
+
else
|
|
341
|
+
{ params_declaration: nil, params_definition: nil }
|
|
342
|
+
end
|
|
194
343
|
end
|
|
195
344
|
|
|
196
|
-
|
|
197
|
-
|
|
345
|
+
def trace_matcher
|
|
346
|
+
@trace_matcher ||= if @cli_options.key?(:matching)
|
|
347
|
+
data = YAML.load_file(@cli_options[:matching])
|
|
348
|
+
data[:match] = true
|
|
349
|
+
Babeltrace2Gen::BTTraceClass.from_h(nil, data)
|
|
350
|
+
else
|
|
351
|
+
Babeltrace2Gen::BTTraceClass.new(parent: nil, stream_classes: [])
|
|
352
|
+
end
|
|
198
353
|
end
|
|
199
354
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
355
|
+
def callback_types
|
|
356
|
+
@callback_types ||= begin
|
|
357
|
+
callback_types = ['generic']
|
|
358
|
+
if @cli_options.key?(:matching)
|
|
359
|
+
event_classes = trace_matcher.stream_classes.map(&:event_classes).flatten(1).filter do |em|
|
|
360
|
+
raise "Key ':set_id' required for matching events." unless em.set_id
|
|
203
361
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
362
|
+
em.register
|
|
363
|
+
end
|
|
364
|
+
callback_types += event_classes.map { |em| "matching_#{sanitize(em.set_id)}" }
|
|
365
|
+
end
|
|
207
366
|
|
|
208
|
-
|
|
209
|
-
|
|
367
|
+
static_callbacks = [StaticDispatcher.new('initialize_component',
|
|
368
|
+
[GeneratedArg.new('void **', 'usr_data_p')],
|
|
369
|
+
no_btx_handle: true),
|
|
370
|
+
StaticDispatcher.new('finalize_component',
|
|
371
|
+
[GeneratedArg.new('void *', 'usr_data')],
|
|
372
|
+
no_btx_handle: true),
|
|
373
|
+
StaticDispatcher.new('read_params',
|
|
374
|
+
[GeneratedArg.new('void *', 'usr_data'),
|
|
375
|
+
GeneratedArg.new('btx_params_t *', 'usr_params')],
|
|
376
|
+
no_btx_handle: true)]
|
|
377
|
+
# Usefull to push message
|
|
378
|
+
if %w[SOURCE FILTER].include?(@cli_options[:component_type])
|
|
379
|
+
static_callbacks += [StaticDispatcher.new('initialize_processing',
|
|
380
|
+
[GeneratedArg.new('void *', 'usr_data_p')]),
|
|
381
|
+
StaticDispatcher.new('finalize_processing',
|
|
382
|
+
[GeneratedArg.new('void *', 'usr_data')])]
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
if %w[SOURCE].include?(@cli_options[:component_type])
|
|
386
|
+
static_callbacks << StaticDispatcher.new('push_usr_messages',
|
|
387
|
+
[GeneratedArg.new('void *', 'usr_data'),
|
|
388
|
+
GeneratedArg.new('btx_source_status_t*', 'status')])
|
|
389
|
+
|
|
390
|
+
end
|
|
391
|
+
{ callback_types: callback_types,
|
|
392
|
+
static_callback_types: static_callbacks }
|
|
393
|
+
end
|
|
210
394
|
end
|
|
211
395
|
|
|
212
|
-
|
|
213
|
-
|
|
396
|
+
def downstream
|
|
397
|
+
@downstream ||= begin
|
|
398
|
+
raise 'Missing downstream model' unless @cli_options[:downstream]
|
|
399
|
+
|
|
400
|
+
y = load_models(@cli_options[:downstream])
|
|
401
|
+
t = Babeltrace2Gen::BTTraceClass.from_h(nil, y)
|
|
402
|
+
|
|
403
|
+
event_name = '_event'
|
|
404
|
+
downstream_events = t.filter_map_event_classes_with_index do |e, index_stream_class, index_event_class, default_clock_class|
|
|
405
|
+
Dispatcher.new(e, event_name, 'setter', index_stream_class, index_event_class, default_clock_class)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
body_declarator_classes = "\n" + Babeltrace2Gen.context(indent: 1) do
|
|
409
|
+
t.get_declarator(variable: '_trace_class', self_component: '_self_component')
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
{ body_declarator_classes: body_declarator_classes,
|
|
413
|
+
downstream_events: downstream_events,
|
|
414
|
+
stream_classes: t.stream_classes,
|
|
415
|
+
event_name: event_name }
|
|
416
|
+
end
|
|
214
417
|
end
|
|
215
|
-
end.parse!
|
|
216
418
|
|
|
217
|
-
|
|
419
|
+
def upstream
|
|
420
|
+
@upstream ||= begin
|
|
421
|
+
raise 'Missing upstreams models' unless @cli_options[:upstreams]
|
|
218
422
|
|
|
219
|
-
|
|
220
|
-
|
|
423
|
+
y = load_models(@cli_options[:upstreams])
|
|
424
|
+
t = Babeltrace2Gen::BTTraceClass.from_h(nil, y)
|
|
221
425
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
426
|
+
event_name = '_event'
|
|
427
|
+
dispatchers, automatic_dispatch_types = t.filter_map_event_classes_with_index do |e, index_stream_class, index_event_class, default_clock_class|
|
|
428
|
+
dispatcher = Dispatcher.new(e, event_name, 'getter', index_stream_class, index_event_class,
|
|
429
|
+
default_clock_class)
|
|
430
|
+
dispatch_type = DispatchType.new(e.name, dispatcher.args, 'generic', [dispatcher])
|
|
431
|
+
dispatcher.dispatch_types << dispatch_type
|
|
432
|
+
|
|
433
|
+
[dispatcher, dispatch_type]
|
|
434
|
+
end.transpose
|
|
435
|
+
|
|
436
|
+
context = { 'all' => dispatchers.to_set }
|
|
437
|
+
matching_dispatch_types = trace_matcher.filter_map_event_classes_with_index do |em, _, _, default_clock_class|
|
|
438
|
+
# We mutate context across iterations.
|
|
439
|
+
get_dispatch_type(em, default_clock_class, context)
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
{ dispatchers: dispatchers,
|
|
443
|
+
dispatch_types: automatic_dispatch_types + matching_dispatch_types,
|
|
444
|
+
event_name: event_name }
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def get_context(list_symbols)
|
|
449
|
+
d = {}
|
|
450
|
+
d.update(options) if list_symbols.include?('options')
|
|
451
|
+
d.update(params) if list_symbols.include?('params')
|
|
452
|
+
d.update(callback_types) if list_symbols.include?('callback_types')
|
|
453
|
+
d.update(static_callback_types) if list_symbols.include?('static_callback_types')
|
|
454
|
+
d.update(downstream) if list_symbols.include?('downstream')
|
|
455
|
+
d.update(upstream) if list_symbols.include?('upstream')
|
|
456
|
+
d
|
|
236
457
|
end
|
|
237
|
-
d[:params_declaration] = c.get_struct_definition('params')
|
|
238
|
-
d[:params_definition] = body
|
|
239
|
-
else
|
|
240
|
-
d[:params_declaration] = 'char _dummy;'
|
|
241
458
|
end
|
|
242
459
|
|
|
243
|
-
|
|
244
|
-
erb_render_and_save(
|
|
460
|
+
def wrote_upstream(cb)
|
|
461
|
+
erb_render_and_save(cb.get_context(%w[upstream]), 'upstream.h', cb.folder)
|
|
462
|
+
erb_render_and_save(cb.get_context(%w[upstream]), 'upstream.c', cb.folder)
|
|
463
|
+
end
|
|
245
464
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
465
|
+
def wrote_downstream(cb)
|
|
466
|
+
erb_render_and_save(cb.get_context(%w[downstream options]), 'downstream.h', cb.folder)
|
|
467
|
+
erb_render_and_save(cb.get_context(%w[downstream options]), 'downstream.c', cb.folder)
|
|
468
|
+
end
|
|
249
469
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
470
|
+
def wrote_component(cb)
|
|
471
|
+
erb_render_and_save(cb.get_context(%w[options params callback_types]), 'component.h',
|
|
472
|
+
cb.folder)
|
|
473
|
+
erb_render_and_save(cb.get_context(%w[options params callback_types]), 'component.c',
|
|
474
|
+
cb.folder)
|
|
254
475
|
end
|
|
255
476
|
|
|
256
|
-
|
|
257
|
-
|
|
477
|
+
def wrote_main(cb)
|
|
478
|
+
erb_render_and_save(cb.get_context(%w[params options]), "#{cb.cli_options[:component_type].downcase}.c",
|
|
479
|
+
cb.base_folder, out_name: 'main.c')
|
|
480
|
+
end
|
|
258
481
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
end
|
|
263
|
-
validate_model(y)
|
|
264
|
-
t = Babeltrace2Gen::BTTraceClass.from_h(nil, y)
|
|
265
|
-
wrote_event_dispatchers(folder, t)
|
|
482
|
+
def wrote_header(cb)
|
|
483
|
+
erb_render_and_save(cb.get_context(%w[options]), 'metababel.h',
|
|
484
|
+
cb.folder, prefix: '')
|
|
266
485
|
end
|
|
486
|
+
|
|
487
|
+
# Babeltrace can be extended by plugins, which provide one or more component classes.
|
|
488
|
+
context_builder = ContextBuilder.new
|
|
489
|
+
wrote_header(context_builder)
|
|
490
|
+
wrote_main(context_builder)
|
|
491
|
+
wrote_component(context_builder)
|
|
492
|
+
wrote_downstream(context_builder) if %w[SOURCE FILTER].include?(context_builder.cli_options[:component_type])
|
|
493
|
+
wrote_upstream(context_builder) if %w[FILTER SINK].include?(context_builder.cli_options[:component_type])
|