blob: 1021ebb2998dd94caec04bd963f24fd06e6ed06b [file] [log] [blame]
Pekka Paalanena5630ea2017-10-12 13:13:42 +02001/*
2 * Copyright © 2017 Pekka Paalanen <pq@iki.fi>
3 * Copyright © 2018 Zodiac Inflight Innovations
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27#include "config.h"
28
Marius Vladc901e892019-06-21 22:49:18 +030029#include <libweston/weston-log.h>
Pekka Paalanenc232f8d2019-04-05 16:09:45 +030030#include "shared/helpers.h"
Pekka Paalanen3d5d9472019-03-28 16:28:47 +020031#include <libweston/libweston.h>
Pekka Paalanena5630ea2017-10-12 13:13:42 +020032
Marius Vlade0a858a2019-06-25 12:48:56 +030033#include "weston-log-internal.h"
Pekka Paalanena5630ea2017-10-12 13:13:42 +020034#include "weston-debug-server-protocol.h"
35
36#include <assert.h>
37#include <unistd.h>
38#include <stdarg.h>
39#include <string.h>
40#include <errno.h>
41#include <sys/time.h>
42
Marius Vlad8b8b8032019-06-27 18:34:03 +030043/**
44 * @defgroup log Public Logging/Debugging API
45 * @defgroup internal-log Private/Internal Logging/Debugging API
46 * @defgroup debug-protocol weston-debug protocol specific
47 */
48
Marius Vlad3d7d9782019-04-17 12:35:38 +030049/** Main weston-log context
Pekka Paalanena5630ea2017-10-12 13:13:42 +020050 *
Marius Vlade0a858a2019-06-25 12:48:56 +030051 * One per weston_compositor. Stores list of scopes created and a list pending
52 * subscriptions.
Pekka Paalanena5630ea2017-10-12 13:13:42 +020053 *
Marius Vlade0a858a2019-06-25 12:48:56 +030054 * A pending subscription is a subscription to a scope which hasn't been
55 * created. When the scope is finally created the pending subscription will be
56 * removed from the pending subscription list, but not before was added in the
57 * scope's subscription list and that of the subscriber list.
58 *
59 * Pending subscriptions only make sense for other types of streams, other than
60 * those created by weston-debug protocol. In the case of the weston-debug
61 * protocol, the subscription processes is done automatically whenever a client
62 * connects and subscribes to a scope which was previously advertised by the
63 * compositor.
64 *
Marius Vlad8b8b8032019-06-27 18:34:03 +030065 * @ingroup internal-log
Pekka Paalanena5630ea2017-10-12 13:13:42 +020066 */
Marius Vlad3d7d9782019-04-17 12:35:38 +030067struct weston_log_context {
Pekka Paalanena5630ea2017-10-12 13:13:42 +020068 struct wl_global *global;
Marius Vlad5d5e3352019-04-17 13:05:38 +030069 struct wl_list scope_list; /**< weston_log_scope::compositor_link */
Marius Vlade0a858a2019-06-25 12:48:56 +030070 struct wl_list pending_subscription_list; /**< weston_log_subscription::source_link */
Pekka Paalanena5630ea2017-10-12 13:13:42 +020071};
72
Marius Vlad5d5e3352019-04-17 13:05:38 +030073/** weston-log message scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +020074 *
Marius Vlad7e4db952019-04-17 13:47:06 +030075 * This is used for scoping logging/debugging messages. Clients can subscribe
76 * to only the scopes they are interested in. A scope is identified by its name
Pekka Paalanena5630ea2017-10-12 13:13:42 +020077 * (also referred to as debug stream name).
Marius Vlad8b8b8032019-06-27 18:34:03 +030078 *
79 * @ingroup log
Pekka Paalanena5630ea2017-10-12 13:13:42 +020080 */
Marius Vlad5d5e3352019-04-17 13:05:38 +030081struct weston_log_scope {
Pekka Paalanena5630ea2017-10-12 13:13:42 +020082 char *name;
83 char *desc;
Marius Vlad0c7beb02019-07-25 11:46:44 +030084 weston_log_scope_cb new_subscription;
Marius Vlad9bb1c3a2019-07-29 12:02:47 +030085 weston_log_scope_cb destroy_subscription;
Pekka Paalanena5630ea2017-10-12 13:13:42 +020086 void *user_data;
Pekka Paalanena5630ea2017-10-12 13:13:42 +020087 struct wl_list compositor_link;
Marius Vlade0a858a2019-06-25 12:48:56 +030088 struct wl_list subscription_list; /**< weston_log_subscription::source_link */
Pekka Paalanena5630ea2017-10-12 13:13:42 +020089};
90
Marius Vlade0a858a2019-06-25 12:48:56 +030091/** Ties a subscriber to a scope
92 *
93 * A subscription is created each time we'd want to subscribe to a scope. From
94 * the stream type we can retrieve the subscriber and from the subscriber we
95 * reach each of the streams callbacks. See also weston_log_subscriber object.
96 *
97 * When a subscription has been created we store it in the scope's subscription
98 * list and in the subscriber's subscription list. The subscription might be a
99 * pending subscription until the scope for which there's was a subscribe has
100 * been created. The scope creation will take of looking through the pending
101 * subscription list.
102 *
103 * A subscription can reached from a subscriber subscription list by using the
104 * streams base class.
105 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300106 * @ingroup internal-log
Marius Vlade0a858a2019-06-25 12:48:56 +0300107 */
108struct weston_log_subscription {
109 struct weston_log_subscriber *owner;
110 struct wl_list owner_link; /**< weston_log_subscriber::subscription_list */
111
112 char *scope_name;
113 struct weston_log_scope *source;
114 struct wl_list source_link; /**< weston_log_scope::subscription_list or
115 weston_log_context::pending_subscription_list */
116};
117
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300118static struct weston_log_subscription *
119find_pending_subscription(struct weston_log_context *log_ctx,
120 const char *scope_name)
121{
122 struct weston_log_subscription *sub;
123
124 wl_list_for_each(sub, &log_ctx->pending_subscription_list, source_link)
125 if (!strncmp(sub->scope_name, scope_name, strlen(scope_name)))
126 return sub;
127
128 return NULL;
129}
130
131/** Create a pending subscription and add it the list of pending subscriptions
132 *
133 * @param owner a subscriber represented by weston_log_subscriber object
134 * @param scope_name the name of the scope (which we don't have in the list of scopes)
135 * @param log_ctx the logging context used to add the pending subscription
136 *
137 * @memberof weston_log_subscription
138 */
139static void
140weston_log_subscription_create_pending(struct weston_log_subscriber *owner,
141 const char *scope_name,
142 struct weston_log_context *log_ctx)
143{
144 assert(owner);
145 assert(scope_name);
146 struct weston_log_subscription *sub = zalloc(sizeof(*sub));
147
148 if (!sub)
149 return;
150
151 sub->scope_name = strdup(scope_name);
152 sub->owner = owner;
153
154 wl_list_insert(&log_ctx->pending_subscription_list, &sub->source_link);
155}
156
157/** Destroys the pending subscription created previously with
158 * weston_log_subscription_create_pending()
159 *
160 * @param sub the weston_log_subscription object to remove from the list
161 * of subscriptions and to destroy the subscription
162 *
163 * @memberof weston_log_subscription
164 */
165static void
166weston_log_subscription_destroy_pending(struct weston_log_subscription *sub)
167{
168 assert(sub);
169 /* pending subsriptions do not have a source */
170 wl_list_remove(&sub->source_link);
171 free(sub->scope_name);
172 free(sub);
173}
174
Marius Vlad8b8b8032019-06-27 18:34:03 +0300175/** Write to the stream's subscription
176 *
177 * @memberof weston_log_subscription
178 */
Marius Vladdad882a2019-07-17 15:43:53 +0300179static void
180weston_log_subscription_write(struct weston_log_subscription *sub,
181 const char *data, size_t len)
182{
183 if (sub->owner && sub->owner->write)
184 sub->owner->write(sub->owner, data, len);
185}
186
Marius Vlad8b8b8032019-06-27 18:34:03 +0300187/** Write a formatted string to the stream's subscription
188 *
189 * @memberof weston_log_subscription
190 */
Marius Vladdad882a2019-07-17 15:43:53 +0300191static void
192weston_log_subscription_vprintf(struct weston_log_subscription *sub,
193 const char *fmt, va_list ap)
194{
195 static const char oom[] = "Out of memory";
196 char *str;
197 int len;
198
199 if (!weston_log_scope_is_enabled(sub->source))
200 return;
201
202 len = vasprintf(&str, fmt, ap);
203 if (len >= 0) {
204 weston_log_subscription_write(sub, str, len);
205 free(str);
206 } else {
207 weston_log_subscription_write(sub, oom, sizeof oom - 1);
208 }
209}
210
Marius Vlade0a858a2019-06-25 12:48:56 +0300211/** Creates a new subscription using the subscriber by \c owner.
212 *
213 * The subscription created is added to the \c owner subscription list.
214 * Destroying the subscription using weston_log_subscription_destroy() will
215 * remove the link from the subscription list and free storage alloc'ed.
216 *
Marius Vlad5ae0e622019-07-11 17:44:50 +0300217 * Note that this adds the subscription to the scope's subscription list
218 * hence the \c scope required argument.
219 *
Marius Vlade0a858a2019-06-25 12:48:56 +0300220 * @param owner the subscriber owner, must be created before creating a
221 * subscription
Marius Vlad5ae0e622019-07-11 17:44:50 +0300222 * @param scope the scope in order to add the subscription to the scope's
223 * subscription list
Marius Vlade0a858a2019-06-25 12:48:56 +0300224 * @returns a weston_log_subscription object in case of success, or NULL
225 * otherwise
226 *
Marius Vlade0a858a2019-06-25 12:48:56 +0300227 * @sa weston_log_subscription_destroy, weston_log_subscription_remove,
228 * weston_log_subscription_add
Marius Vlad8b8b8032019-06-27 18:34:03 +0300229 * @memberof weston_log_subscription
Marius Vlade0a858a2019-06-25 12:48:56 +0300230 */
Marius Vlad5ae0e622019-07-11 17:44:50 +0300231void
Marius Vlade0a858a2019-06-25 12:48:56 +0300232weston_log_subscription_create(struct weston_log_subscriber *owner,
Marius Vlad5ae0e622019-07-11 17:44:50 +0300233 struct weston_log_scope *scope)
Marius Vlade0a858a2019-06-25 12:48:56 +0300234{
235 struct weston_log_subscription *sub;
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300236 assert(owner);
Marius Vlad5ae0e622019-07-11 17:44:50 +0300237 assert(scope);
238 assert(scope->name);
Marius Vlade0a858a2019-06-25 12:48:56 +0300239
240 sub = zalloc(sizeof(*sub));
241 if (!sub)
Marius Vlad5ae0e622019-07-11 17:44:50 +0300242 return;
Marius Vlade0a858a2019-06-25 12:48:56 +0300243
244 sub->owner = owner;
Marius Vlad5ae0e622019-07-11 17:44:50 +0300245 sub->scope_name = strdup(scope->name);
Marius Vlade0a858a2019-06-25 12:48:56 +0300246
247 wl_list_insert(&sub->owner->subscription_list, &sub->owner_link);
Marius Vlad5ae0e622019-07-11 17:44:50 +0300248
249 weston_log_subscription_add(scope, sub);
Marius Vlad0c7beb02019-07-25 11:46:44 +0300250 weston_log_run_cb_new_subscription(sub);
Marius Vlade0a858a2019-06-25 12:48:56 +0300251}
252
253/** Destroys the subscription
254 *
Marius Vlad5ae0e622019-07-11 17:44:50 +0300255 * Removes the subscription from the scopes subscription list and from
256 * subscriber's subscription list. It destroys the subscription afterwads.
257 *
258 * @memberof weston_log_subscription
Marius Vlade0a858a2019-06-25 12:48:56 +0300259 */
260void
261weston_log_subscription_destroy(struct weston_log_subscription *sub)
262{
Marius Vlad5ae0e622019-07-11 17:44:50 +0300263 assert(sub);
Marius Vlad9bb1c3a2019-07-29 12:02:47 +0300264
265 if (sub->source->destroy_subscription)
266 sub->source->destroy_subscription(sub, sub->source->user_data);
267
Marius Vlade0a858a2019-06-25 12:48:56 +0300268 if (sub->owner)
269 wl_list_remove(&sub->owner_link);
Marius Vlad5ae0e622019-07-11 17:44:50 +0300270
271 weston_log_subscription_remove(sub);
Marius Vlade0a858a2019-06-25 12:48:56 +0300272 free(sub->scope_name);
273 free(sub);
274}
275
276/** Retrieve a subscription by using the subscriber
277 *
278 * This is useful when trying to find a subscription from the subscriber by
279 * having only access to the stream.
280 *
281 * @param subscriber the subscriber in question
282 * @returns a weston_log_subscription object
283 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300284 * @memberof weston_log_subscription
Marius Vlade0a858a2019-06-25 12:48:56 +0300285 */
286struct weston_log_subscription *
287weston_log_subscriber_get_only_subscription(struct weston_log_subscriber *subscriber)
288{
289 struct weston_log_subscription *sub;
290 /* unlikely, but can happen */
291 if (wl_list_length(&subscriber->subscription_list) == 0)
292 return NULL;
293
294 assert(wl_list_length(&subscriber->subscription_list) == 1);
295
296 return wl_container_of(subscriber->subscription_list.prev,
297 sub, owner_link);
298}
299
300/** Adds the subscription \c sub to the subscription list of the
301 * scope.
302 *
303 * This should used when the scope has been created, and the subscription \c
304 * sub has be created before calling this function.
305 *
306 * @param scope the scope
307 * @param sub the subscription, it must be created before, see
308 * weston_log_subscription_create()
309 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300310 * @memberof weston_log_subscription
Marius Vlade0a858a2019-06-25 12:48:56 +0300311 */
312void
313weston_log_subscription_add(struct weston_log_scope *scope,
314 struct weston_log_subscription *sub)
315{
316 assert(scope);
317 assert(sub);
318 /* don't allow subscriptions to have a source already! */
319 assert(!sub->source);
320
321 sub->source = scope;
322 wl_list_insert(&scope->subscription_list, &sub->source_link);
323}
324
325/** Removes the subscription from the scope's subscription list
326 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300327 * @memberof weston_log_subscription
Marius Vlade0a858a2019-06-25 12:48:56 +0300328 */
329void
330weston_log_subscription_remove(struct weston_log_subscription *sub)
331{
332 assert(sub);
333 if (sub->source)
334 wl_list_remove(&sub->source_link);
335 sub->source = NULL;
336}
337
Marius Vlad8f329e22019-06-21 14:57:02 +0300338/** Look-up the scope from the scope list stored in the log context, by
339 * matching against the \c name.
340 *
341 * @param log_ctx
342 * @param name the scope name, see weston_compositor_add_log_scope()
343 * @returns NULL if none found, or a pointer to a weston_log_scope
344 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300345 * @ingroup internal-log
Marius Vlad8f329e22019-06-21 14:57:02 +0300346 */
347struct weston_log_scope *
348weston_log_get_scope(struct weston_log_context *log_ctx, const char *name)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200349{
Marius Vlad5d5e3352019-04-17 13:05:38 +0300350 struct weston_log_scope *scope;
Marius Vlad3d7d9782019-04-17 12:35:38 +0300351 wl_list_for_each(scope, &log_ctx->scope_list, compositor_link)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200352 if (strcmp(name, scope->name) == 0)
353 return scope;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200354 return NULL;
355}
356
Marius Vlad0c7beb02019-07-25 11:46:44 +0300357/** Wrapper to invoke the weston_log_scope_cb. Allows to call the cb
358 * new_subscription of a log scope.
Marius Vlad8f329e22019-06-21 14:57:02 +0300359 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300360 * @ingroup internal-log
Marius Vlad8f329e22019-06-21 14:57:02 +0300361 */
362void
Marius Vlad0c7beb02019-07-25 11:46:44 +0300363weston_log_run_cb_new_subscription(struct weston_log_subscription *sub)
Marius Vlad8f329e22019-06-21 14:57:02 +0300364{
Marius Vlad0c7beb02019-07-25 11:46:44 +0300365 if (sub->source->new_subscription)
366 sub->source->new_subscription(sub, sub->source->user_data);
Marius Vlad8f329e22019-06-21 14:57:02 +0300367}
368
369/** Advertise the log scope name and the log scope description
370 *
371 * This is only used by the weston-debug protocol!
372 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300373 * @ingroup internal-log
Marius Vlad8f329e22019-06-21 14:57:02 +0300374 */
375void
376weston_debug_protocol_advertise_scopes(struct weston_log_context *log_ctx,
377 struct wl_resource *res)
378{
379 struct weston_log_scope *scope;
380 wl_list_for_each(scope, &log_ctx->scope_list, compositor_link)
381 weston_debug_v1_send_available(res, scope->name, scope->desc);
382}
383
Marius Vlad880b4852019-04-07 17:07:58 +0300384/**
Marius Vlad3d7d9782019-04-17 12:35:38 +0300385 * Connect weston_compositor structure to weston_log_context structure.
Marius Vlad880b4852019-04-07 17:07:58 +0300386 *
387 * \param compositor
Marius Vlad3d7d9782019-04-17 12:35:38 +0300388 * \param log_ctx
Marius Vlad880b4852019-04-07 17:07:58 +0300389 * \return 0 on success, -1 on failure
390 *
Marius Vlad3d7d9782019-04-17 12:35:38 +0300391 * Sets weston_compositor::weston_log_ctx.
Marius Vlad8b8b8032019-06-27 18:34:03 +0300392 *
393 * @ingroup log
Marius Vlad880b4852019-04-07 17:07:58 +0300394 */
395int
Marius Vlad3d7d9782019-04-17 12:35:38 +0300396weston_log_ctx_compositor_setup(struct weston_compositor *compositor,
397 struct weston_log_context *log_ctx)
Marius Vlad880b4852019-04-07 17:07:58 +0300398{
Marius Vlad6f098662019-04-17 13:50:28 +0300399 assert(!compositor->weston_log_ctx);
400 assert(log_ctx);
Marius Vlad880b4852019-04-07 17:07:58 +0300401
Marius Vlad3d7d9782019-04-17 12:35:38 +0300402 compositor->weston_log_ctx = log_ctx;
Marius Vlad880b4852019-04-07 17:07:58 +0300403 return 0;
404}
405
Marius Vlada2dace22019-06-12 16:05:44 +0300406/** Creates weston_log_context structure
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200407 *
Marius Vlada2dace22019-06-12 16:05:44 +0300408 * \return NULL in case of failure, or a weston_log_context object in case of
409 * success
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200410 *
Marius Vlad3d7d9782019-04-17 12:35:38 +0300411 * weston_log_context is a singleton for each weston_compositor.
Marius Vlad8b8b8032019-06-27 18:34:03 +0300412 * @ingroup log
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200413 *
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200414 */
Marius Vlad3d7d9782019-04-17 12:35:38 +0300415WL_EXPORT struct weston_log_context *
416weston_log_ctx_compositor_create(void)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200417{
Marius Vlad3d7d9782019-04-17 12:35:38 +0300418 struct weston_log_context *log_ctx;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200419
Marius Vlad3d7d9782019-04-17 12:35:38 +0300420 log_ctx = zalloc(sizeof *log_ctx);
421 if (!log_ctx)
Marius Vlad880b4852019-04-07 17:07:58 +0300422 return NULL;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200423
Marius Vlad3d7d9782019-04-17 12:35:38 +0300424 wl_list_init(&log_ctx->scope_list);
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300425 wl_list_init(&log_ctx->pending_subscription_list);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200426
Marius Vlad3d7d9782019-04-17 12:35:38 +0300427 return log_ctx;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200428}
429
Marius Vlad3d7d9782019-04-17 12:35:38 +0300430/** Destroy weston_log_context structure
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200431 *
432 * \param compositor The libweston compositor whose weston-debug to tear down.
433 *
Marius Vlad3d7d9782019-04-17 12:35:38 +0300434 * Clears weston_compositor::weston_log_ctx.
Marius Vlad8b8b8032019-06-27 18:34:03 +0300435 * @ingroup log
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200436 *
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200437 */
Marius Vlad3d7d9782019-04-17 12:35:38 +0300438WL_EXPORT void
439weston_log_ctx_compositor_destroy(struct weston_compositor *compositor)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200440{
Marius Vlad3d7d9782019-04-17 12:35:38 +0300441 struct weston_log_context *log_ctx = compositor->weston_log_ctx;
Marius Vlad5d5e3352019-04-17 13:05:38 +0300442 struct weston_log_scope *scope;
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300443 struct weston_log_subscription *pending_sub, *pending_sub_tmp;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200444
Marius Vlad3d7d9782019-04-17 12:35:38 +0300445 if (log_ctx->global)
446 wl_global_destroy(log_ctx->global);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200447
Marius Vlad3d7d9782019-04-17 12:35:38 +0300448 wl_list_for_each(scope, &log_ctx->scope_list, compositor_link)
Marius Vladef4c2682019-06-23 15:48:54 +0300449 fprintf(stderr, "Internal warning: debug scope '%s' has not been destroyed.\n",
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200450 scope->name);
451
452 /* Remove head to not crash if scope removed later. */
Marius Vlad3d7d9782019-04-17 12:35:38 +0300453 wl_list_remove(&log_ctx->scope_list);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200454
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300455 /* Remove any pending subscription(s) which nobody subscribed to */
456 wl_list_for_each_safe(pending_sub, pending_sub_tmp,
457 &log_ctx->pending_subscription_list, source_link) {
458 weston_log_subscription_destroy_pending(pending_sub);
459 }
460
461 /* pending_subscription_list should be empty at this point */
462
Marius Vlad3d7d9782019-04-17 12:35:38 +0300463 free(log_ctx);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200464
Marius Vlad3d7d9782019-04-17 12:35:38 +0300465 compositor->weston_log_ctx = NULL;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200466}
467
468/** Enable weston-debug protocol extension
469 *
470 * \param compositor The libweston compositor where to enable.
471 *
472 * This enables the weston_debug_v1 Wayland protocol extension which any client
Emmanuel Gil Peyrot426c2462019-02-20 16:33:32 +0100473 * can use to get debug messages from the compositor.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200474 *
475 * WARNING: This feature should not be used in production. If a client
476 * provides a file descriptor that blocks writes, it will block the whole
477 * compositor indefinitely.
478 *
479 * There is no control on which client is allowed to subscribe to debug
480 * messages. Any and all clients are allowed.
481 *
482 * The debug extension is disabled by default, and once enabled, cannot be
483 * disabled again.
Marius Vlad8b8b8032019-06-27 18:34:03 +0300484 *
485 * @ingroup debug-protocol
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200486 */
487WL_EXPORT void
488weston_compositor_enable_debug_protocol(struct weston_compositor *compositor)
489{
Marius Vlad1e2fda22019-04-07 19:07:16 +0300490 struct weston_log_context *log_ctx = compositor->weston_log_ctx;
491 assert(log_ctx);
492 if (log_ctx->global)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200493 return;
494
Marius Vlad1e2fda22019-04-07 19:07:16 +0300495 log_ctx->global = wl_global_create(compositor->wl_display,
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200496 &weston_debug_v1_interface, 1,
Marius Vlad69e75712019-06-25 13:29:57 +0300497 log_ctx, weston_log_bind_weston_debug);
Marius Vlad1e2fda22019-04-07 19:07:16 +0300498 if (!log_ctx->global)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200499 return;
500
Marius Vladef4c2682019-06-23 15:48:54 +0300501 fprintf(stderr, "WARNING: debug protocol has been enabled. "
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200502 "This is a potential denial-of-service attack vector and "
503 "information leak.\n");
504}
505
Marius Vladd9bcc0b2018-12-13 23:03:30 +0200506/** Determine if the debug protocol has been enabled
507 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300508 * \param wc The libweston compositor to verify if debug protocol has been
509 * enabled
510 *
511 * @ingroup debug-protocol
Marius Vladd9bcc0b2018-12-13 23:03:30 +0200512 */
513WL_EXPORT bool
514weston_compositor_is_debug_protocol_enabled(struct weston_compositor *wc)
515{
Marius Vlad3d7d9782019-04-17 12:35:38 +0300516 return wc->weston_log_ctx->global != NULL;
Marius Vladd9bcc0b2018-12-13 23:03:30 +0200517}
518
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300519/** Register a new stream name, creating a log scope.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200520 *
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300521 * @param log_ctx The weston_log_context where to add.
522 * @param name The debug stream/scope name; must not be NULL.
523 * @param description The log scope description for humans; must not be NULL.
Marius Vlad0c7beb02019-07-25 11:46:44 +0300524 * @param new_subscription Optional callback when a client subscribes to this
Marius Vladdad882a2019-07-17 15:43:53 +0300525 * scope.
Marius Vlad9bb1c3a2019-07-29 12:02:47 +0300526 * @param destroy_subscription Optional callback when a client destroys the
527 * subscription.
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300528 * @param user_data Optional user data pointer for the callback.
529 * @returns A valid pointer on success, NULL on failure.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200530 *
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300531 * This function is used to create a log scope. All debug message printing
532 * happens for a scope, which allows clients to subscribe to the kind of debug
533 * messages they want by \c name. For the weston-debug protocol,
534 * subscription for the scope will happen automatically but for other types of
535 * streams, weston_log_subscribe() should be called as to create a subscription
536 * and tie it to the scope created by this function.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200537 *
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300538 * \p name must be unique in the weston_compositor instance. \p name
539 * and \p description must both be provided. In case of the weston-debug
540 * protocol, the description is printed when a client asks for a list of
541 * supported log scopes.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200542 *
Marius Vlad0c7beb02019-07-25 11:46:44 +0300543 * \p new_subscription, if not NULL, is called when a client subscribes to the log
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300544 * scope creating a debug stream. This is for log scopes that need to print
545 * messages as a response to a client appearing, e.g. printing a list of
546 * windows on demand or a static preamble. The argument \p user_data is
547 * passed in to the callback and is otherwise unused.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200548 *
Marius Vlad0c7beb02019-07-25 11:46:44 +0300549 * For one-shot debug streams, \c new_subscription should finally call
Marius Vladdad882a2019-07-17 15:43:53 +0300550 * weston_log_subscription_complete() to close the stream and tell the client
551 * the printing is complete. Otherwise the client expects more data to be
552 * written. The complete callback in weston_log_subscriber should be installed
553 * to trigger it and it is set-up automatically for the weston-debug protocol.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200554 *
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300555 * As subscription can take place before creating the scope, any pending
556 * subscriptions to scope added by weston_log_subscribe(), will be checked
557 * against the scope being created and if found will be added to the scope's
558 * subscription list.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200559 *
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300560 * The log scope must be destroyed using weston_compositor_log_scope_destroy()
561 * before destroying the weston_compositor.
562 *
563 * @memberof weston_log_scope
564 * @sa weston_log_scope_cb, weston_log_subscribe
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200565 */
Marius Vlad5d5e3352019-04-17 13:05:38 +0300566WL_EXPORT struct weston_log_scope *
Marius Vlad7e4db952019-04-17 13:47:06 +0300567weston_compositor_add_log_scope(struct weston_log_context *log_ctx,
568 const char *name,
569 const char *description,
Marius Vlad0c7beb02019-07-25 11:46:44 +0300570 weston_log_scope_cb new_subscription,
Marius Vlad9bb1c3a2019-07-29 12:02:47 +0300571 weston_log_scope_cb destroy_subscription,
Marius Vlad7e4db952019-04-17 13:47:06 +0300572 void *user_data)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200573{
Marius Vlad5d5e3352019-04-17 13:05:38 +0300574 struct weston_log_scope *scope;
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300575 struct weston_log_subscription *pending_sub = NULL;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200576
Marius Vlad1e2fda22019-04-07 19:07:16 +0300577 if (!name || !description) {
Marius Vladef4c2682019-06-23 15:48:54 +0300578 fprintf(stderr, "Error: cannot add a debug scope without name or description.\n");
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200579 return NULL;
580 }
581
Marius Vlad3d7d9782019-04-17 12:35:38 +0300582 if (!log_ctx) {
Marius Vladef4c2682019-06-23 15:48:54 +0300583 fprintf(stderr, "Error: cannot add debug scope '%s', infra not initialized.\n",
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200584 name);
585 return NULL;
586 }
587
Marius Vlad8f329e22019-06-21 14:57:02 +0300588 if (weston_log_get_scope(log_ctx, name)){
Marius Vladef4c2682019-06-23 15:48:54 +0300589 fprintf(stderr, "Error: debug scope named '%s' is already registered.\n",
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200590 name);
591 return NULL;
592 }
593
594 scope = zalloc(sizeof *scope);
595 if (!scope) {
Marius Vladef4c2682019-06-23 15:48:54 +0300596 fprintf(stderr, "Error adding debug scope '%s': out of memory.\n",
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200597 name);
598 return NULL;
599 }
600
601 scope->name = strdup(name);
602 scope->desc = strdup(description);
Marius Vlad0c7beb02019-07-25 11:46:44 +0300603 scope->new_subscription = new_subscription;
Marius Vlad9bb1c3a2019-07-29 12:02:47 +0300604 scope->destroy_subscription = destroy_subscription;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200605 scope->user_data = user_data;
Marius Vlad7814f302019-06-21 14:20:15 +0300606 wl_list_init(&scope->subscription_list);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200607
608 if (!scope->name || !scope->desc) {
Marius Vladef4c2682019-06-23 15:48:54 +0300609 fprintf(stderr, "Error adding debug scope '%s': out of memory.\n",
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200610 name);
611 free(scope->name);
612 free(scope->desc);
613 free(scope);
614 return NULL;
615 }
616
Marius Vlad3d7d9782019-04-17 12:35:38 +0300617 wl_list_insert(log_ctx->scope_list.prev, &scope->compositor_link);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200618
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300619 /* check if there are any pending subscriptions to this scope */
620 while ((pending_sub = find_pending_subscription(log_ctx, scope->name)) != NULL) {
Marius Vlad5ae0e622019-07-11 17:44:50 +0300621 weston_log_subscription_create(pending_sub->owner, scope);
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300622
623 /* remove it from pending */
624 weston_log_subscription_destroy_pending(pending_sub);
625 }
626
627
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200628 return scope;
629}
630
Marius Vlad3d7d9782019-04-17 12:35:38 +0300631/** Destroy a log scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200632 *
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300633 * @param scope The log scope to destroy; may be NULL.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200634 *
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300635 * Destroys the log scope, calling each stream's destroy callback if one was
636 * installed/created.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200637 *
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300638 * @memberof weston_log_scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200639 */
640WL_EXPORT void
Marius Vlad7e4db952019-04-17 13:47:06 +0300641weston_compositor_log_scope_destroy(struct weston_log_scope *scope)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200642{
Marius Vlad7814f302019-06-21 14:20:15 +0300643 struct weston_log_subscription *sub, *sub_tmp;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200644
645 if (!scope)
646 return;
647
Marius Vlad7814f302019-06-21 14:20:15 +0300648 wl_list_for_each_safe(sub, sub_tmp, &scope->subscription_list, source_link) {
649 /* destroy each subscription */
650 if (sub->owner->destroy)
651 sub->owner->destroy(sub->owner);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200652
Marius Vlad7814f302019-06-21 14:20:15 +0300653 weston_log_subscription_destroy(sub);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200654 }
655
656 wl_list_remove(&scope->compositor_link);
657 free(scope->name);
658 free(scope->desc);
659 free(scope);
660}
661
662/** Are there any active subscriptions to the scope?
663 *
Marius Vlad7e4db952019-04-17 13:47:06 +0300664 * \param scope The log scope to check; may be NULL.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200665 * \return True if any streams are open for this scope, false otherwise.
666 *
667 * As printing some debugging messages may be relatively expensive, one
668 * can use this function to determine if there is a need to gather the
669 * debugging information at all. If this function returns false, all
670 * printing for this scope is dropped, so gathering the information is
671 * pointless.
672 *
673 * The return value of this function should not be stored, as new clients
674 * may subscribe to the debug scope later.
675 *
676 * If the given scope is NULL, this function will always return false,
677 * making it safe to use in teardown or destroy code, provided the
678 * scope is initialized to NULL before creation and set to NULL after
679 * destruction.
680 *
Marius Vlad5d5e3352019-04-17 13:05:38 +0300681 * \memberof weston_log_scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200682 */
683WL_EXPORT bool
Marius Vlad7e4db952019-04-17 13:47:06 +0300684weston_log_scope_is_enabled(struct weston_log_scope *scope)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200685{
686 if (!scope)
687 return false;
688
Marius Vlad7814f302019-06-21 14:20:15 +0300689 return !wl_list_empty(&scope->subscription_list);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200690}
691
Marius Vladdad882a2019-07-17 15:43:53 +0300692/** Close the stream's complete callback if one was installed/created.
693 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300694 * @ingroup log
Marius Vladdad882a2019-07-17 15:43:53 +0300695 */
696WL_EXPORT void
697weston_log_subscription_complete(struct weston_log_subscription *sub)
698{
699 if (sub->owner && sub->owner->complete)
700 sub->owner->complete(sub->owner);
701}
702
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300703/** Close the log scope.
704 *
705 * @param scope The log scope to complete; may be NULL.
706 *
707 * Complete the log scope, calling each stream's complete callback if one was
708 * installed/created. This can be useful to signal the reading end that the
709 * data has been transmited and should no longer expect that written over the
710 * stream. Particularly useful for the weston-debug protocol.
711 *
712 * @memberof weston_log_scope
713 * @sa weston_compositor_add_log_scope, weston_compositor_log_scope_destroy
714 */
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200715WL_EXPORT void
Marius Vlad7814f302019-06-21 14:20:15 +0300716weston_log_scope_complete(struct weston_log_scope *scope)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200717{
Marius Vlad7814f302019-06-21 14:20:15 +0300718 struct weston_log_subscription *sub;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200719
Marius Vlad7814f302019-06-21 14:20:15 +0300720 if (!scope)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200721 return;
722
Marius Vlad7814f302019-06-21 14:20:15 +0300723 wl_list_for_each(sub, &scope->subscription_list, source_link)
Marius Vladdad882a2019-07-17 15:43:53 +0300724 weston_log_subscription_complete(sub);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200725}
726
Marius Vlad7e4db952019-04-17 13:47:06 +0300727/** Write log data for a scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200728 *
729 * \param scope The debug scope to write for; may be NULL, in which case
730 * nothing will be written.
Marius Vlada2dace22019-06-12 16:05:44 +0300731 * \param[in] data Pointer to the data to write.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200732 * \param len Number of bytes to write.
733 *
734 * Writes the given data to all subscribed clients' streams.
735 *
Marius Vlad5d5e3352019-04-17 13:05:38 +0300736 * \memberof weston_log_scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200737 */
738WL_EXPORT void
Marius Vlad7e4db952019-04-17 13:47:06 +0300739weston_log_scope_write(struct weston_log_scope *scope,
740 const char *data, size_t len)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200741{
Marius Vlad7814f302019-06-21 14:20:15 +0300742 struct weston_log_subscription *sub;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200743
744 if (!scope)
745 return;
746
Marius Vlad7814f302019-06-21 14:20:15 +0300747 wl_list_for_each(sub, &scope->subscription_list, source_link)
Marius Vladdad882a2019-07-17 15:43:53 +0300748 weston_log_subscription_write(sub, data, len);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200749}
750
751/** Write a formatted string for a scope (varargs)
752 *
Marius Vlad7e4db952019-04-17 13:47:06 +0300753 * \param scope The log scope to write for; may be NULL, in which case
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200754 * nothing will be written.
755 * \param fmt Printf-style format string.
756 * \param ap Formatting arguments.
757 *
758 * Writes to formatted string to all subscribed clients' streams.
759 *
760 * The behavioral details for each stream are the same as for
761 * weston_debug_stream_write().
762 *
Marius Vlad5d5e3352019-04-17 13:05:38 +0300763 * \memberof weston_log_scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200764 */
Marius Vlad843b2382019-08-06 17:37:51 +0300765WL_EXPORT int
Marius Vlad7e4db952019-04-17 13:47:06 +0300766weston_log_scope_vprintf(struct weston_log_scope *scope,
767 const char *fmt, va_list ap)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200768{
769 static const char oom[] = "Out of memory";
770 char *str;
Marius Vlad843b2382019-08-06 17:37:51 +0300771 int len = 0;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200772
Marius Vlad7e4db952019-04-17 13:47:06 +0300773 if (!weston_log_scope_is_enabled(scope))
Marius Vlad843b2382019-08-06 17:37:51 +0300774 return len;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200775
776 len = vasprintf(&str, fmt, ap);
777 if (len >= 0) {
Marius Vlad7e4db952019-04-17 13:47:06 +0300778 weston_log_scope_write(scope, str, len);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200779 free(str);
780 } else {
Marius Vlad7e4db952019-04-17 13:47:06 +0300781 weston_log_scope_write(scope, oom, sizeof oom - 1);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200782 }
Marius Vlad843b2382019-08-06 17:37:51 +0300783
784 return len;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200785}
786
787/** Write a formatted string for a scope
788 *
Marius Vlad7e4db952019-04-17 13:47:06 +0300789 * \param scope The log scope to write for; may be NULL, in which case
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200790 * nothing will be written.
791 * \param fmt Printf-style format string and arguments.
792 *
793 * Writes to formatted string to all subscribed clients' streams.
794 *
795 * The behavioral details for each stream are the same as for
796 * weston_debug_stream_write().
797 *
Marius Vlad5d5e3352019-04-17 13:05:38 +0300798 * \memberof weston_log_scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200799 */
Marius Vlad843b2382019-08-06 17:37:51 +0300800WL_EXPORT int
Marius Vlad7e4db952019-04-17 13:47:06 +0300801weston_log_scope_printf(struct weston_log_scope *scope,
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200802 const char *fmt, ...)
803{
804 va_list ap;
Marius Vlad843b2382019-08-06 17:37:51 +0300805 int len;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200806
807 va_start(ap, fmt);
Marius Vlad843b2382019-08-06 17:37:51 +0300808 len = weston_log_scope_vprintf(scope, fmt, ap);
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200809 va_end(ap);
Marius Vlad843b2382019-08-06 17:37:51 +0300810
811 return len;
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200812}
813
Marius Vladdad882a2019-07-17 15:43:53 +0300814/** Write a formatted string for a subscription
815 *
816 * \param sub The subscription to write for; may be NULL, in which case
817 * nothing will be written.
818 * \param fmt Printf-style format string and arguments.
819 *
820 * Writes to formatted string to the stream that created the subscription.
821 *
Marius Vlad8b8b8032019-06-27 18:34:03 +0300822 * @ingroup log
Marius Vladdad882a2019-07-17 15:43:53 +0300823 */
824WL_EXPORT void
825weston_log_subscription_printf(struct weston_log_subscription *sub,
826 const char *fmt, ...)
827{
828 va_list ap;
829
830 va_start(ap, fmt);
831 weston_log_subscription_vprintf(sub, fmt, ap);
832 va_end(ap);
833}
834
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200835/** Write debug scope name and current time into string
836 *
Marius Vlada2dace22019-06-12 16:05:44 +0300837 * \param[in] scope debug scope; may be NULL
838 * \param[out] buf Buffer to store the string.
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200839 * \param len Available size in the buffer in bytes.
840 * \return \c buf
841 *
842 * Reads the current local wall-clock time and formats it into a string.
843 * and append the debug scope name to it, if a scope is available.
844 * The string is NUL-terminated, even if truncated.
Marius Vlad8b8b8032019-06-27 18:34:03 +0300845 *
846 * @memberof weston_log_scope
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200847 */
848WL_EXPORT char *
Marius Vlad7e4db952019-04-17 13:47:06 +0300849weston_log_scope_timestamp(struct weston_log_scope *scope,
850 char *buf, size_t len)
Pekka Paalanena5630ea2017-10-12 13:13:42 +0200851{
852 struct timeval tv;
853 struct tm *bdt;
854 char string[128];
855 size_t ret = 0;
856
857 gettimeofday(&tv, NULL);
858
859 bdt = localtime(&tv.tv_sec);
860 if (bdt)
861 ret = strftime(string, sizeof string,
862 "%Y-%m-%d %H:%M:%S", bdt);
863
864 if (ret > 0) {
865 snprintf(buf, len, "[%s.%03ld][%s]", string,
866 tv.tv_usec / 1000,
867 (scope) ? scope->name : "no scope");
868 } else {
869 snprintf(buf, len, "[?][%s]",
870 (scope) ? scope->name : "no scope");
871 }
872
873 return buf;
874}
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300875
876/** Subscribe to a scope
877 *
878 * Creates a subscription which is used to subscribe the \p subscriber
879 * to the scope \c scope_name.
880 *
881 * If \c scope_name has already been created (using
882 * weston_compositor_add_log_scope) the subscription will take place
883 * immediately, otherwise we store the subscription into a pending list. See
884 * also weston_compositor_add_log_scope().
885 *
886 * @param log_ctx the log context, used for accessing pending list
887 * @param subscriber the subscriber, which has to be created before
888 * @param scope_name the scope name. In case the scope is not created
889 * we temporarily store the subscription in the pending list.
Marius Vlad8b8b8032019-06-27 18:34:03 +0300890 *
891 * @ingroup log
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300892 */
893WL_EXPORT void
894weston_log_subscribe(struct weston_log_context *log_ctx,
895 struct weston_log_subscriber *subscriber,
896 const char *scope_name)
897{
898 assert(log_ctx);
899 assert(subscriber);
900 assert(scope_name);
901
902 struct weston_log_scope *scope;
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300903
904 scope = weston_log_get_scope(log_ctx, scope_name);
Marius Vlad5ae0e622019-07-11 17:44:50 +0300905 if (scope)
906 weston_log_subscription_create(subscriber, scope);
907 else
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300908 /*
909 * if we don't have already as scope for it, add it to pending
910 * subscription list
911 */
912 weston_log_subscription_create_pending(subscriber, scope_name, log_ctx);
Marius Vlad9f71a4a2019-06-22 00:29:31 +0300913}