metababel 0.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.
- checksums.yaml +7 -0
- data/README.md +60 -0
- data/bin/metababel +233 -0
- data/lib/metababel/bt2_generator_utils.rb +38 -0
- data/lib/metababel/bt2_stream_classes_generator.rb +716 -0
- data/lib/metababel/bt2_values_generator.rb +132 -0
- data/lib/metababel/version.rb +3 -0
- data/lib/metababel.rb +4 -0
- data/template/component.c.erb +69 -0
- data/template/component.h.erb +160 -0
- data/template/downstream.c.erb +119 -0
- data/template/downstream.h.erb +34 -0
- data/template/filter.c.erb +400 -0
- data/template/metababel.h.erb +7 -0
- data/template/sink.c.erb +166 -0
- data/template/source.c.erb +200 -0
- data/template/upstream.c.erb +47 -0
- data/template/upstream.h.erb +22 -0
- metadata +62 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 579d0e3d53d8a2cc77b458621e278d01e98cc5a9b736f9615671c35d5a7ec881
|
|
4
|
+
data.tar.gz: dede291f1c00394ed257784551fc3c2cffbcd1c9d5404fdb305f272d10c4bb41
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8da116eba6fc46b84324f10ace6a46aad4b8144d8ec4eadbbfe80c380abf4cd2cd7deaafcc70e3ac86ce3e6ce4971e354029ff93b7885f87e19cb455a6d22a37
|
|
7
|
+
data.tar.gz: 585f64b8cb02ab0255d131a94f4ecda9fa24dcd7ecaecc7d1ffa9825004671dd550054fbdd638ac3a0fe597fbf1881f1b78cc6ab4cea2c00e75a9b009f6b55ea
|
data/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<img width="384" alt="METABABEL" src="https://user-images.githubusercontent.com/6524907/217338770-ab69a6c8-f0fa-4e00-9b8f-bf5d2192d0bd.png">
|
|
2
|
+
|
|
3
|
+
# What symbols to provide?
|
|
4
|
+
|
|
5
|
+
## Filter & Sink
|
|
6
|
+
|
|
7
|
+
Link with a object file who export the symbol `btx_register_usr_callbacks(void *)`.
|
|
8
|
+
|
|
9
|
+
The implementation of `btx_register_usr_callbacks` should conssist of calls to `btx_register_callbacks_#{stream_class_name}_#{event_class_name}(btx_handle, &callbacks)`.
|
|
10
|
+
|
|
11
|
+
## Source:
|
|
12
|
+
|
|
13
|
+
Link with a object file who export the symbol `btx_push_usr_messages(struct xprof_common_data *common_data)`.
|
|
14
|
+
|
|
15
|
+
# Function Provided
|
|
16
|
+
|
|
17
|
+
## Source & Filter
|
|
18
|
+
|
|
19
|
+
In the callbacks, and in the `btx_push_usr_messages`, you have access to `btx_push_message_{stream_class_name}_#{event_class_name}(struct xprof_common_data *common_data, ...)`.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Source Description
|
|
23
|
+
|
|
24
|
+
## State Machine
|
|
25
|
+
|
|
26
|
+
```mermaid
|
|
27
|
+
stateDiagram-v2
|
|
28
|
+
[*] --> BTX_SOURCE_STATE_INITIALIZING
|
|
29
|
+
BTX_SOURCE_STATE_INITIALIZING --> BTX_SOURCE_STATE_PROCESSING
|
|
30
|
+
BTX_SOURCE_STATE_PROCESSING --> BTX_SOURCE_STATE_FINALIZING
|
|
31
|
+
BTX_SOURCE_STATE_FINALIZING --> BTX_FILTER_STATE_FINISHED
|
|
32
|
+
BTX_FILTER_STATE_FINISHED --> [*]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
# Filter Description
|
|
36
|
+
|
|
37
|
+
## State Machine
|
|
38
|
+
|
|
39
|
+
```mermaid
|
|
40
|
+
stateDiagram-v2
|
|
41
|
+
[*] --> BTX_SOURCE_STATE_INITIALIZING
|
|
42
|
+
BTX_SOURCE_STATE_INITIALIZING --> BTX_FILTER_PROCESSING
|
|
43
|
+
state BTX_FILTER_PROCESSING {
|
|
44
|
+
[*] --> BTX_FILTER_PROCESSING_STATE_READING
|
|
45
|
+
[*] --> BTX_FILTER_PROCESSING_STATE_SENDING
|
|
46
|
+
BTX_FILTER_PROCESSING_STATE_SENDING --> BTX_FILTER_PROCESSING_STATE_READING
|
|
47
|
+
BTX_FILTER_PROCESSING_STATE_READING --> BTX_FILTER_PROCESSING_STATE_SENDING
|
|
48
|
+
BTX_FILTER_PROCESSING_STATE_READING --> BTX_FILTER_PROCESSING_STATE_FINISHED
|
|
49
|
+
BTX_FILTER_PROCESSING_STATE_FINISHED --> [*]
|
|
50
|
+
}
|
|
51
|
+
BTX_FILTER_PROCESSING --> BTX_FILTER_STATE_FINALIZING
|
|
52
|
+
BTX_FILTER_STATE_FINALIZING --> BTX_FILTER_STATE_FINISHED
|
|
53
|
+
BTX_FILTER_STATE_FINISHED --> [*]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
# Sink Description
|
|
57
|
+
|
|
58
|
+
At finalization we will call the `btx_user_finalization(struct xprof_common_data *common_data)`
|
|
59
|
+
|
|
60
|
+
|
data/bin/metababel
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
require 'erb'
|
|
6
|
+
require 'metababel'
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
|
|
9
|
+
def validate_model(yaml)
|
|
10
|
+
raise "Invalid Model #{yaml}" unless yaml[:stream_classes].all? do |d|
|
|
11
|
+
d.key?(:event_common_context_field_class) || d[:event_classes].all? do |d2|
|
|
12
|
+
d2.key?(:payload_field_class)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Hash
|
|
18
|
+
# Copy pasted from rails (https://apidock.com/rails/Hash/deep_merge%21)
|
|
19
|
+
def deep_merge!(other_hash, &block)
|
|
20
|
+
merge!(other_hash) do |key, this_val, other_val|
|
|
21
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
|
22
|
+
this_val.deep_merge(other_val, &block)
|
|
23
|
+
elsif block_given?
|
|
24
|
+
block.call(key, this_val, other_val)
|
|
25
|
+
else
|
|
26
|
+
other_val
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def deep_merge(other_hash, &block)
|
|
32
|
+
dup.deep_merge!(other_hash, &block)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
EventInfo = Struct.new(:name, :args, :body, :index_stream_class, :index_event_class) do
|
|
37
|
+
def name_sanitized
|
|
38
|
+
name.gsub(/[^0-9A-Za-z-]/, '_')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def erb_render_and_save(vars,
|
|
43
|
+
basename, out_folder, out_name: nil, prefix: 'btx_')
|
|
44
|
+
template = File.read(File.join(__dir__, "../template/#{basename}.erb"))
|
|
45
|
+
# We need to trim line who contain only with space, because we indent our erb block <% %>
|
|
46
|
+
# The trim_mode remove line only when it's start with the erb block
|
|
47
|
+
# The regex remove the lines who are not indented
|
|
48
|
+
# Maybe related to `https://github.com/ruby/erb/issues/24`
|
|
49
|
+
str = ERB.new(template, trim_mode: '<>').result_with_hash(vars).gsub(/^ +$\n/, '')
|
|
50
|
+
File.open(File.join(out_folder, "#{prefix}#{out_name || basename}"), 'w') do |f|
|
|
51
|
+
f.write(str)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Babeltrace2Gen::BTTraceClass
|
|
56
|
+
def map_event_classes_with_index
|
|
57
|
+
@stream_classes.map.with_index do |s, index_stream_class|
|
|
58
|
+
s.event_classes.map.with_index do |e, index_event_class|
|
|
59
|
+
yield(e, index_stream_class, index_event_class)
|
|
60
|
+
end
|
|
61
|
+
end.flatten
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class GeneratedArg < Struct.new(:type, :name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# We preprent an empty new line from the body as a hack, to correct the indentation
|
|
69
|
+
# Indeeed the <%= body %> will be indented, but we don't don't want it,
|
|
70
|
+
# in the body string is already indented
|
|
71
|
+
# But we clean the white space empty line afterward \o/
|
|
72
|
+
def wrote_event_dispatchers(folder, t)
|
|
73
|
+
event_name = 'event'
|
|
74
|
+
event_dispatchers = t.map_event_classes_with_index do |e, index_stream_class, index_event_class|
|
|
75
|
+
arg_variables = []
|
|
76
|
+
body = Babeltrace2Gen.context(indent: 1) do
|
|
77
|
+
e.get_getter(event: event_name, arg_variables: arg_variables)
|
|
78
|
+
end
|
|
79
|
+
EventInfo.new(e.name, arg_variables, "\n" + body, index_stream_class, index_event_class)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
d = { event_dispatchers: event_dispatchers,
|
|
83
|
+
event_name: event_name }
|
|
84
|
+
|
|
85
|
+
erb_render_and_save(d, 'upstream.h', folder)
|
|
86
|
+
erb_render_and_save(d, 'upstream.c', folder)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def wrote_creates(folder, t)
|
|
90
|
+
event_name = 'event'
|
|
91
|
+
downstream_events = t.map_event_classes_with_index do |e, index_stream_class, index_event_class|
|
|
92
|
+
arg_variables = []
|
|
93
|
+
body = Babeltrace2Gen.context(indent: 1) do
|
|
94
|
+
e.get_setter(event: event_name, arg_variables: arg_variables)
|
|
95
|
+
end
|
|
96
|
+
EventInfo.new(e.name, arg_variables, "\n" + body, index_stream_class, index_event_class)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
body_declarator_classes = "\n" + Babeltrace2Gen.context(indent: 1) do
|
|
100
|
+
t.get_declarator(variable: 'trace_class')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
d = { body_declarator_classes: body_declarator_classes,
|
|
104
|
+
downstream_events: downstream_events,
|
|
105
|
+
stream_classes: t.stream_classes,
|
|
106
|
+
event_name: event_name }
|
|
107
|
+
|
|
108
|
+
erb_render_and_save(d, 'downstream.h', folder)
|
|
109
|
+
erb_render_and_save(d, 'downstream.c', folder)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def wrote_component(options, d, folder)
|
|
113
|
+
|
|
114
|
+
component_dispatchers = [EventInfo.new('initialize_usr_data',
|
|
115
|
+
[GeneratedArg.new('void **', 'usr_data_p')]),
|
|
116
|
+
EventInfo.new('finalize_usr_data',
|
|
117
|
+
[GeneratedArg.new('void *', 'usr_data')]),
|
|
118
|
+
EventInfo.new('read_params',
|
|
119
|
+
[GeneratedArg.new('void *', 'usr_data'),
|
|
120
|
+
GeneratedArg.new('btx_params_t *', 'usr_params')])
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
if options[:component_type] == "SOURCE"
|
|
124
|
+
component_dispatchers << EventInfo.new('push_usr_messages',
|
|
125
|
+
[GeneratedArg.new('void *', 'usr_data'),
|
|
126
|
+
GeneratedArg.new('btx_source_status_t*', 'status') ])
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
d2 = { component_dispatchers: component_dispatchers,
|
|
130
|
+
event_name: 'dummy_event' }
|
|
131
|
+
|
|
132
|
+
erb_render_and_save(d2.update(d).update(:options => options), 'component.h', folder)
|
|
133
|
+
erb_render_and_save(d2.update(d).update(:options => options), 'component.c', folder)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
options = { plugin_name: 'metababel',
|
|
137
|
+
component_name: 'btx' }
|
|
138
|
+
|
|
139
|
+
# Display help if no arguments.
|
|
140
|
+
ARGV << '-h' if ARGV.empty?
|
|
141
|
+
|
|
142
|
+
OptionParser.new do |opts|
|
|
143
|
+
opts.banner = 'Usage: example.rb [options]'
|
|
144
|
+
|
|
145
|
+
opts.on('-h', '--help', 'Prints this help') do
|
|
146
|
+
puts opts
|
|
147
|
+
exit
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
opts.on('-v', '--version', 'Prints this help') do
|
|
151
|
+
puts "Ruby: #{RUBY_VERSION}"
|
|
152
|
+
puts "Metababel: #{Metababel::VERSION}"
|
|
153
|
+
exit
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
opts.on('-t', '--component TYPE', '[Mandatory] Node within a trace processing graph.') do |p|
|
|
157
|
+
options[:component_type] = p
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
opts.on('-u', '--upstreams PATH', Array, '[Mandatory] Path to the bt2 yaml file.') do |p|
|
|
161
|
+
options[:upstreams] = p
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
opts.on('-d', '--downstream PATH', '[Optional] Path to the bt2 yaml file.') do |p|
|
|
165
|
+
options[:downstream] = p
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
opts.on('-p', '--plugin-name PATH', '[Optional] Name of the bt2 plugin created.') do |p|
|
|
169
|
+
options[:plugin_name] = p
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
opts.on('-c', '--component-name PATH', '[Optional] Name of the bt2 componant created.') do |p|
|
|
173
|
+
options[:component_name] = p
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
opts.on('--params PATH', '[Optional] Name of YAML params definition.') do |p|
|
|
177
|
+
options[:params] = p
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
opts.on('-o', '--output FOLDER', '[Optional] Output folder path.') do |p|
|
|
181
|
+
options[:folder] = p
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
opts.on('-i', '--usr-data-header NAME', '[Optional] User datatypes definitions.') do |p|
|
|
185
|
+
options[:usr_data_header] = p
|
|
186
|
+
end
|
|
187
|
+
end.parse!
|
|
188
|
+
|
|
189
|
+
raise OptionParser::MissingArgument if options[:component_type].nil?
|
|
190
|
+
|
|
191
|
+
# Babeltrace can be extended by plugins, which provide one or more component classes.
|
|
192
|
+
base_folder = options[:folder] || "#{options[:component_type]}.#{options[:plugin_name]}.#{options[:component_name]}"
|
|
193
|
+
folder = "#{base_folder}/metababel"
|
|
194
|
+
FileUtils.mkdir_p(folder)
|
|
195
|
+
|
|
196
|
+
d = {:options => options}
|
|
197
|
+
|
|
198
|
+
d[:params_declaration] = ''
|
|
199
|
+
d[:params_definition] = ''
|
|
200
|
+
if options.key?(:params)
|
|
201
|
+
y = YAML.load_file(options[:params])
|
|
202
|
+
c = Babeltrace2Gen::BTValueCLass.from_h(y)
|
|
203
|
+
body = Babeltrace2Gen.context(indent: 1) do
|
|
204
|
+
c.get('usr_params', 'params')
|
|
205
|
+
end
|
|
206
|
+
d[:params_declaration] = c.get_struct_definition('params')
|
|
207
|
+
d[:params_definition] = body
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
erb_render_and_save(d, "#{options[:component_type].downcase}.c", base_folder, out_name: "#{options[:plugin_name]}.c")
|
|
211
|
+
erb_render_and_save({options: options}, 'metababel.h', folder, prefix: '')
|
|
212
|
+
|
|
213
|
+
wrote_component(options, d, folder)
|
|
214
|
+
if %w[SOURCE FILTER].include?(options[:component_type])
|
|
215
|
+
raise 'Missing downstream model' unless options[:downstream]
|
|
216
|
+
|
|
217
|
+
y = YAML.load_file(options[:downstream])
|
|
218
|
+
validate_model(y)
|
|
219
|
+
t = Babeltrace2Gen::BTTraceClass.from_h(nil, y)
|
|
220
|
+
wrote_creates(folder, t)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
if %w[FILTER SINK].include?(options[:component_type])
|
|
224
|
+
raise 'Missing upstream models' unless options[:upstreams]
|
|
225
|
+
|
|
226
|
+
y = options[:upstreams].reduce({}) do |y, upstream|
|
|
227
|
+
# Need to specialize for merging arrays
|
|
228
|
+
y.deep_merge(YAML.load_file(upstream)) { |_key, old, new| old + new }
|
|
229
|
+
end
|
|
230
|
+
validate_model(y)
|
|
231
|
+
t = Babeltrace2Gen::BTTraceClass.from_h(nil, y)
|
|
232
|
+
wrote_event_dispatchers(folder, t)
|
|
233
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Babeltrace2Gen
|
|
2
|
+
module BTPrinter
|
|
3
|
+
@@output = ''
|
|
4
|
+
@@indent = 0
|
|
5
|
+
INDENT_INCREMENT = ' '.freeze
|
|
6
|
+
|
|
7
|
+
def pr(str)
|
|
8
|
+
@@output << INDENT_INCREMENT * @@indent << str << "\n"
|
|
9
|
+
end
|
|
10
|
+
module_function :pr
|
|
11
|
+
|
|
12
|
+
def scope
|
|
13
|
+
pr '{'
|
|
14
|
+
@@indent += 1
|
|
15
|
+
yield
|
|
16
|
+
@@indent -= 1
|
|
17
|
+
pr '}'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.context(output: '', indent: 0)
|
|
21
|
+
@@output = output
|
|
22
|
+
@@indent = indent
|
|
23
|
+
yield
|
|
24
|
+
@@output
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Maybe not the best place
|
|
28
|
+
def name_sanitized
|
|
29
|
+
raise unless @name
|
|
30
|
+
|
|
31
|
+
@name.gsub(/[^0-9A-Za-z\-]/, '_')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.context(**args, &block)
|
|
36
|
+
BTPrinter.context(**args, &block)
|
|
37
|
+
end
|
|
38
|
+
end
|