Commit | Line | Data |
---|---|---|
d3a684ee JR |
1 | /* |
2 | * base_client.c | |
3 | * | |
4 | * Base client application for testing of LTTng trigger API | |
5 | * | |
6 | * Copyright 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> | |
7 | * | |
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
9 | * of this software and associated documentation files (the "Software"), to deal | |
10 | * in the Software without restriction, including without limitation the rights | |
11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
12 | * copies of the Software, and to permit persons to whom the Software is | |
13 | * furnished to do so, subject to the following conditions: | |
14 | * | |
15 | * The above copyright notice and this permission notice shall be included in | |
16 | * all copies or substantial portions of the Software. | |
17 | * | |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
24 | * SOFTWARE. | |
25 | */ | |
26 | ||
27 | #include <stdio.h> | |
28 | #include <stdbool.h> | |
29 | #include <string.h> | |
30 | #include <unistd.h> | |
31 | #include <inttypes.h> | |
32 | #include <assert.h> | |
33 | ||
34 | #include <lttng/action/action.h> | |
35 | #include <lttng/action/start-session.h> | |
36 | #include <lttng/action/notify.h> | |
37 | #include <lttng/condition/condition.h> | |
38 | #include <lttng/condition/event-rule.h> | |
39 | #include <lttng/event-rule/tracepoint.h> | |
40 | #include <lttng/domain.h> | |
41 | #include <lttng/trigger/trigger.h> | |
42 | #include <lttng/lttng-error.h> | |
43 | #include <lttng/endpoint.h> | |
44 | #include <lttng/notification/channel.h> | |
45 | #include <lttng/notification/notification.h> | |
46 | ||
47 | const char *session_name = NULL; | |
48 | enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE; | |
49 | const char *pattern = NULL; | |
50 | ||
51 | int parse_arguments(char **argv) { | |
52 | const char *domain_type_string = NULL; | |
53 | ||
54 | session_name = argv[1]; | |
55 | domain_type_string = argv[2]; | |
56 | pattern = argv[3]; | |
57 | ||
58 | /* Parse arguments */ | |
59 | /* Domain type */ | |
60 | if (!strcasecmp("LTTNG_DOMAIN_UST", domain_type_string)) { | |
61 | domain_type = LTTNG_DOMAIN_UST; | |
62 | } | |
63 | if (!strcasecmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) { | |
64 | domain_type = LTTNG_DOMAIN_KERNEL; | |
65 | } | |
66 | if (!strcasecmp("LTTNG_DOMAIN_JUL", domain_type_string)) { | |
67 | domain_type = LTTNG_DOMAIN_JUL; | |
68 | } | |
69 | if (!strcasecmp("LTTNG_DOMAIN_PYTHON", domain_type_string)) { | |
70 | domain_type = LTTNG_DOMAIN_PYTHON; | |
71 | } | |
72 | if (!strcasecmp("LTTNG_DOMAIN_LOG4J", domain_type_string)) { | |
73 | domain_type = LTTNG_DOMAIN_LOG4J; | |
74 | } | |
75 | if (domain_type == LTTNG_DOMAIN_NONE) { | |
76 | printf("error: Unknown domain type\n"); | |
77 | goto error; | |
78 | } | |
79 | ||
80 | return 0; | |
81 | error: | |
82 | return 1; | |
83 | } | |
84 | ||
85 | int main(int argc, char **argv) | |
86 | { | |
87 | int ret = 0; | |
88 | struct lttng_condition *condition = NULL; | |
89 | ||
90 | enum lttng_event_rule_status event_rule_status; | |
91 | struct lttng_event_rule *event_rule = NULL; | |
92 | ||
93 | enum lttng_action_status action_status; | |
94 | struct lttng_action *action = NULL; | |
95 | ||
96 | enum lttng_notification_channel_status nc_status; | |
97 | struct lttng_notification_channel *notification_channel = NULL; | |
98 | ||
99 | const char* exclusions[] = { "sample_component:message2"}; | |
100 | ||
101 | struct lttng_trigger *trigger = NULL; | |
102 | ||
103 | if (argc < 4) { | |
104 | printf("error: Missing arguments for tests\n"); | |
105 | ret = 1; | |
106 | goto end; | |
107 | } | |
108 | ||
109 | ret = parse_arguments(argv); | |
110 | if (ret) { | |
111 | printf("error: Could not parse arguments\n"); | |
112 | goto end; | |
113 | } | |
114 | ||
115 | event_rule = lttng_event_rule_tracepoint_create(domain_type); | |
116 | if (!event_rule) { | |
117 | printf("error: Could not create condition object\n"); | |
118 | ret = 1; | |
119 | goto end; | |
120 | } | |
121 | ||
122 | event_rule_status = lttng_event_rule_tracepoint_set_pattern(event_rule, pattern); | |
123 | if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { | |
124 | printf("error: Could not set pattern\n"); | |
125 | ret = 1; | |
126 | goto end; | |
127 | } | |
128 | ||
129 | event_rule_status = lttng_event_rule_tracepoint_set_filter(event_rule, "message=='Hello World'"); | |
130 | if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { | |
131 | printf("error: Could not set pattern\n"); | |
132 | ret = 1; | |
133 | goto end; | |
134 | } | |
135 | ||
136 | event_rule_status = lttng_event_rule_tracepoint_set_exclusions(event_rule, 1, exclusions); | |
137 | if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { | |
138 | printf("error: Could not set exclusions\n"); | |
139 | ret = 1; | |
140 | goto end; | |
141 | } | |
142 | ||
143 | condition = lttng_condition_event_rule_create(event_rule); | |
144 | if (!condition) { | |
145 | printf("error: Could not create condition\n"); | |
146 | ret = 1; | |
147 | goto end; | |
148 | } | |
149 | /* Ownership was passed to condition */ | |
150 | event_rule = NULL; | |
151 | ||
152 | action = lttng_action_notify_create(); | |
153 | if (!action) { | |
154 | printf("error: Could not create action notify\n"); | |
155 | ret = 1; | |
156 | goto end; | |
157 | } | |
158 | ||
159 | trigger = lttng_trigger_create(condition, action); | |
160 | if (!trigger) { | |
161 | printf("error: Could not create trigger\n"); | |
162 | ret = 1; | |
163 | goto end; | |
164 | } | |
165 | ||
166 | ret = lttng_register_trigger(trigger); | |
167 | ||
168 | notification_channel = lttng_notification_channel_create( | |
169 | lttng_session_daemon_notification_endpoint); | |
170 | if (!notification_channel) { | |
171 | printf("error: Could not create notification channel\n"); | |
172 | ret = 1; | |
173 | goto end; | |
174 | } | |
175 | /* | |
176 | * An equivalent trigger might already be registered if an other app | |
177 | * registered an equivalent trigger. | |
178 | */ | |
179 | if (ret < 0 && ret != -LTTNG_ERR_TRIGGER_EXISTS) { | |
180 | printf("error: %s\n", lttng_strerror(ret)); | |
181 | ret = 1; | |
182 | goto end; | |
183 | } | |
184 | ||
185 | nc_status = lttng_notification_channel_subscribe(notification_channel, condition); | |
186 | if (nc_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) { | |
187 | printf("error: Could not subscribe\n"); | |
188 | ret = 1; | |
189 | goto end; | |
190 | } | |
191 | ||
192 | for (;;) { | |
193 | struct lttng_notification *notification; | |
194 | enum lttng_notification_channel_status status; | |
195 | const struct lttng_evaluation *notification_evaluation; | |
196 | const struct lttng_condition *notification_condition; | |
197 | const char *name; | |
198 | ||
199 | /* Receive the next notification. */ | |
200 | status = lttng_notification_channel_get_next_notification( | |
201 | notification_channel, | |
202 | ¬ification); | |
203 | ||
204 | switch (status) { | |
205 | case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK: | |
206 | break; | |
207 | case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED: | |
208 | ret = 1; | |
209 | printf("error: No drop should be observed during this test app\n"); | |
210 | goto end; | |
211 | case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED: | |
212 | /* | |
213 | * The notification channel has been closed by the | |
214 | * session daemon. This is typically caused by a session | |
215 | * daemon shutting down (cleanly or because of a crash). | |
216 | */ | |
217 | printf("error: Notification channel was closed\n"); | |
218 | ret = 1; | |
219 | goto end; | |
220 | default: | |
221 | /* Unhandled conditions / errors. */ | |
222 | printf("error: Unknown notification channel status\n"); | |
223 | ret = 1; | |
224 | goto end; | |
225 | } | |
226 | ||
227 | notification_condition = lttng_notification_get_condition(notification); | |
228 | notification_evaluation = lttng_notification_get_evaluation(notification); | |
229 | switch (lttng_evaluation_get_type(notification_evaluation)) { | |
230 | case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT: | |
231 | lttng_evaluation_event_rule_get_trigger_name(notification_evaluation, &name); | |
232 | printf("Received nootification from trigger \"%s\"\n", name); | |
233 | break; | |
234 | default: | |
235 | printf("error: Wrong notification evaluation type \n"); | |
236 | break; | |
237 | ||
238 | } | |
239 | ||
240 | lttng_notification_destroy(notification); | |
241 | } | |
242 | end: | |
243 | if (trigger) { | |
244 | lttng_unregister_trigger(trigger); | |
245 | } | |
246 | lttng_event_rule_destroy(event_rule); | |
247 | lttng_trigger_destroy(trigger); | |
248 | lttng_condition_destroy(condition); | |
249 | lttng_action_destroy(action); | |
250 | printf("exit: %d\n", ret); | |
251 | return ret; | |
252 | } |