Common Trace Format 2 generation sow-2021-0006-rev1
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 17 Dec 2021 20:41:59 +0000 (15:41 -0500)
committerFrancis Deslauriers <francis.deslauriers@efficios.com>
Fri, 14 Jan 2022 18:22:57 +0000 (13:22 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I2607ddf8a108896f7cd30216b0f996a40eed13a4

786 files changed:
configure.ac
doc/examples/trigger-condition-event-matches/notification-client.cpp
extras/bindings/swig/python/Makefile.am
include/Makefile.am
include/lttng/action/action-internal.h [deleted file]
include/lttng/action/action-internal.hpp [new file with mode: 0644]
include/lttng/action/list-internal.h [deleted file]
include/lttng/action/list-internal.hpp [new file with mode: 0644]
include/lttng/action/notify-internal.h [deleted file]
include/lttng/action/notify-internal.hpp [new file with mode: 0644]
include/lttng/action/path-internal.h [deleted file]
include/lttng/action/path-internal.hpp [new file with mode: 0644]
include/lttng/action/rate-policy-internal.h [deleted file]
include/lttng/action/rate-policy-internal.hpp [new file with mode: 0644]
include/lttng/action/rotate-session-internal.h [deleted file]
include/lttng/action/rotate-session-internal.hpp [new file with mode: 0644]
include/lttng/action/snapshot-session-internal.h [deleted file]
include/lttng/action/snapshot-session-internal.hpp [new file with mode: 0644]
include/lttng/action/start-session-internal.h [deleted file]
include/lttng/action/start-session-internal.hpp [new file with mode: 0644]
include/lttng/action/stop-session-internal.h [deleted file]
include/lttng/action/stop-session-internal.hpp [new file with mode: 0644]
include/lttng/channel-internal.h [deleted file]
include/lttng/channel-internal.hpp [new file with mode: 0644]
include/lttng/condition/buffer-usage-internal.h [deleted file]
include/lttng/condition/buffer-usage-internal.hpp [new file with mode: 0644]
include/lttng/condition/condition-internal.h [deleted file]
include/lttng/condition/condition-internal.hpp [new file with mode: 0644]
include/lttng/condition/evaluation-internal.h [deleted file]
include/lttng/condition/evaluation-internal.hpp [new file with mode: 0644]
include/lttng/condition/event-rule-matches-internal.h [deleted file]
include/lttng/condition/event-rule-matches-internal.hpp [new file with mode: 0644]
include/lttng/condition/session-consumed-size-internal.h [deleted file]
include/lttng/condition/session-consumed-size-internal.hpp [new file with mode: 0644]
include/lttng/condition/session-rotation-internal.h [deleted file]
include/lttng/condition/session-rotation-internal.hpp [new file with mode: 0644]
include/lttng/domain-internal.h [deleted file]
include/lttng/domain-internal.hpp [new file with mode: 0644]
include/lttng/endpoint-internal.h [deleted file]
include/lttng/endpoint-internal.hpp [new file with mode: 0644]
include/lttng/error-query-internal.h [deleted file]
include/lttng/error-query-internal.hpp [new file with mode: 0644]
include/lttng/event-expr-internal.h [deleted file]
include/lttng/event-expr-internal.hpp [new file with mode: 0644]
include/lttng/event-field-value-internal.h [deleted file]
include/lttng/event-field-value-internal.hpp [new file with mode: 0644]
include/lttng/event-internal.h [deleted file]
include/lttng/event-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/event-rule-internal.h [deleted file]
include/lttng/event-rule/event-rule-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/jul-logging-internal.h [deleted file]
include/lttng/event-rule/jul-logging-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/kernel-kprobe-internal.h [deleted file]
include/lttng/event-rule/kernel-kprobe-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/kernel-syscall-internal.h [deleted file]
include/lttng/event-rule/kernel-syscall-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/kernel-tracepoint-internal.h [deleted file]
include/lttng/event-rule/kernel-tracepoint-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/kernel-uprobe-internal.h [deleted file]
include/lttng/event-rule/kernel-uprobe-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/log4j-logging-internal.h [deleted file]
include/lttng/event-rule/log4j-logging-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/python-logging-internal.h [deleted file]
include/lttng/event-rule/python-logging-internal.hpp [new file with mode: 0644]
include/lttng/event-rule/user-tracepoint-internal.h [deleted file]
include/lttng/event-rule/user-tracepoint-internal.hpp [new file with mode: 0644]
include/lttng/health-internal.h [deleted file]
include/lttng/health-internal.hpp [new file with mode: 0644]
include/lttng/kernel-probe-internal.h [deleted file]
include/lttng/kernel-probe-internal.hpp [new file with mode: 0644]
include/lttng/load-internal.h [deleted file]
include/lttng/load-internal.hpp [new file with mode: 0644]
include/lttng/location-internal.h [deleted file]
include/lttng/location-internal.hpp [new file with mode: 0644]
include/lttng/log-level-rule-internal.h [deleted file]
include/lttng/log-level-rule-internal.hpp [new file with mode: 0644]
include/lttng/notification/channel-internal.h [deleted file]
include/lttng/notification/channel-internal.hpp [new file with mode: 0644]
include/lttng/notification/notification-internal.h [deleted file]
include/lttng/notification/notification-internal.hpp [new file with mode: 0644]
include/lttng/ref-internal.h [deleted file]
include/lttng/ref-internal.hpp [new file with mode: 0644]
include/lttng/rotate-internal.h [deleted file]
include/lttng/rotate-internal.hpp [new file with mode: 0644]
include/lttng/save-internal.h [deleted file]
include/lttng/save-internal.hpp [new file with mode: 0644]
include/lttng/session-descriptor-internal.h [deleted file]
include/lttng/session-descriptor-internal.hpp [new file with mode: 0644]
include/lttng/session-internal.h [deleted file]
include/lttng/session-internal.hpp [new file with mode: 0644]
include/lttng/snapshot-internal.h [deleted file]
include/lttng/snapshot-internal.hpp [new file with mode: 0644]
include/lttng/trigger/trigger-internal.h [deleted file]
include/lttng/trigger/trigger-internal.hpp [new file with mode: 0644]
include/lttng/userspace-probe-internal.h [deleted file]
include/lttng/userspace-probe-internal.hpp [new file with mode: 0644]
include/version.h [deleted file]
include/version.hpp [new file with mode: 0644]
src/bin/lttng-consumerd/Makefile.am
src/bin/lttng-consumerd/health-consumerd.cpp
src/bin/lttng-consumerd/health-consumerd.h [deleted file]
src/bin/lttng-consumerd/health-consumerd.hpp [new file with mode: 0644]
src/bin/lttng-consumerd/lttng-consumerd.cpp
src/bin/lttng-consumerd/lttng-consumerd.h [deleted file]
src/bin/lttng-consumerd/lttng-consumerd.hpp [new file with mode: 0644]
src/bin/lttng-consumerd/testpoint.h [deleted file]
src/bin/lttng-consumerd/testpoint.hpp [new file with mode: 0644]
src/bin/lttng-crash/Makefile.am
src/bin/lttng-crash/lttng-crash.cpp
src/bin/lttng-relayd/Makefile.am
src/bin/lttng-relayd/backward-compatibility-group-by.cpp
src/bin/lttng-relayd/backward-compatibility-group-by.h [deleted file]
src/bin/lttng-relayd/backward-compatibility-group-by.hpp [new file with mode: 0644]
src/bin/lttng-relayd/cmd-2-1.cpp
src/bin/lttng-relayd/cmd-2-1.h [deleted file]
src/bin/lttng-relayd/cmd-2-1.hpp [new file with mode: 0644]
src/bin/lttng-relayd/cmd-2-11.cpp
src/bin/lttng-relayd/cmd-2-11.h [deleted file]
src/bin/lttng-relayd/cmd-2-11.hpp [new file with mode: 0644]
src/bin/lttng-relayd/cmd-2-2.cpp
src/bin/lttng-relayd/cmd-2-2.h [deleted file]
src/bin/lttng-relayd/cmd-2-2.hpp [new file with mode: 0644]
src/bin/lttng-relayd/cmd-2-4.cpp
src/bin/lttng-relayd/cmd-2-4.h [deleted file]
src/bin/lttng-relayd/cmd-2-4.hpp [new file with mode: 0644]
src/bin/lttng-relayd/cmd.h [deleted file]
src/bin/lttng-relayd/cmd.hpp [new file with mode: 0644]
src/bin/lttng-relayd/connection.cpp
src/bin/lttng-relayd/connection.h [deleted file]
src/bin/lttng-relayd/connection.hpp [new file with mode: 0644]
src/bin/lttng-relayd/ctf-trace.cpp
src/bin/lttng-relayd/ctf-trace.h [deleted file]
src/bin/lttng-relayd/ctf-trace.hpp [new file with mode: 0644]
src/bin/lttng-relayd/health-relayd.cpp
src/bin/lttng-relayd/health-relayd.h [deleted file]
src/bin/lttng-relayd/health-relayd.hpp [new file with mode: 0644]
src/bin/lttng-relayd/index.cpp
src/bin/lttng-relayd/index.h [deleted file]
src/bin/lttng-relayd/index.hpp [new file with mode: 0644]
src/bin/lttng-relayd/live.cpp
src/bin/lttng-relayd/live.h [deleted file]
src/bin/lttng-relayd/live.hpp [new file with mode: 0644]
src/bin/lttng-relayd/lttng-relayd.h [deleted file]
src/bin/lttng-relayd/lttng-relayd.hpp [new file with mode: 0644]
src/bin/lttng-relayd/lttng-viewer-abi.h [deleted file]
src/bin/lttng-relayd/lttng-viewer-abi.hpp [new file with mode: 0644]
src/bin/lttng-relayd/main.cpp
src/bin/lttng-relayd/session.cpp
src/bin/lttng-relayd/session.h [deleted file]
src/bin/lttng-relayd/session.hpp [new file with mode: 0644]
src/bin/lttng-relayd/sessiond-trace-chunks.cpp
src/bin/lttng-relayd/sessiond-trace-chunks.h [deleted file]
src/bin/lttng-relayd/sessiond-trace-chunks.hpp [new file with mode: 0644]
src/bin/lttng-relayd/stream.cpp
src/bin/lttng-relayd/stream.h [deleted file]
src/bin/lttng-relayd/stream.hpp [new file with mode: 0644]
src/bin/lttng-relayd/tcp_keep_alive.cpp
src/bin/lttng-relayd/tcp_keep_alive.h [deleted file]
src/bin/lttng-relayd/tcp_keep_alive.hpp [new file with mode: 0644]
src/bin/lttng-relayd/testpoint.h [deleted file]
src/bin/lttng-relayd/testpoint.hpp [new file with mode: 0644]
src/bin/lttng-relayd/tracefile-array.cpp
src/bin/lttng-relayd/tracefile-array.h [deleted file]
src/bin/lttng-relayd/tracefile-array.hpp [new file with mode: 0644]
src/bin/lttng-relayd/utils.cpp
src/bin/lttng-relayd/utils.h [deleted file]
src/bin/lttng-relayd/utils.hpp [new file with mode: 0644]
src/bin/lttng-relayd/viewer-session.cpp
src/bin/lttng-relayd/viewer-session.h [deleted file]
src/bin/lttng-relayd/viewer-session.hpp [new file with mode: 0644]
src/bin/lttng-relayd/viewer-stream.cpp
src/bin/lttng-relayd/viewer-stream.h [deleted file]
src/bin/lttng-relayd/viewer-stream.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/Makefile.am
src/bin/lttng-sessiond/action-executor.cpp
src/bin/lttng-sessiond/action-executor.h [deleted file]
src/bin/lttng-sessiond/action-executor.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/agent-thread.cpp
src/bin/lttng-sessiond/agent-thread.h [deleted file]
src/bin/lttng-sessiond/agent-thread.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/agent.cpp
src/bin/lttng-sessiond/agent.h [deleted file]
src/bin/lttng-sessiond/agent.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/buffer-registry.cpp
src/bin/lttng-sessiond/buffer-registry.h [deleted file]
src/bin/lttng-sessiond/buffer-registry.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/channel.cpp
src/bin/lttng-sessiond/channel.h [deleted file]
src/bin/lttng-sessiond/channel.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/clear.cpp
src/bin/lttng-sessiond/clear.h [deleted file]
src/bin/lttng-sessiond/clear.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/client.cpp
src/bin/lttng-sessiond/client.h [deleted file]
src/bin/lttng-sessiond/client.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/cmd.cpp
src/bin/lttng-sessiond/cmd.h [deleted file]
src/bin/lttng-sessiond/cmd.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/condition-internal.cpp
src/bin/lttng-sessiond/condition-internal.h [deleted file]
src/bin/lttng-sessiond/condition-internal.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/consumer.cpp
src/bin/lttng-sessiond/consumer.h [deleted file]
src/bin/lttng-sessiond/consumer.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/context.cpp
src/bin/lttng-sessiond/context.h [deleted file]
src/bin/lttng-sessiond/context.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/dispatch.cpp
src/bin/lttng-sessiond/dispatch.h [deleted file]
src/bin/lttng-sessiond/dispatch.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/event-notifier-error-accounting.cpp
src/bin/lttng-sessiond/event-notifier-error-accounting.h [deleted file]
src/bin/lttng-sessiond/event-notifier-error-accounting.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/event.cpp
src/bin/lttng-sessiond/event.h [deleted file]
src/bin/lttng-sessiond/event.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/fd-limit.cpp
src/bin/lttng-sessiond/fd-limit.h [deleted file]
src/bin/lttng-sessiond/fd-limit.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/globals.cpp
src/bin/lttng-sessiond/health-sessiond.h [deleted file]
src/bin/lttng-sessiond/health-sessiond.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/health.cpp
src/bin/lttng-sessiond/ht-cleanup.cpp
src/bin/lttng-sessiond/ht-cleanup.h [deleted file]
src/bin/lttng-sessiond/ht-cleanup.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/kern-modules.h [deleted file]
src/bin/lttng-sessiond/kern-modules.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/kernel-consumer.cpp
src/bin/lttng-sessiond/kernel-consumer.h [deleted file]
src/bin/lttng-sessiond/kernel-consumer.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/kernel.cpp
src/bin/lttng-sessiond/kernel.h [deleted file]
src/bin/lttng-sessiond/kernel.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/lttng-sessiond.h [deleted file]
src/bin/lttng-sessiond/lttng-sessiond.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/lttng-syscall.cpp
src/bin/lttng-sessiond/lttng-syscall.h [deleted file]
src/bin/lttng-sessiond/lttng-syscall.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/lttng-ust-abi.h [deleted file]
src/bin/lttng-sessiond/lttng-ust-abi.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/lttng-ust-ctl.h [deleted file]
src/bin/lttng-sessiond/lttng-ust-ctl.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/lttng-ust-error.h [deleted file]
src/bin/lttng-sessiond/lttng-ust-error.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/main.cpp
src/bin/lttng-sessiond/manage-apps.cpp
src/bin/lttng-sessiond/manage-apps.h [deleted file]
src/bin/lttng-sessiond/manage-apps.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/manage-consumer.cpp
src/bin/lttng-sessiond/manage-consumer.h [deleted file]
src/bin/lttng-sessiond/manage-consumer.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/manage-kernel.cpp
src/bin/lttng-sessiond/manage-kernel.h [deleted file]
src/bin/lttng-sessiond/manage-kernel.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/modprobe.cpp
src/bin/lttng-sessiond/modprobe.h [deleted file]
src/bin/lttng-sessiond/modprobe.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/notification-thread-commands.cpp
src/bin/lttng-sessiond/notification-thread-commands.h [deleted file]
src/bin/lttng-sessiond/notification-thread-commands.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/notification-thread-events.cpp
src/bin/lttng-sessiond/notification-thread-events.h [deleted file]
src/bin/lttng-sessiond/notification-thread-events.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/notification-thread-internal.h [deleted file]
src/bin/lttng-sessiond/notification-thread-internal.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/notification-thread.cpp
src/bin/lttng-sessiond/notification-thread.h [deleted file]
src/bin/lttng-sessiond/notification-thread.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/notify-apps.cpp
src/bin/lttng-sessiond/notify-apps.h [deleted file]
src/bin/lttng-sessiond/notify-apps.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/process-utils.cpp
src/bin/lttng-sessiond/register.cpp
src/bin/lttng-sessiond/register.h [deleted file]
src/bin/lttng-sessiond/register.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/rotate.cpp
src/bin/lttng-sessiond/rotate.h [deleted file]
src/bin/lttng-sessiond/rotate.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/rotation-thread.cpp
src/bin/lttng-sessiond/rotation-thread.h [deleted file]
src/bin/lttng-sessiond/rotation-thread.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/save.cpp
src/bin/lttng-sessiond/save.h [deleted file]
src/bin/lttng-sessiond/save.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/session.cpp
src/bin/lttng-sessiond/session.h [deleted file]
src/bin/lttng-sessiond/session.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/sessiond-config.cpp
src/bin/lttng-sessiond/sessiond-config.h [deleted file]
src/bin/lttng-sessiond/sessiond-config.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/snapshot.cpp
src/bin/lttng-sessiond/snapshot.h [deleted file]
src/bin/lttng-sessiond/snapshot.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/testpoint.h [deleted file]
src/bin/lttng-sessiond/testpoint.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/thread-utils.cpp
src/bin/lttng-sessiond/thread.cpp
src/bin/lttng-sessiond/thread.h [deleted file]
src/bin/lttng-sessiond/thread.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/timer.cpp
src/bin/lttng-sessiond/timer.h [deleted file]
src/bin/lttng-sessiond/timer.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/trace-kernel.cpp
src/bin/lttng-sessiond/trace-kernel.h [deleted file]
src/bin/lttng-sessiond/trace-kernel.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/trace-ust.cpp
src/bin/lttng-sessiond/trace-ust.h [deleted file]
src/bin/lttng-sessiond/trace-ust.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/tracker.cpp
src/bin/lttng-sessiond/tracker.h [deleted file]
src/bin/lttng-sessiond/tracker.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/trigger-error-query.cpp
src/bin/lttng-sessiond/ust-abi-internal.h [deleted file]
src/bin/lttng-sessiond/ust-abi-internal.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-app.cpp
src/bin/lttng-sessiond/ust-app.h [deleted file]
src/bin/lttng-sessiond/ust-app.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-clock.h [deleted file]
src/bin/lttng-sessiond/ust-clock.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-consumer.cpp
src/bin/lttng-sessiond/ust-consumer.h [deleted file]
src/bin/lttng-sessiond/ust-consumer.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-ctl-internal.h [deleted file]
src/bin/lttng-sessiond/ust-ctl-internal.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-error-internal.h [deleted file]
src/bin/lttng-sessiond/ust-error-internal.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-field-utils.cpp
src/bin/lttng-sessiond/ust-field-utils.h [deleted file]
src/bin/lttng-sessiond/ust-field-utils.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-metadata.cpp
src/bin/lttng-sessiond/ust-registry.cpp
src/bin/lttng-sessiond/ust-registry.h [deleted file]
src/bin/lttng-sessiond/ust-registry.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-sigbus.cpp
src/bin/lttng-sessiond/ust-sigbus.h [deleted file]
src/bin/lttng-sessiond/ust-sigbus.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/utils.cpp
src/bin/lttng-sessiond/utils.h [deleted file]
src/bin/lttng-sessiond/utils.hpp [new file with mode: 0644]
src/bin/lttng/Makefile.am
src/bin/lttng/command.h [deleted file]
src/bin/lttng/command.hpp [new file with mode: 0644]
src/bin/lttng/commands/add_context.cpp
src/bin/lttng/commands/add_trigger.cpp
src/bin/lttng/commands/clear.cpp
src/bin/lttng/commands/create.cpp
src/bin/lttng/commands/destroy.cpp
src/bin/lttng/commands/disable_channels.cpp
src/bin/lttng/commands/disable_events.cpp
src/bin/lttng/commands/disable_rotation.cpp
src/bin/lttng/commands/enable_channels.cpp
src/bin/lttng/commands/enable_events.cpp
src/bin/lttng/commands/enable_rotation.cpp
src/bin/lttng/commands/help.cpp
src/bin/lttng/commands/list.cpp
src/bin/lttng/commands/list_triggers.cpp
src/bin/lttng/commands/load.cpp
src/bin/lttng/commands/metadata.cpp
src/bin/lttng/commands/regenerate.cpp
src/bin/lttng/commands/remove_trigger.cpp
src/bin/lttng/commands/rotate.cpp
src/bin/lttng/commands/save.cpp
src/bin/lttng/commands/set_session.cpp
src/bin/lttng/commands/snapshot.cpp
src/bin/lttng/commands/start.cpp
src/bin/lttng/commands/status.cpp
src/bin/lttng/commands/stop.cpp
src/bin/lttng/commands/track-untrack.cpp
src/bin/lttng/commands/version.cpp
src/bin/lttng/commands/view.cpp
src/bin/lttng/conf.cpp
src/bin/lttng/conf.h [deleted file]
src/bin/lttng/conf.hpp [new file with mode: 0644]
src/bin/lttng/loglevel.cpp
src/bin/lttng/loglevel.h [deleted file]
src/bin/lttng/loglevel.hpp [new file with mode: 0644]
src/bin/lttng/lttng.cpp
src/bin/lttng/uprobe.cpp
src/bin/lttng/uprobe.h [deleted file]
src/bin/lttng/uprobe.hpp [new file with mode: 0644]
src/bin/lttng/utils.cpp
src/bin/lttng/utils.h [deleted file]
src/bin/lttng/utils.hpp [new file with mode: 0644]
src/common/Makefile.am
src/common/actions/action.cpp
src/common/actions/list.cpp
src/common/actions/notify.cpp
src/common/actions/path.cpp
src/common/actions/rate-policy.cpp
src/common/actions/rotate-session.cpp
src/common/actions/snapshot-session.cpp
src/common/actions/start-session.cpp
src/common/actions/stop-session.cpp
src/common/align.h [deleted file]
src/common/align.hpp [new file with mode: 0644]
src/common/argpar-utils/Makefile.am [deleted file]
src/common/argpar-utils/argpar-utils.cpp
src/common/argpar-utils/argpar-utils.h [deleted file]
src/common/argpar-utils/argpar-utils.hpp [new file with mode: 0644]
src/common/argpar/Makefile.am [deleted file]
src/common/buffer-view.cpp
src/common/buffer-view.h [deleted file]
src/common/buffer-view.hpp [new file with mode: 0644]
src/common/bug.h [deleted file]
src/common/bug.hpp [new file with mode: 0644]
src/common/bytecode/Makefile.am [deleted file]
src/common/bytecode/bytecode.cpp
src/common/bytecode/bytecode.h [deleted file]
src/common/bytecode/bytecode.hpp [new file with mode: 0644]
src/common/common.h [deleted file]
src/common/common.hpp [new file with mode: 0644]
src/common/compat/Makefile.am [deleted file]
src/common/compat/compat-fcntl.cpp
src/common/compat/directory-handle.cpp
src/common/compat/directory-handle.h [deleted file]
src/common/compat/directory-handle.hpp [new file with mode: 0644]
src/common/compat/dirent.h [deleted file]
src/common/compat/dirent.hpp [new file with mode: 0644]
src/common/compat/endian.h [deleted file]
src/common/compat/endian.hpp [new file with mode: 0644]
src/common/compat/errno.h [deleted file]
src/common/compat/errno.hpp [new file with mode: 0644]
src/common/compat/fcntl.h [deleted file]
src/common/compat/fcntl.hpp [new file with mode: 0644]
src/common/compat/getenv.h [deleted file]
src/common/compat/getenv.hpp [new file with mode: 0644]
src/common/compat/mman.h [deleted file]
src/common/compat/mman.hpp [new file with mode: 0644]
src/common/compat/netdb.h [deleted file]
src/common/compat/netdb.hpp [new file with mode: 0644]
src/common/compat/path.h [deleted file]
src/common/compat/path.hpp [new file with mode: 0644]
src/common/compat/paths.h [deleted file]
src/common/compat/paths.hpp [new file with mode: 0644]
src/common/compat/poll.cpp
src/common/compat/poll.h [deleted file]
src/common/compat/poll.hpp [new file with mode: 0644]
src/common/compat/pthread.h [deleted file]
src/common/compat/pthread.hpp [new file with mode: 0644]
src/common/compat/socket.h [deleted file]
src/common/compat/socket.hpp [new file with mode: 0644]
src/common/compat/string.h [deleted file]
src/common/compat/string.hpp [new file with mode: 0644]
src/common/compat/tid.h [deleted file]
src/common/compat/tid.hpp [new file with mode: 0644]
src/common/compat/time.h [deleted file]
src/common/compat/time.hpp [new file with mode: 0644]
src/common/conditions/buffer-usage.cpp
src/common/conditions/condition.cpp
src/common/conditions/event-rule-matches.cpp
src/common/conditions/session-consumed-size.cpp
src/common/conditions/session-rotation.cpp
src/common/config/Makefile.am [deleted file]
src/common/config/config-internal.h [deleted file]
src/common/config/config-internal.hpp [new file with mode: 0644]
src/common/config/config-session-abi.h [deleted file]
src/common/config/config-session-abi.hpp [new file with mode: 0644]
src/common/config/session-config.cpp
src/common/config/session-config.h [deleted file]
src/common/config/session-config.hpp [new file with mode: 0644]
src/common/config/session.xsd [deleted file]
src/common/consumer/Makefile.am [deleted file]
src/common/consumer/consumer-metadata-cache.cpp
src/common/consumer/consumer-metadata-cache.h [deleted file]
src/common/consumer/consumer-metadata-cache.hpp [new file with mode: 0644]
src/common/consumer/consumer-stream.cpp
src/common/consumer/consumer-stream.h [deleted file]
src/common/consumer/consumer-stream.hpp [new file with mode: 0644]
src/common/consumer/consumer-testpoint.h [deleted file]
src/common/consumer/consumer-testpoint.hpp [new file with mode: 0644]
src/common/consumer/consumer-timer.cpp
src/common/consumer/consumer-timer.h [deleted file]
src/common/consumer/consumer-timer.hpp [new file with mode: 0644]
src/common/consumer/consumer.cpp
src/common/consumer/consumer.h [deleted file]
src/common/consumer/consumer.hpp [new file with mode: 0644]
src/common/consumer/metadata-bucket.cpp
src/common/consumer/metadata-bucket.h [deleted file]
src/common/consumer/metadata-bucket.hpp [new file with mode: 0644]
src/common/context.cpp
src/common/context.h [deleted file]
src/common/context.hpp [new file with mode: 0644]
src/common/credentials.cpp
src/common/credentials.h [deleted file]
src/common/credentials.hpp [new file with mode: 0644]
src/common/daemonize.cpp
src/common/daemonize.h [deleted file]
src/common/daemonize.hpp [new file with mode: 0644]
src/common/defaults.cpp
src/common/defaults.h [deleted file]
src/common/defaults.hpp [new file with mode: 0644]
src/common/domain.cpp
src/common/dynamic-array.cpp
src/common/dynamic-array.h [deleted file]
src/common/dynamic-array.hpp [new file with mode: 0644]
src/common/dynamic-buffer.cpp
src/common/dynamic-buffer.h [deleted file]
src/common/dynamic-buffer.hpp [new file with mode: 0644]
src/common/endpoint.cpp
src/common/error-query.cpp
src/common/error.cpp
src/common/error.h [deleted file]
src/common/error.hpp [new file with mode: 0644]
src/common/evaluation.cpp
src/common/event-expr/event-expr.cpp
src/common/event-field-value.cpp
src/common/event-rule/event-rule.cpp
src/common/event-rule/jul-logging.cpp
src/common/event-rule/kernel-kprobe.cpp
src/common/event-rule/kernel-syscall.cpp
src/common/event-rule/kernel-tracepoint.cpp
src/common/event-rule/kernel-uprobe.cpp
src/common/event-rule/log4j-logging.cpp
src/common/event-rule/python-logging.cpp
src/common/event-rule/user-tracepoint.cpp
src/common/event.cpp
src/common/fd-handle.cpp
src/common/fd-handle.h [deleted file]
src/common/fd-handle.hpp [new file with mode: 0644]
src/common/fd-tracker/Makefile.am [deleted file]
src/common/fd-tracker/fd-tracker.cpp
src/common/fd-tracker/fd-tracker.h [deleted file]
src/common/fd-tracker/fd-tracker.hpp [new file with mode: 0644]
src/common/fd-tracker/inode.cpp
src/common/fd-tracker/inode.h [deleted file]
src/common/fd-tracker/inode.hpp [new file with mode: 0644]
src/common/fd-tracker/utils-poll.cpp
src/common/fd-tracker/utils.cpp
src/common/fd-tracker/utils.h [deleted file]
src/common/fd-tracker/utils.hpp [new file with mode: 0644]
src/common/filter-grammar-test.cpp
src/common/filter.cpp
src/common/filter.h [deleted file]
src/common/filter.hpp [new file with mode: 0644]
src/common/filter/Makefile.am [deleted file]
src/common/filter/filter-ast.h [deleted file]
src/common/filter/filter-ast.hpp [new file with mode: 0644]
src/common/filter/filter-ir.h [deleted file]
src/common/filter/filter-ir.hpp [new file with mode: 0644]
src/common/filter/filter-lexer.lpp
src/common/filter/filter-parser.ypp
src/common/filter/filter-symbols.h [deleted file]
src/common/filter/filter-symbols.hpp [new file with mode: 0644]
src/common/filter/filter-visitor-generate-bytecode.cpp
src/common/filter/filter-visitor-generate-ir.cpp
src/common/filter/filter-visitor-ir-check-binary-comparator.cpp
src/common/filter/filter-visitor-ir-check-binary-op-nesting.cpp
src/common/filter/filter-visitor-ir-normalize-glob-patterns.cpp
src/common/filter/filter-visitor-ir-validate-globbing.cpp
src/common/filter/filter-visitor-ir-validate-string.cpp
src/common/filter/filter-visitor-xml.cpp
src/common/filter/memstream.h [deleted file]
src/common/filter/memstream.hpp [new file with mode: 0644]
src/common/fs-handle-internal.h [deleted file]
src/common/fs-handle-internal.hpp [new file with mode: 0644]
src/common/fs-handle.cpp
src/common/fs-handle.h [deleted file]
src/common/fs-handle.hpp [new file with mode: 0644]
src/common/futex.cpp
src/common/futex.h [deleted file]
src/common/futex.hpp [new file with mode: 0644]
src/common/hashtable/Makefile.am [deleted file]
src/common/hashtable/hashtable-symbols.h [deleted file]
src/common/hashtable/hashtable-symbols.hpp [new file with mode: 0644]
src/common/hashtable/hashtable.cpp
src/common/hashtable/hashtable.h [deleted file]
src/common/hashtable/hashtable.hpp [new file with mode: 0644]
src/common/hashtable/utils.cpp
src/common/hashtable/utils.h [deleted file]
src/common/hashtable/utils.hpp [new file with mode: 0644]
src/common/health/Makefile.am [deleted file]
src/common/health/health.cpp
src/common/index-allocator.cpp
src/common/index-allocator.h [deleted file]
src/common/index-allocator.hpp [new file with mode: 0644]
src/common/index/Makefile.am [deleted file]
src/common/index/ctf-index.h [deleted file]
src/common/index/ctf-index.hpp [new file with mode: 0644]
src/common/index/index.cpp
src/common/index/index.h [deleted file]
src/common/index/index.hpp [new file with mode: 0644]
src/common/ini-config/Makefile.am [deleted file]
src/common/ini-config/ini-config.cpp
src/common/ini-config/ini-config.h [deleted file]
src/common/ini-config/ini-config.hpp [new file with mode: 0644]
src/common/ini-config/ini.cpp
src/common/ini-config/ini.h [deleted file]
src/common/ini-config/ini.hpp [new file with mode: 0644]
src/common/kernel-consumer/Makefile.am [deleted file]
src/common/kernel-consumer/kernel-consumer.cpp
src/common/kernel-consumer/kernel-consumer.h [deleted file]
src/common/kernel-consumer/kernel-consumer.hpp [new file with mode: 0644]
src/common/kernel-ctl/Makefile.am [deleted file]
src/common/kernel-ctl/kernel-ctl.cpp
src/common/kernel-ctl/kernel-ctl.h [deleted file]
src/common/kernel-ctl/kernel-ctl.hpp [new file with mode: 0644]
src/common/kernel-ctl/kernel-ioctl.h [deleted file]
src/common/kernel-ctl/kernel-ioctl.hpp [new file with mode: 0644]
src/common/kernel-probe.cpp
src/common/location.cpp
src/common/log-level-rule.cpp
src/common/lttng-elf.cpp
src/common/lttng-elf.h [deleted file]
src/common/lttng-elf.hpp [new file with mode: 0644]
src/common/lttng-kernel-old.h [deleted file]
src/common/lttng-kernel-old.hpp [new file with mode: 0644]
src/common/lttng-kernel.h [deleted file]
src/common/lttng-kernel.hpp [new file with mode: 0644]
src/common/macros.h [deleted file]
src/common/macros.hpp [new file with mode: 0644]
src/common/mi-lttng.cpp
src/common/mi-lttng.h [deleted file]
src/common/mi-lttng.hpp [new file with mode: 0644]
src/common/notification.cpp
src/common/optional.h [deleted file]
src/common/optional.hpp [new file with mode: 0644]
src/common/payload-view.cpp
src/common/payload-view.h [deleted file]
src/common/payload-view.hpp [new file with mode: 0644]
src/common/payload.cpp
src/common/payload.h [deleted file]
src/common/payload.hpp [new file with mode: 0644]
src/common/pipe.cpp
src/common/pipe.h [deleted file]
src/common/pipe.hpp [new file with mode: 0644]
src/common/readwrite.cpp
src/common/readwrite.h [deleted file]
src/common/readwrite.hpp [new file with mode: 0644]
src/common/relayd/Makefile.am [deleted file]
src/common/relayd/relayd.cpp
src/common/relayd/relayd.h [deleted file]
src/common/relayd/relayd.hpp [new file with mode: 0644]
src/common/runas.cpp
src/common/runas.h [deleted file]
src/common/runas.hpp [new file with mode: 0644]
src/common/session-descriptor.cpp
src/common/session.xsd [new file with mode: 0644]
src/common/sessiond-comm/Makefile.am [deleted file]
src/common/sessiond-comm/agent.h [deleted file]
src/common/sessiond-comm/agent.hpp [new file with mode: 0644]
src/common/sessiond-comm/inet.cpp
src/common/sessiond-comm/inet.h [deleted file]
src/common/sessiond-comm/inet.hpp [new file with mode: 0644]
src/common/sessiond-comm/inet6.cpp
src/common/sessiond-comm/inet6.h [deleted file]
src/common/sessiond-comm/inet6.hpp [new file with mode: 0644]
src/common/sessiond-comm/relayd.h [deleted file]
src/common/sessiond-comm/relayd.hpp [new file with mode: 0644]
src/common/sessiond-comm/sessiond-comm.cpp
src/common/sessiond-comm/sessiond-comm.h [deleted file]
src/common/sessiond-comm/sessiond-comm.hpp [new file with mode: 0644]
src/common/shm.cpp
src/common/shm.h [deleted file]
src/common/shm.hpp [new file with mode: 0644]
src/common/snapshot.cpp
src/common/snapshot.h [deleted file]
src/common/snapshot.hpp [new file with mode: 0644]
src/common/spawn-viewer.cpp
src/common/spawn-viewer.h [deleted file]
src/common/spawn-viewer.hpp [new file with mode: 0644]
src/common/string-utils/Makefile.am [deleted file]
src/common/string-utils/format.h [deleted file]
src/common/string-utils/format.hpp [new file with mode: 0644]
src/common/string-utils/string-utils.cpp
src/common/string-utils/string-utils.h [deleted file]
src/common/string-utils/string-utils.hpp [new file with mode: 0644]
src/common/testpoint/Makefile.am [deleted file]
src/common/testpoint/testpoint.cpp
src/common/testpoint/testpoint.h [deleted file]
src/common/testpoint/testpoint.hpp [new file with mode: 0644]
src/common/thread.cpp
src/common/thread.h [deleted file]
src/common/thread.hpp [new file with mode: 0644]
src/common/time.cpp
src/common/time.h [deleted file]
src/common/time.hpp [new file with mode: 0644]
src/common/trace-chunk-registry.h [deleted file]
src/common/trace-chunk-registry.hpp [new file with mode: 0644]
src/common/trace-chunk.cpp
src/common/trace-chunk.h [deleted file]
src/common/trace-chunk.hpp [new file with mode: 0644]
src/common/tracker.cpp
src/common/tracker.h [deleted file]
src/common/tracker.hpp [new file with mode: 0644]
src/common/trigger.cpp
src/common/unix.cpp
src/common/unix.h [deleted file]
src/common/unix.hpp [new file with mode: 0644]
src/common/uri.cpp
src/common/uri.h [deleted file]
src/common/uri.hpp [new file with mode: 0644]
src/common/userspace-probe.cpp
src/common/ust-consumer/Makefile.am [deleted file]
src/common/ust-consumer/ust-consumer.cpp
src/common/ust-consumer/ust-consumer.h [deleted file]
src/common/ust-consumer/ust-consumer.hpp [new file with mode: 0644]
src/common/utils.cpp
src/common/utils.h [deleted file]
src/common/utils.hpp [new file with mode: 0644]
src/common/uuid.cpp
src/common/uuid.h [deleted file]
src/common/uuid.hpp [new file with mode: 0644]
src/common/waiter.cpp
src/common/waiter.h [deleted file]
src/common/waiter.hpp [new file with mode: 0644]
src/lib/lttng-ctl/Makefile.am
src/lib/lttng-ctl/channel.cpp
src/lib/lttng-ctl/clear.cpp
src/lib/lttng-ctl/destruction-handle.cpp
src/lib/lttng-ctl/event.cpp
src/lib/lttng-ctl/load.cpp
src/lib/lttng-ctl/lttng-ctl-health.cpp
src/lib/lttng-ctl/lttng-ctl-helper.h [deleted file]
src/lib/lttng-ctl/lttng-ctl-helper.hpp [new file with mode: 0644]
src/lib/lttng-ctl/lttng-ctl.cpp
src/lib/lttng-ctl/rotate.cpp
src/lib/lttng-ctl/save.cpp
src/lib/lttng-ctl/snapshot.cpp
src/lib/lttng-ctl/tracker.cpp
src/vendor/msgpack/lttng-config.h
src/vendor/nlohmann/json.hpp [new file with mode: 0644]
tests/regression/kernel/select_poll_epoll.c
tests/regression/tools/live/Makefile.am
tests/regression/tools/live/live_test.cpp
tests/regression/tools/notification/Makefile.am
tests/regression/tools/notification/consumer_testpoints.cpp
tests/regression/tools/notification/default_pipe_size_getter.cpp
tests/regression/tools/notification/notification.cpp
tests/regression/tools/notification/sessiond_testpoints.cpp
tests/regression/tools/save-load/test_autoload
tests/regression/tools/save-load/test_load
tests/regression/tools/trigger/hidden/hidden_trigger.cpp
tests/regression/tools/trigger/name/trigger_name.cpp
tests/regression/tools/trigger/utils/Makefile.am
tests/regression/tools/trigger/utils/register-some-triggers.cpp
tests/regression/ust/clock-override/lttng-ust-clock-override-test.c
tests/regression/ust/getcpu-override/lttng-ust-getcpu-override-test.c
tests/regression/ust/ust-dl/prog.c
tests/unit/Makefile.am
tests/unit/ini_config/Makefile.am
tests/unit/ini_config/ini_config.cpp
tests/unit/test_action.cpp
tests/unit/test_buffer_view.cpp
tests/unit/test_condition.cpp
tests/unit/test_directory_handle.cpp
tests/unit/test_event_expr_to_bytecode.cpp
tests/unit/test_event_rule.cpp
tests/unit/test_fd_tracker.cpp
tests/unit/test_kernel_data.cpp
tests/unit/test_kernel_probe.cpp
tests/unit/test_log_level_rule.cpp
tests/unit/test_notification.cpp
tests/unit/test_payload.cpp
tests/unit/test_rate_policy.cpp
tests/unit/test_relayd_backward_compat_group_by_session.cpp
tests/unit/test_session.cpp
tests/unit/test_string_utils.cpp
tests/unit/test_unix_socket.cpp
tests/unit/test_uri.cpp
tests/unit/test_ust_data.cpp
tests/unit/test_utils_compat_poll.cpp
tests/unit/test_utils_compat_pthread.cpp
tests/unit/test_utils_expand_path.cpp
tests/unit/test_utils_parse_size_suffix.cpp
tests/unit/test_utils_parse_time_suffix.cpp
tests/unit/test_uuid.cpp
tests/utils/testapp/Makefile.am
tests/utils/testapp/gen-ns-events/gen-ns-events.cpp
tests/utils/testapp/gen-syscall-events/gen-syscall-events.cpp
tests/utils/testapp/gen-ust-events-ns/gen-ust-events-ns.cpp
tests/utils/testapp/gen-ust-events/gen-ust-events.cpp
tests/utils/testapp/gen-ust-nevents-str/gen-ust-nevents-str.cpp
tests/utils/testapp/gen-ust-nevents/gen-ust-nevents.cpp
tests/utils/testapp/gen-ust-tracef/gen-ust-tracef.cpp
tests/utils/testapp/signal-helper.h [deleted file]
tests/utils/testapp/signal-helper.hpp [new file with mode: 0644]
tests/utils/testapp/userspace-probe-elf-cxx-binary/Makefile.am
tests/utils/testapp/userspace-probe-elf-cxx-binary/test_class.cpp
tests/utils/testapp/userspace-probe-elf-cxx-binary/test_class.h [deleted file]
tests/utils/testapp/userspace-probe-elf-cxx-binary/test_class.hpp [new file with mode: 0644]
tests/utils/testapp/userspace-probe-elf-cxx-binary/userspace-probe-elf-cxx-binary.cpp
tests/utils/utils.cpp
tests/utils/utils.sh
tests/utils/xml-utils/extract_xml.cpp
tests/utils/xml-utils/validate_xml.cpp

index 6166b25a0bc60a805ed60fa24d966ccb69f86d5c..a8f595a2c17ed39c879ffc08a4fc19a406ae915f 100644 (file)
@@ -1142,25 +1142,6 @@ AC_CONFIG_FILES([
        extras/core-handler/Makefile
        src/Makefile
        src/common/Makefile
-       src/common/argpar/Makefile
-       src/common/argpar-utils/Makefile
-       src/common/bytecode/Makefile
-       src/common/kernel-ctl/Makefile
-       src/common/kernel-consumer/Makefile
-       src/common/consumer/Makefile
-       src/common/ust-consumer/Makefile
-       src/common/hashtable/Makefile
-       src/common/sessiond-comm/Makefile
-       src/common/compat/Makefile
-       src/common/relayd/Makefile
-       src/common/testpoint/Makefile
-       src/common/index/Makefile
-       src/common/health/Makefile
-       src/common/config/Makefile
-       src/common/ini-config/Makefile
-       src/common/string-utils/Makefile
-       src/common/fd-tracker/Makefile
-       src/common/filter/Makefile
        src/lib/Makefile
        src/lib/lttng-ctl/Makefile
        src/lib/lttng-ctl/lttng-ctl.pc
index 4a251556938d335630652d3208d599ecceb78a54..d1d5d8721471d9809cb38c75e7eae37ed72e0e61 100644 (file)
@@ -16,7 +16,7 @@
 #include <sys/time.h>
 #include <time.h>
 
-#include <common/macros.h>
+#include <common/macros.hpp>
 
 static int print_capture(const struct lttng_condition *condition,
                const struct lttng_event_field_value *capture,
index 209f5bd61d4293a0c740b74ccbd4a8d22b510a11..069e1079e88344e45e8ee115e47e9dfa9b2de95d 100644 (file)
@@ -21,7 +21,7 @@ MAINTAINERCLEANFILES = lttng_wrap.c lttng.py
 nodist__lttng_la_SOURCES = lttng_wrap.c
 _lttng_la_LDFLAGS = -module
 _lttng_la_LIBADD =     $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la               \
-                       $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la            \
+                       $(top_builddir)/src/common/libsessiond-comm.la          \
                        $(top_builddir)/src/common/libcommon.la
 
 lttng_wrap.c: lttng.i
index 6fe724b3ae0ee0605f9d97aff4cc0ebe4f4c5761..d840d58dcd8458487348a993feddde279d531485 100644 (file)
@@ -163,51 +163,51 @@ lttngeventruleinclude_HEADERS= \
        lttng/event-rule/user-tracepoint.h
 
 noinst_HEADERS = \
-       lttng/action/action-internal.h \
-       lttng/action/list-internal.h \
-       lttng/action/notify-internal.h \
-       lttng/action/path-internal.h \
-       lttng/action/rotate-session-internal.h \
-       lttng/action/snapshot-session-internal.h \
-       lttng/action/start-session-internal.h \
-       lttng/action/stop-session-internal.h \
-       lttng/action/rate-policy-internal.h \
-       lttng/channel-internal.h \
-       lttng/condition/buffer-usage-internal.h \
-       lttng/condition/condition-internal.h \
-       lttng/condition/evaluation-internal.h \
-       lttng/condition/event-rule-matches-internal.h \
-       lttng/condition/session-consumed-size-internal.h \
-       lttng/condition/session-rotation-internal.h \
-       lttng/domain-internal.h \
-       lttng/endpoint-internal.h \
-       lttng/error-query-internal.h \
-       lttng/event-expr-internal.h \
-       lttng/event-field-value-internal.h \
-       lttng/event-internal.h \
-       lttng/event-rule/event-rule-internal.h \
-       lttng/event-rule/jul-logging-internal.h \
-       lttng/event-rule/kernel-kprobe-internal.h \
-       lttng/event-rule/kernel-syscall-internal.h \
-       lttng/event-rule/kernel-tracepoint-internal.h \
-       lttng/event-rule/kernel-uprobe-internal.h \
-       lttng/event-rule/log4j-logging-internal.h \
-       lttng/event-rule/python-logging-internal.h \
-       lttng/event-rule/user-tracepoint-internal.h \
-       lttng/health-internal.h \
-       lttng/kernel-probe-internal.h \
-       lttng/load-internal.h \
-       lttng/location-internal.h \
-       lttng/log-level-rule-internal.h \
-       lttng/notification/channel-internal.h \
-       lttng/notification/notification-internal.h \
-       lttng/ref-internal.h \
-       lttng/rotate-internal.h \
-       lttng/save-internal.h \
-       lttng/session-descriptor-internal.h \
-       lttng/session-internal.h \
-       lttng/snapshot-internal.h \
-       lttng/trigger/trigger-internal.h \
-       lttng/userspace-probe-internal.h \
-       version.h \
+       lttng/action/action-internal.hpp \
+       lttng/action/list-internal.hpp \
+       lttng/action/notify-internal.hpp \
+       lttng/action/path-internal.hpp \
+       lttng/action/rotate-session-internal.hpp \
+       lttng/action/snapshot-session-internal.hpp \
+       lttng/action/start-session-internal.hpp \
+       lttng/action/stop-session-internal.hpp \
+       lttng/action/rate-policy-internal.hpp \
+       lttng/channel-internal.hpp \
+       lttng/condition/buffer-usage-internal.hpp \
+       lttng/condition/condition-internal.hpp \
+       lttng/condition/evaluation-internal.hpp \
+       lttng/condition/event-rule-matches-internal.hpp \
+       lttng/condition/session-consumed-size-internal.hpp \
+       lttng/condition/session-rotation-internal.hpp \
+       lttng/domain-internal.hpp \
+       lttng/endpoint-internal.hpp \
+       lttng/error-query-internal.hpp \
+       lttng/event-expr-internal.hpp \
+       lttng/event-field-value-internal.hpp \
+       lttng/event-internal.hpp \
+       lttng/event-rule/event-rule-internal.hpp \
+       lttng/event-rule/jul-logging-internal.hpp \
+       lttng/event-rule/kernel-kprobe-internal.hpp \
+       lttng/event-rule/kernel-syscall-internal.hpp \
+       lttng/event-rule/kernel-tracepoint-internal.hpp \
+       lttng/event-rule/kernel-uprobe-internal.hpp \
+       lttng/event-rule/log4j-logging-internal.hpp \
+       lttng/event-rule/python-logging-internal.hpp \
+       lttng/event-rule/user-tracepoint-internal.hpp \
+       lttng/health-internal.hpp \
+       lttng/kernel-probe-internal.hpp \
+       lttng/load-internal.hpp \
+       lttng/location-internal.hpp \
+       lttng/log-level-rule-internal.hpp \
+       lttng/notification/channel-internal.hpp \
+       lttng/notification/notification-internal.hpp \
+       lttng/ref-internal.hpp \
+       lttng/rotate-internal.hpp \
+       lttng/save-internal.hpp \
+       lttng/session-descriptor-internal.hpp \
+       lttng/session-internal.hpp \
+       lttng/snapshot-internal.hpp \
+       lttng/trigger/trigger-internal.hpp \
+       lttng/userspace-probe-internal.hpp \
+       version.hpp \
        version.i
diff --git a/include/lttng/action/action-internal.h b/include/lttng/action/action-internal.h
deleted file mode 100644 (file)
index 71270a8..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ACTION_INTERNAL_H
-#define LTTNG_ACTION_INTERNAL_H
-
-#include <common/buffer-view.h>
-#include <common/dynamic-buffer.h>
-#include <common/macros.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/lttng.h>
-#include <pthread.h>
-#include <stdbool.h>
-#include <sys/types.h>
-#include <urcu/ref.h>
-
-struct lttng_rate_policy;
-struct mi_writer;
-struct mi_lttng_error_query_callbacks;
-struct lttng_trigger;
-
-typedef bool (*action_validate_cb)(struct lttng_action *action);
-typedef void (*action_destroy_cb)(struct lttng_action *action);
-typedef int (*action_serialize_cb)(struct lttng_action *action,
-               struct lttng_payload *payload);
-typedef bool (*action_equal_cb)(const struct lttng_action *a,
-               const struct lttng_action *b);
-typedef ssize_t (*action_create_from_payload_cb)(
-               struct lttng_payload_view *view,
-               struct lttng_action **action);
-typedef const struct lttng_rate_policy *(*action_get_rate_policy_cb)(
-               const struct lttng_action *action);
-typedef enum lttng_action_status (*action_add_error_query_results_cb)(
-               const struct lttng_action *action,
-               struct lttng_error_query_results *results);
-typedef enum lttng_error_code (*action_mi_serialize_cb)(
-               const struct lttng_action *condition, struct mi_writer *writer);
-
-struct lttng_action {
-       struct urcu_ref ref;
-       enum lttng_action_type type;
-       action_validate_cb validate;
-       action_serialize_cb serialize;
-       action_equal_cb equal;
-       action_destroy_cb destroy;
-       action_get_rate_policy_cb get_rate_policy;
-       action_add_error_query_results_cb add_error_query_results;
-       action_mi_serialize_cb mi_serialize;
-
-       /* Internal use only. */
-
-       /* The number of time the actions was enqueued for execution. */
-       uint64_t execution_request_counter;
-       /*
-        * The number of time the action was actually executed.
-        * Action rate policy can impact on this number.
-        * */
-       uint64_t execution_counter;
-       /*
-        * The number of time the action execution failed.
-        * An unsigned long is used to use a type which makes atomic
-        * operations possible.
-        */
-       unsigned long execution_failure_counter;
-};
-
-struct lttng_action_comm {
-       /* enum lttng_action_type */
-       int8_t action_type;
-} LTTNG_PACKED;
-
-void lttng_action_init(struct lttng_action *action,
-               enum lttng_action_type type,
-               action_validate_cb validate,
-               action_serialize_cb serialize,
-               action_equal_cb equal,
-               action_destroy_cb destroy,
-               action_get_rate_policy_cb get_rate_policy,
-               action_add_error_query_results_cb add_error_query_results,
-               action_mi_serialize_cb mi);
-
-bool lttng_action_validate(struct lttng_action *action);
-
-int lttng_action_serialize(struct lttng_action *action,
-               struct lttng_payload *buf);
-
-ssize_t lttng_action_create_from_payload(struct lttng_payload_view *view,
-               struct lttng_action **action);
-
-bool lttng_action_is_equal(const struct lttng_action *a,
-               const struct lttng_action *b);
-
-void lttng_action_get(struct lttng_action *action);
-
-void lttng_action_put(struct lttng_action *action);
-
-const char* lttng_action_type_string(enum lttng_action_type action_type);
-
-void lttng_action_increase_execution_request_count(struct lttng_action *action);
-
-void lttng_action_increase_execution_count(struct lttng_action *action);
-
-void lttng_action_increase_execution_failure_count(struct lttng_action *action);
-
-bool lttng_action_should_execute(const struct lttng_action *action);
-
-enum lttng_action_status lttng_action_add_error_query_results(
-               const struct lttng_action *action,
-               struct lttng_error_query_results *results);
-
-/*
- * For use by the various lttng_action implementation. Implements the default
- * behavior to the generic error "execution failure counter" that all actions
- * (except list, which passes-through) provide.
- */
-enum lttng_action_status lttng_action_generic_add_error_query_results(
-               const struct lttng_action *action,
-               struct lttng_error_query_results *results);
-enum lttng_error_code lttng_action_mi_serialize(const struct lttng_trigger *trigger,
-               const struct lttng_action *action,
-               struct mi_writer *writer,
-               const struct mi_lttng_error_query_callbacks
-                               *error_query_callbacks,
-               struct lttng_dynamic_array *action_path_indexes);
-
-#endif /* LTTNG_ACTION_INTERNAL_H */
diff --git a/include/lttng/action/action-internal.hpp b/include/lttng/action/action-internal.hpp
new file mode 100644 (file)
index 0000000..996e166
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ACTION_INTERNAL_H
+#define LTTNG_ACTION_INTERNAL_H
+
+#include <common/buffer-view.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/macros.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/lttng.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <urcu/ref.h>
+
+struct lttng_rate_policy;
+struct mi_writer;
+struct mi_lttng_error_query_callbacks;
+struct lttng_trigger;
+
+typedef bool (*action_validate_cb)(struct lttng_action *action);
+typedef void (*action_destroy_cb)(struct lttng_action *action);
+typedef int (*action_serialize_cb)(struct lttng_action *action,
+               struct lttng_payload *payload);
+typedef bool (*action_equal_cb)(const struct lttng_action *a,
+               const struct lttng_action *b);
+typedef ssize_t (*action_create_from_payload_cb)(
+               struct lttng_payload_view *view,
+               struct lttng_action **action);
+typedef const struct lttng_rate_policy *(*action_get_rate_policy_cb)(
+               const struct lttng_action *action);
+typedef enum lttng_action_status (*action_add_error_query_results_cb)(
+               const struct lttng_action *action,
+               struct lttng_error_query_results *results);
+typedef enum lttng_error_code (*action_mi_serialize_cb)(
+               const struct lttng_action *condition, struct mi_writer *writer);
+
+struct lttng_action {
+       struct urcu_ref ref;
+       enum lttng_action_type type;
+       action_validate_cb validate;
+       action_serialize_cb serialize;
+       action_equal_cb equal;
+       action_destroy_cb destroy;
+       action_get_rate_policy_cb get_rate_policy;
+       action_add_error_query_results_cb add_error_query_results;
+       action_mi_serialize_cb mi_serialize;
+
+       /* Internal use only. */
+
+       /* The number of time the actions was enqueued for execution. */
+       uint64_t execution_request_counter;
+       /*
+        * The number of time the action was actually executed.
+        * Action rate policy can impact on this number.
+        * */
+       uint64_t execution_counter;
+       /*
+        * The number of time the action execution failed.
+        * An unsigned long is used to use a type which makes atomic
+        * operations possible.
+        */
+       unsigned long execution_failure_counter;
+};
+
+struct lttng_action_comm {
+       /* enum lttng_action_type */
+       int8_t action_type;
+} LTTNG_PACKED;
+
+void lttng_action_init(struct lttng_action *action,
+               enum lttng_action_type type,
+               action_validate_cb validate,
+               action_serialize_cb serialize,
+               action_equal_cb equal,
+               action_destroy_cb destroy,
+               action_get_rate_policy_cb get_rate_policy,
+               action_add_error_query_results_cb add_error_query_results,
+               action_mi_serialize_cb mi);
+
+bool lttng_action_validate(struct lttng_action *action);
+
+int lttng_action_serialize(struct lttng_action *action,
+               struct lttng_payload *buf);
+
+ssize_t lttng_action_create_from_payload(struct lttng_payload_view *view,
+               struct lttng_action **action);
+
+bool lttng_action_is_equal(const struct lttng_action *a,
+               const struct lttng_action *b);
+
+void lttng_action_get(struct lttng_action *action);
+
+void lttng_action_put(struct lttng_action *action);
+
+const char* lttng_action_type_string(enum lttng_action_type action_type);
+
+void lttng_action_increase_execution_request_count(struct lttng_action *action);
+
+void lttng_action_increase_execution_count(struct lttng_action *action);
+
+void lttng_action_increase_execution_failure_count(struct lttng_action *action);
+
+bool lttng_action_should_execute(const struct lttng_action *action);
+
+enum lttng_action_status lttng_action_add_error_query_results(
+               const struct lttng_action *action,
+               struct lttng_error_query_results *results);
+
+/*
+ * For use by the various lttng_action implementation. Implements the default
+ * behavior to the generic error "execution failure counter" that all actions
+ * (except list, which passes-through) provide.
+ */
+enum lttng_action_status lttng_action_generic_add_error_query_results(
+               const struct lttng_action *action,
+               struct lttng_error_query_results *results);
+enum lttng_error_code lttng_action_mi_serialize(const struct lttng_trigger *trigger,
+               const struct lttng_action *action,
+               struct mi_writer *writer,
+               const struct mi_lttng_error_query_callbacks
+                               *error_query_callbacks,
+               struct lttng_dynamic_array *action_path_indexes);
+
+#endif /* LTTNG_ACTION_INTERNAL_H */
diff --git a/include/lttng/action/list-internal.h b/include/lttng/action/list-internal.h
deleted file mode 100644 (file)
index 231755f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ACTION_LIST_INTERNAL_H
-#define LTTNG_ACTION_LIST_INTERNAL_H
-
-#include <sys/types.h>
-
-#include <common/macros.h>
-
-struct lttng_action;
-struct lttng_payload_view;
-struct mi_writer;
-struct mi_lttng_error_query_callbacks;
-struct lttng_dynamic_array;
-struct lttng_trigger;
-
-/*
- * Create an action list from a payload view.
- *
- * On success, return the number of bytes consumed from `view`, and the created
- * list in `*list`. On failure, return -1.
- */
-extern ssize_t lttng_action_list_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_action **list);
-
-extern struct lttng_action *lttng_action_list_borrow_mutable_at_index(
-               const struct lttng_action *list, unsigned int index);
-
-enum lttng_error_code lttng_action_list_mi_serialize(const struct lttng_trigger *trigger,
-               const struct lttng_action *action,
-               struct mi_writer *writer,
-               const struct mi_lttng_error_query_callbacks
-                               *error_query_callbacks,
-               struct lttng_dynamic_array *action_path_indexes);
-
-#endif /* LTTNG_ACTION_LIST_INTERNAL_H */
diff --git a/include/lttng/action/list-internal.hpp b/include/lttng/action/list-internal.hpp
new file mode 100644 (file)
index 0000000..294a53c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ACTION_LIST_INTERNAL_H
+#define LTTNG_ACTION_LIST_INTERNAL_H
+
+#include <sys/types.h>
+
+#include <common/macros.hpp>
+
+struct lttng_action;
+struct lttng_payload_view;
+struct mi_writer;
+struct mi_lttng_error_query_callbacks;
+struct lttng_dynamic_array;
+struct lttng_trigger;
+
+/*
+ * Create an action list from a payload view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * list in `*list`. On failure, return -1.
+ */
+extern ssize_t lttng_action_list_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_action **list);
+
+extern struct lttng_action *lttng_action_list_borrow_mutable_at_index(
+               const struct lttng_action *list, unsigned int index);
+
+enum lttng_error_code lttng_action_list_mi_serialize(const struct lttng_trigger *trigger,
+               const struct lttng_action *action,
+               struct mi_writer *writer,
+               const struct mi_lttng_error_query_callbacks
+                               *error_query_callbacks,
+               struct lttng_dynamic_array *action_path_indexes);
+
+#endif /* LTTNG_ACTION_LIST_INTERNAL_H */
diff --git a/include/lttng/action/notify-internal.h b/include/lttng/action/notify-internal.h
deleted file mode 100644 (file)
index 8588ac2..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ACTION_NOTIFY_INTERNAL_H
-#define LTTNG_ACTION_NOTIFY_INTERNAL_H
-
-#include <lttng/action/notify.h>
-#include <lttng/action/action-internal.h>
-
-struct lttng_action_notify {
-       struct lttng_action parent;
-       struct lttng_rate_policy *policy;
-};
-
-ssize_t lttng_action_notify_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_action **action);
-
-#endif /* LTTNG_ACTION_NOTIFY_INTERNAL_H */
diff --git a/include/lttng/action/notify-internal.hpp b/include/lttng/action/notify-internal.hpp
new file mode 100644 (file)
index 0000000..c923019
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ACTION_NOTIFY_INTERNAL_H
+#define LTTNG_ACTION_NOTIFY_INTERNAL_H
+
+#include <lttng/action/notify.h>
+#include <lttng/action/action-internal.hpp>
+
+struct lttng_action_notify {
+       struct lttng_action parent;
+       struct lttng_rate_policy *policy;
+};
+
+ssize_t lttng_action_notify_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_NOTIFY_INTERNAL_H */
diff --git a/include/lttng/action/path-internal.h b/include/lttng/action/path-internal.h
deleted file mode 100644 (file)
index 8a255f0..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ACTION_PATH_INTERNAL_H
-#define LTTNG_ACTION_PATH_INTERNAL_H
-
-#include <lttng/action/path.h>
-#include <common/macros.h>
-#include <common/dynamic-array.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <sys/types.h>
-
-struct lttng_action_path {
-       struct lttng_dynamic_array indexes;
-};
-
-/* Assumes that 'dst' is uninitialized. */
-int lttng_action_path_copy(const struct lttng_action_path *src,
-               struct lttng_action_path *dst);
-
-ssize_t lttng_action_path_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_action_path **action_path);
-
-int lttng_action_path_serialize(const struct lttng_action_path *action_path,
-               struct lttng_payload *payload);
-
-#endif /* LTTNG_ACTION_PATH_INTERNAL_H */
diff --git a/include/lttng/action/path-internal.hpp b/include/lttng/action/path-internal.hpp
new file mode 100644 (file)
index 0000000..9b9a4d1
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ACTION_PATH_INTERNAL_H
+#define LTTNG_ACTION_PATH_INTERNAL_H
+
+#include <lttng/action/path.h>
+#include <common/macros.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <sys/types.h>
+
+struct lttng_action_path {
+       struct lttng_dynamic_array indexes;
+};
+
+/* Assumes that 'dst' is uninitialized. */
+int lttng_action_path_copy(const struct lttng_action_path *src,
+               struct lttng_action_path *dst);
+
+ssize_t lttng_action_path_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_action_path **action_path);
+
+int lttng_action_path_serialize(const struct lttng_action_path *action_path,
+               struct lttng_payload *payload);
+
+#endif /* LTTNG_ACTION_PATH_INTERNAL_H */
diff --git a/include/lttng/action/rate-policy-internal.h b/include/lttng/action/rate-policy-internal.h
deleted file mode 100644 (file)
index b24ed52..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_RATE_POLICY_INTERNAL_H
-#define LTTNG_RATE_POLICY_INTERNAL_H
-
-#include <common/macros.h>
-#include <common/payload-view.h>
-#include <lttng/action/rate-policy.h>
-#include <lttng/lttng-error.h>
-#include <stdbool.h>
-
-
-struct mi_writer;
-
-int lttng_rate_policy_serialize(struct lttng_rate_policy *rate_policy,
-               struct lttng_payload *buf);
-
-ssize_t lttng_rate_policy_create_from_payload(struct lttng_payload_view *view,
-               struct lttng_rate_policy **rate_policy);
-
-bool lttng_rate_policy_is_equal(const struct lttng_rate_policy *a,
-               const struct lttng_rate_policy *b);
-
-const char *lttng_rate_policy_type_string(
-               enum lttng_rate_policy_type rate_policy_type);
-
-struct lttng_rate_policy *lttng_rate_policy_copy(
-               const struct lttng_rate_policy *source);
-
-bool lttng_rate_policy_should_execute(
-               const struct lttng_rate_policy *policy, uint64_t counter);
-
-enum lttng_error_code lttng_rate_policy_mi_serialize(
-               const struct lttng_rate_policy *policy,
-               struct mi_writer *writer);
-
-#endif /* LTTNG_RATE_POLICY */
diff --git a/include/lttng/action/rate-policy-internal.hpp b/include/lttng/action/rate-policy-internal.hpp
new file mode 100644 (file)
index 0000000..5f6eb1f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_RATE_POLICY_INTERNAL_H
+#define LTTNG_RATE_POLICY_INTERNAL_H
+
+#include <common/macros.hpp>
+#include <common/payload-view.hpp>
+#include <lttng/action/rate-policy.h>
+#include <lttng/lttng-error.h>
+#include <stdbool.h>
+
+
+struct mi_writer;
+
+int lttng_rate_policy_serialize(struct lttng_rate_policy *rate_policy,
+               struct lttng_payload *buf);
+
+ssize_t lttng_rate_policy_create_from_payload(struct lttng_payload_view *view,
+               struct lttng_rate_policy **rate_policy);
+
+bool lttng_rate_policy_is_equal(const struct lttng_rate_policy *a,
+               const struct lttng_rate_policy *b);
+
+const char *lttng_rate_policy_type_string(
+               enum lttng_rate_policy_type rate_policy_type);
+
+struct lttng_rate_policy *lttng_rate_policy_copy(
+               const struct lttng_rate_policy *source);
+
+bool lttng_rate_policy_should_execute(
+               const struct lttng_rate_policy *policy, uint64_t counter);
+
+enum lttng_error_code lttng_rate_policy_mi_serialize(
+               const struct lttng_rate_policy *policy,
+               struct mi_writer *writer);
+
+#endif /* LTTNG_RATE_POLICY */
diff --git a/include/lttng/action/rotate-session-internal.h b/include/lttng/action/rotate-session-internal.h
deleted file mode 100644 (file)
index 9a451f8..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H
-#define LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H
-
-#include <common/macros.h>
-
-struct lttng_action;
-struct lttng_payload_view;
-
-/*
- * Create a "rotate session" action from a payload view.
- *
- * On success, return the number of bytes consumed from `view`, and the created
- * action in `*action`. On failure, return -1.
- */
-extern ssize_t lttng_action_rotate_session_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_action **action);
-
-#endif /* LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H */
diff --git a/include/lttng/action/rotate-session-internal.hpp b/include/lttng/action/rotate-session-internal.hpp
new file mode 100644 (file)
index 0000000..5030aea
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H
+#define LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H
+
+#include <common/macros.hpp>
+
+struct lttng_action;
+struct lttng_payload_view;
+
+/*
+ * Create a "rotate session" action from a payload view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * action in `*action`. On failure, return -1.
+ */
+extern ssize_t lttng_action_rotate_session_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_ROTATE_SESSION_INTERNAL_H */
diff --git a/include/lttng/action/snapshot-session-internal.h b/include/lttng/action/snapshot-session-internal.h
deleted file mode 100644 (file)
index 7396c29..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H
-#define LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H
-
-#include <sys/types.h>
-
-#include <common/macros.h>
-
-struct lttng_action;
-struct lttng_payload_view;
-
-/*
- * Create a "snapshot session" action from a payload view.
- *
- * On success, return the number of bytes consumed from `view`, and the created
- * action in `*action`. On failure, return -1.
- */
-extern ssize_t lttng_action_snapshot_session_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_action **action);
-
-#endif /* LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H */
diff --git a/include/lttng/action/snapshot-session-internal.hpp b/include/lttng/action/snapshot-session-internal.hpp
new file mode 100644 (file)
index 0000000..27a8795
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H
+#define LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H
+
+#include <sys/types.h>
+
+#include <common/macros.hpp>
+
+struct lttng_action;
+struct lttng_payload_view;
+
+/*
+ * Create a "snapshot session" action from a payload view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * action in `*action`. On failure, return -1.
+ */
+extern ssize_t lttng_action_snapshot_session_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_SNAPSHOT_SESSION_INTERNAL_H */
diff --git a/include/lttng/action/start-session-internal.h b/include/lttng/action/start-session-internal.h
deleted file mode 100644 (file)
index 56ffb71..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ACTION_START_SESSION_INTERNAL_H
-#define LTTNG_ACTION_START_SESSION_INTERNAL_H
-
-#include <common/macros.h>
-
-struct lttng_action;
-struct lttng_payload_view;
-
-/*
- * Create a "start session" action from a payload view.
- *
- * On success, return the number of bytes consumed from `view`, and the created
- * action in `*action`. On failure, return -1.
- */
-extern ssize_t lttng_action_start_session_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_action **action);
-
-#endif /* LTTNG_ACTION_START_SESSION_INTERNAL_H */
diff --git a/include/lttng/action/start-session-internal.hpp b/include/lttng/action/start-session-internal.hpp
new file mode 100644 (file)
index 0000000..44dab1b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ACTION_START_SESSION_INTERNAL_H
+#define LTTNG_ACTION_START_SESSION_INTERNAL_H
+
+#include <common/macros.hpp>
+
+struct lttng_action;
+struct lttng_payload_view;
+
+/*
+ * Create a "start session" action from a payload view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * action in `*action`. On failure, return -1.
+ */
+extern ssize_t lttng_action_start_session_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_START_SESSION_INTERNAL_H */
diff --git a/include/lttng/action/stop-session-internal.h b/include/lttng/action/stop-session-internal.h
deleted file mode 100644 (file)
index da4a5aa..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ACTION_STOP_SESSION_INTERNAL_H
-#define LTTNG_ACTION_STOP_SESSION_INTERNAL_H
-
-#include <common/macros.h>
-
-struct lttng_action;
-struct lttng_payload_view;
-
-/*
- * Create a "stop session" action from a payload view.
- *
- * On success, return the number of bytes consumed from `view`, and the created
- * action in `*action`. On failure, return -1.
- */
-extern ssize_t lttng_action_stop_session_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_action **action);
-
-#endif /* LTTNG_ACTION_STOP_SESSION_INTERNAL_H */
diff --git a/include/lttng/action/stop-session-internal.hpp b/include/lttng/action/stop-session-internal.hpp
new file mode 100644 (file)
index 0000000..2205535
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ACTION_STOP_SESSION_INTERNAL_H
+#define LTTNG_ACTION_STOP_SESSION_INTERNAL_H
+
+#include <common/macros.hpp>
+
+struct lttng_action;
+struct lttng_payload_view;
+
+/*
+ * Create a "stop session" action from a payload view.
+ *
+ * On success, return the number of bytes consumed from `view`, and the created
+ * action in `*action`. On failure, return -1.
+ */
+extern ssize_t lttng_action_stop_session_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_action **action);
+
+#endif /* LTTNG_ACTION_STOP_SESSION_INTERNAL_H */
diff --git a/include/lttng/channel-internal.h b/include/lttng/channel-internal.h
deleted file mode 100644 (file)
index 04b1932..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CHANNEL_INTERNAL_H
-#define LTTNG_CHANNEL_INTERNAL_H
-
-#include <common/macros.h>
-
-struct lttng_channel_extended {
-       uint64_t discarded_events;
-       uint64_t lost_packets;
-       uint64_t monitor_timer_interval;
-       int64_t blocking_timeout;
-} LTTNG_PACKED;
-
-#endif /* LTTNG_CHANNEL_INTERNAL_H */
diff --git a/include/lttng/channel-internal.hpp b/include/lttng/channel-internal.hpp
new file mode 100644 (file)
index 0000000..ece0e83
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CHANNEL_INTERNAL_H
+#define LTTNG_CHANNEL_INTERNAL_H
+
+#include <common/macros.hpp>
+
+struct lttng_channel_extended {
+       uint64_t discarded_events;
+       uint64_t lost_packets;
+       uint64_t monitor_timer_interval;
+       int64_t blocking_timeout;
+} LTTNG_PACKED;
+
+#endif /* LTTNG_CHANNEL_INTERNAL_H */
diff --git a/include/lttng/condition/buffer-usage-internal.h b/include/lttng/condition/buffer-usage-internal.h
deleted file mode 100644 (file)
index 1e6d5a5..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H
-#define LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H
-
-#include <lttng/condition/buffer-usage.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/evaluation-internal.h>
-#include <lttng/domain.h>
-#include "common/buffer-view.h"
-#include <common/macros.h>
-
-struct lttng_condition_buffer_usage {
-       struct lttng_condition parent;
-       struct {
-               bool set;
-               uint64_t value;
-       } threshold_bytes;
-       struct {
-               bool set;
-               double value;
-       } threshold_ratio;
-       char *session_name;
-       char *channel_name;
-       struct {
-               bool set;
-               enum lttng_domain_type type;
-       } domain;
-};
-
-struct lttng_condition_buffer_usage_comm {
-       uint8_t threshold_set_in_bytes;
-       uint64_t threshold_bytes;
-       double threshold_ratio;
-       /* Both lengths include the trailing \0. */
-       uint32_t session_name_len;
-       uint32_t channel_name_len;
-       /* enum lttng_domain_type */
-       int8_t domain_type;
-       /* session and channel names. */
-       char names[];
-} LTTNG_PACKED;
-
-struct lttng_evaluation_buffer_usage {
-       struct lttng_evaluation parent;
-       uint64_t buffer_use;
-       uint64_t buffer_capacity;
-};
-
-struct lttng_evaluation_buffer_usage_comm {
-       uint64_t buffer_use;
-       uint64_t buffer_capacity;
-} LTTNG_PACKED;
-
-struct lttng_evaluation *lttng_evaluation_buffer_usage_create(
-               enum lttng_condition_type type, uint64_t use,
-               uint64_t capacity);
-
-ssize_t lttng_condition_buffer_usage_low_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_condition **condition);
-
-ssize_t lttng_condition_buffer_usage_high_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_condition **condition);
-
-ssize_t lttng_evaluation_buffer_usage_low_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_evaluation **evaluation);
-
-ssize_t lttng_evaluation_buffer_usage_high_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_evaluation **evaluation);
-
-#endif /* LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H */
diff --git a/include/lttng/condition/buffer-usage-internal.hpp b/include/lttng/condition/buffer-usage-internal.hpp
new file mode 100644 (file)
index 0000000..b2e6f85
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H
+#define LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H
+
+#include <lttng/condition/buffer-usage.h>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/evaluation-internal.hpp>
+#include <lttng/domain.h>
+#include "common/buffer-view.hpp"
+#include <common/macros.hpp>
+
+struct lttng_condition_buffer_usage {
+       struct lttng_condition parent;
+       struct {
+               bool set;
+               uint64_t value;
+       } threshold_bytes;
+       struct {
+               bool set;
+               double value;
+       } threshold_ratio;
+       char *session_name;
+       char *channel_name;
+       struct {
+               bool set;
+               enum lttng_domain_type type;
+       } domain;
+};
+
+struct lttng_condition_buffer_usage_comm {
+       uint8_t threshold_set_in_bytes;
+       uint64_t threshold_bytes;
+       double threshold_ratio;
+       /* Both lengths include the trailing \0. */
+       uint32_t session_name_len;
+       uint32_t channel_name_len;
+       /* enum lttng_domain_type */
+       int8_t domain_type;
+       /* session and channel names. */
+       char names[];
+} LTTNG_PACKED;
+
+struct lttng_evaluation_buffer_usage {
+       struct lttng_evaluation parent;
+       uint64_t buffer_use;
+       uint64_t buffer_capacity;
+};
+
+struct lttng_evaluation_buffer_usage_comm {
+       uint64_t buffer_use;
+       uint64_t buffer_capacity;
+} LTTNG_PACKED;
+
+struct lttng_evaluation *lttng_evaluation_buffer_usage_create(
+               enum lttng_condition_type type, uint64_t use,
+               uint64_t capacity);
+
+ssize_t lttng_condition_buffer_usage_low_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_condition **condition);
+
+ssize_t lttng_condition_buffer_usage_high_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_condition **condition);
+
+ssize_t lttng_evaluation_buffer_usage_low_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_evaluation **evaluation);
+
+ssize_t lttng_evaluation_buffer_usage_high_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_evaluation **evaluation);
+
+#endif /* LTTNG_CONDITION_BUFFER_USAGE_INTERNAL_H */
diff --git a/include/lttng/condition/condition-internal.h b/include/lttng/condition/condition-internal.h
deleted file mode 100644 (file)
index 5bafaf0..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CONDITION_INTERNAL_H
-#define LTTNG_CONDITION_INTERNAL_H
-
-#include <common/macros.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/condition/condition.h>
-#include <lttng/lttng-error.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <urcu/list.h>
-#include <urcu/ref.h>
-
-struct mi_writer;
-struct mi_lttng_error_query_callbacks;
-struct lttng_trigger;
-
-typedef void (*condition_destroy_cb)(struct lttng_condition *condition);
-typedef bool (*condition_validate_cb)(const struct lttng_condition *condition);
-typedef int (*condition_serialize_cb)(
-               const struct lttng_condition *condition,
-               struct lttng_payload *payload);
-typedef bool (*condition_equal_cb)(const struct lttng_condition *a,
-               const struct lttng_condition *b);
-typedef ssize_t (*condition_create_from_payload_cb)(
-               struct lttng_payload_view *view,
-               struct lttng_condition **condition);
-typedef enum lttng_error_code (*condition_mi_serialize_cb)(
-               const struct lttng_condition *condition,
-               struct mi_writer *writer);
-
-struct lttng_condition {
-       /* Reference counting is only exposed to internal users. */
-       struct urcu_ref ref;
-       enum lttng_condition_type type;
-       condition_validate_cb validate;
-       condition_serialize_cb serialize;
-       condition_equal_cb equal;
-       condition_destroy_cb destroy;
-       condition_mi_serialize_cb mi_serialize;
-};
-
-struct lttng_condition_comm {
-       /* enum lttng_condition_type */
-       int8_t condition_type;
-       char payload[];
-};
-
-void lttng_condition_get(struct lttng_condition *condition);
-
-void lttng_condition_put(struct lttng_condition *condition);
-
-void lttng_condition_init(struct lttng_condition *condition,
-               enum lttng_condition_type type);
-
-bool lttng_condition_validate(const struct lttng_condition *condition);
-
-ssize_t lttng_condition_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_condition **condition);
-
-int lttng_condition_serialize(const struct lttng_condition *condition,
-               struct lttng_payload *payload);
-
-bool lttng_condition_is_equal(const struct lttng_condition *a,
-               const struct lttng_condition *b);
-
-enum lttng_error_code lttng_condition_mi_serialize(
-               const struct lttng_trigger *trigger,
-               const struct lttng_condition *condition,
-               struct mi_writer *writer,
-               const struct mi_lttng_error_query_callbacks
-                               *error_query_callbacks);
-
-const char *lttng_condition_type_str(enum lttng_condition_type type);
-
-#endif /* LTTNG_CONDITION_INTERNAL_H */
diff --git a/include/lttng/condition/condition-internal.hpp b/include/lttng/condition/condition-internal.hpp
new file mode 100644 (file)
index 0000000..27407d0
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONDITION_INTERNAL_H
+#define LTTNG_CONDITION_INTERNAL_H
+
+#include <common/macros.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/condition/condition.h>
+#include <lttng/lttng-error.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <urcu/list.h>
+#include <urcu/ref.h>
+
+struct mi_writer;
+struct mi_lttng_error_query_callbacks;
+struct lttng_trigger;
+
+typedef void (*condition_destroy_cb)(struct lttng_condition *condition);
+typedef bool (*condition_validate_cb)(const struct lttng_condition *condition);
+typedef int (*condition_serialize_cb)(
+               const struct lttng_condition *condition,
+               struct lttng_payload *payload);
+typedef bool (*condition_equal_cb)(const struct lttng_condition *a,
+               const struct lttng_condition *b);
+typedef ssize_t (*condition_create_from_payload_cb)(
+               struct lttng_payload_view *view,
+               struct lttng_condition **condition);
+typedef enum lttng_error_code (*condition_mi_serialize_cb)(
+               const struct lttng_condition *condition,
+               struct mi_writer *writer);
+
+struct lttng_condition {
+       /* Reference counting is only exposed to internal users. */
+       struct urcu_ref ref;
+       enum lttng_condition_type type;
+       condition_validate_cb validate;
+       condition_serialize_cb serialize;
+       condition_equal_cb equal;
+       condition_destroy_cb destroy;
+       condition_mi_serialize_cb mi_serialize;
+};
+
+struct lttng_condition_comm {
+       /* enum lttng_condition_type */
+       int8_t condition_type;
+       char payload[];
+};
+
+void lttng_condition_get(struct lttng_condition *condition);
+
+void lttng_condition_put(struct lttng_condition *condition);
+
+void lttng_condition_init(struct lttng_condition *condition,
+               enum lttng_condition_type type);
+
+bool lttng_condition_validate(const struct lttng_condition *condition);
+
+ssize_t lttng_condition_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_condition **condition);
+
+int lttng_condition_serialize(const struct lttng_condition *condition,
+               struct lttng_payload *payload);
+
+bool lttng_condition_is_equal(const struct lttng_condition *a,
+               const struct lttng_condition *b);
+
+enum lttng_error_code lttng_condition_mi_serialize(
+               const struct lttng_trigger *trigger,
+               const struct lttng_condition *condition,
+               struct mi_writer *writer,
+               const struct mi_lttng_error_query_callbacks
+                               *error_query_callbacks);
+
+const char *lttng_condition_type_str(enum lttng_condition_type type);
+
+#endif /* LTTNG_CONDITION_INTERNAL_H */
diff --git a/include/lttng/condition/evaluation-internal.h b/include/lttng/condition/evaluation-internal.h
deleted file mode 100644 (file)
index 12ea104..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVALUATION_INTERNAL_H
-#define LTTNG_EVALUATION_INTERNAL_H
-
-#include <lttng/condition/evaluation.h>
-#include <lttng/condition/condition.h>
-#include <common/macros.h>
-#include <stdbool.h>
-#include <sys/types.h>
-
-struct lttng_payload;
-struct lttng_payload_view;
-
-typedef void (*evaluation_destroy_cb)(struct lttng_evaluation *evaluation);
-typedef int (*evaluation_serialize_cb)(
-               const struct lttng_evaluation *evaluation,
-               struct lttng_payload *payload);
-
-struct lttng_evaluation_comm {
-       /* enum lttng_condition_type type */
-       int8_t type;
-       char payload[];
-} LTTNG_PACKED;
-
-struct lttng_evaluation {
-       enum lttng_condition_type type;
-       evaluation_serialize_cb serialize;
-       evaluation_destroy_cb destroy;
-};
-
-void lttng_evaluation_init(struct lttng_evaluation *evaluation,
-               enum lttng_condition_type type);
-
-ssize_t lttng_evaluation_create_from_payload(
-               const struct lttng_condition *condition,
-               struct lttng_payload_view *view,
-               struct lttng_evaluation **evaluation);
-
-int lttng_evaluation_serialize(const struct lttng_evaluation *evaluation,
-               struct lttng_payload *payload);
-
-#endif /* LTTNG_EVALUATION_INTERNAL_H */
diff --git a/include/lttng/condition/evaluation-internal.hpp b/include/lttng/condition/evaluation-internal.hpp
new file mode 100644 (file)
index 0000000..f74927c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVALUATION_INTERNAL_H
+#define LTTNG_EVALUATION_INTERNAL_H
+
+#include <lttng/condition/evaluation.h>
+#include <lttng/condition/condition.h>
+#include <common/macros.hpp>
+#include <stdbool.h>
+#include <sys/types.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+
+typedef void (*evaluation_destroy_cb)(struct lttng_evaluation *evaluation);
+typedef int (*evaluation_serialize_cb)(
+               const struct lttng_evaluation *evaluation,
+               struct lttng_payload *payload);
+
+struct lttng_evaluation_comm {
+       /* enum lttng_condition_type type */
+       int8_t type;
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_evaluation {
+       enum lttng_condition_type type;
+       evaluation_serialize_cb serialize;
+       evaluation_destroy_cb destroy;
+};
+
+void lttng_evaluation_init(struct lttng_evaluation *evaluation,
+               enum lttng_condition_type type);
+
+ssize_t lttng_evaluation_create_from_payload(
+               const struct lttng_condition *condition,
+               struct lttng_payload_view *view,
+               struct lttng_evaluation **evaluation);
+
+int lttng_evaluation_serialize(const struct lttng_evaluation *evaluation,
+               struct lttng_payload *payload);
+
+#endif /* LTTNG_EVALUATION_INTERNAL_H */
diff --git a/include/lttng/condition/event-rule-matches-internal.h b/include/lttng/condition/event-rule-matches-internal.h
deleted file mode 100644 (file)
index ef39f4f..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CONDITION_EVENT_RULE_MATCHES_INTERNAL_H
-#define LTTNG_CONDITION_EVENT_RULE_MATCHES_INTERNAL_H
-
-#include <lttng/condition/condition-internal.h>
-#include <common/buffer-view.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <lttng/condition/evaluation-internal.h>
-#include <common/dynamic-array.h>
-#include <lttng/event-field-value.h>
-
-struct lttng_capture_descriptor {
-       struct lttng_event_expr *event_expression;
-       struct lttng_bytecode *bytecode;
-};
-
-struct lttng_condition_event_rule_matches {
-       struct lttng_condition parent;
-       struct lttng_event_rule *rule;
-
-       /*
-        * Internal use only.
-        * Error accounting counter index.
-        */
-       LTTNG_OPTIONAL(uint64_t) error_counter_index;
-
-       /* Array of `struct lttng_capture_descriptor *`. */
-       struct lttng_dynamic_pointer_array capture_descriptors;
-};
-
-struct lttng_evaluation_event_rule_matches {
-       struct lttng_evaluation parent;
-
-       /* MessagePack-encoded captured event field values. */
-       struct lttng_dynamic_buffer capture_payload;
-
-       /*
-        * The content of this array event field value is the decoded
-        * version of `capture_payload` above.
-        *
-        * This is a cache: it's not serialized/deserialized in
-        * communications from/to the library and the session daemon.
-        */
-       struct lttng_event_field_value *captured_values;
-};
-
-ssize_t lttng_condition_event_rule_matches_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_condition **condition);
-
-enum lttng_condition_status
-lttng_condition_event_rule_matches_borrow_rule_mutable(
-               const struct lttng_condition *condition,
-               struct lttng_event_rule **rule);
-
-void lttng_condition_event_rule_matches_set_error_counter_index(
-               struct lttng_condition *condition,
-               uint64_t error_counter_index);
-
-uint64_t lttng_condition_event_rule_matches_get_error_counter_index(
-               const struct lttng_condition *condition);
-
-struct lttng_evaluation *lttng_evaluation_event_rule_matches_create(
-               const struct lttng_condition_event_rule_matches *condition,
-               const char *capture_payload,
-               size_t capture_payload_size,
-               bool decode_capture_payload);
-
-ssize_t lttng_evaluation_event_rule_matches_create_from_payload(
-               const struct lttng_condition_event_rule_matches *condition,
-               struct lttng_payload_view *view,
-               struct lttng_evaluation **_evaluation);
-
-enum lttng_error_code
-lttng_condition_event_rule_matches_generate_capture_descriptor_bytecode(
-               struct lttng_condition *condition);
-
-const struct lttng_bytecode *
-lttng_condition_event_rule_matches_get_capture_bytecode_at_index(
-               const struct lttng_condition *condition, unsigned int index);
-
-#endif /* LTTNG_CONDITION_EVENT_RULE_MATCHES_INTERNAL_H */
diff --git a/include/lttng/condition/event-rule-matches-internal.hpp b/include/lttng/condition/event-rule-matches-internal.hpp
new file mode 100644 (file)
index 0000000..bb7e03e
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONDITION_EVENT_RULE_MATCHES_INTERNAL_H
+#define LTTNG_CONDITION_EVENT_RULE_MATCHES_INTERNAL_H
+
+#include <lttng/condition/condition-internal.hpp>
+#include <common/buffer-view.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/condition/evaluation-internal.hpp>
+#include <common/dynamic-array.hpp>
+#include <lttng/event-field-value.h>
+
+struct lttng_capture_descriptor {
+       struct lttng_event_expr *event_expression;
+       struct lttng_bytecode *bytecode;
+};
+
+struct lttng_condition_event_rule_matches {
+       struct lttng_condition parent;
+       struct lttng_event_rule *rule;
+
+       /*
+        * Internal use only.
+        * Error accounting counter index.
+        */
+       LTTNG_OPTIONAL(uint64_t) error_counter_index;
+
+       /* Array of `struct lttng_capture_descriptor *`. */
+       struct lttng_dynamic_pointer_array capture_descriptors;
+};
+
+struct lttng_evaluation_event_rule_matches {
+       struct lttng_evaluation parent;
+
+       /* MessagePack-encoded captured event field values. */
+       struct lttng_dynamic_buffer capture_payload;
+
+       /*
+        * The content of this array event field value is the decoded
+        * version of `capture_payload` above.
+        *
+        * This is a cache: it's not serialized/deserialized in
+        * communications from/to the library and the session daemon.
+        */
+       struct lttng_event_field_value *captured_values;
+};
+
+ssize_t lttng_condition_event_rule_matches_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_condition **condition);
+
+enum lttng_condition_status
+lttng_condition_event_rule_matches_borrow_rule_mutable(
+               const struct lttng_condition *condition,
+               struct lttng_event_rule **rule);
+
+void lttng_condition_event_rule_matches_set_error_counter_index(
+               struct lttng_condition *condition,
+               uint64_t error_counter_index);
+
+uint64_t lttng_condition_event_rule_matches_get_error_counter_index(
+               const struct lttng_condition *condition);
+
+struct lttng_evaluation *lttng_evaluation_event_rule_matches_create(
+               const struct lttng_condition_event_rule_matches *condition,
+               const char *capture_payload,
+               size_t capture_payload_size,
+               bool decode_capture_payload);
+
+ssize_t lttng_evaluation_event_rule_matches_create_from_payload(
+               const struct lttng_condition_event_rule_matches *condition,
+               struct lttng_payload_view *view,
+               struct lttng_evaluation **_evaluation);
+
+enum lttng_error_code
+lttng_condition_event_rule_matches_generate_capture_descriptor_bytecode(
+               struct lttng_condition *condition);
+
+const struct lttng_bytecode *
+lttng_condition_event_rule_matches_get_capture_bytecode_at_index(
+               const struct lttng_condition *condition, unsigned int index);
+
+#endif /* LTTNG_CONDITION_EVENT_RULE_MATCHES_INTERNAL_H */
diff --git a/include/lttng/condition/session-consumed-size-internal.h b/include/lttng/condition/session-consumed-size-internal.h
deleted file mode 100644 (file)
index 9340a5f..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CONDITION_SESSION_CONSUMED_SIZE_INTERNAL_H
-#define LTTNG_CONDITION_SESSION_CONSUMED_SIZE_INTERNAL_H
-
-#include <lttng/condition/session-consumed-size.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/evaluation-internal.h>
-#include <common/buffer-view.h>
-#include <common/macros.h>
-
-struct lttng_payload;
-struct lttng_payload_view;
-
-struct lttng_condition_session_consumed_size {
-       struct lttng_condition parent;
-       struct {
-               bool set;
-               uint64_t value;
-       } consumed_threshold_bytes;
-       char *session_name;
-};
-
-struct lttng_condition_session_consumed_size_comm {
-       uint64_t consumed_threshold_bytes;
-       /* Length includes the trailing \0. */
-       uint32_t session_name_len;
-       char session_name[];
-} LTTNG_PACKED;
-
-struct lttng_evaluation_session_consumed_size {
-       struct lttng_evaluation parent;
-       uint64_t session_consumed;
-};
-
-struct lttng_evaluation_session_consumed_size_comm {
-       uint64_t session_consumed;
-} LTTNG_PACKED;
-
-struct lttng_evaluation *lttng_evaluation_session_consumed_size_create(
-               uint64_t consumed);
-
-ssize_t lttng_condition_session_consumed_size_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_condition **condition);
-
-ssize_t lttng_evaluation_session_consumed_size_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_evaluation **evaluation);
-
-#endif /* LTTNG_CONDITION_SESSION_CONSUMED_SIZE_INTERNAL_H */
diff --git a/include/lttng/condition/session-consumed-size-internal.hpp b/include/lttng/condition/session-consumed-size-internal.hpp
new file mode 100644 (file)
index 0000000..cdfa100
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONDITION_SESSION_CONSUMED_SIZE_INTERNAL_H
+#define LTTNG_CONDITION_SESSION_CONSUMED_SIZE_INTERNAL_H
+
+#include <lttng/condition/session-consumed-size.h>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/evaluation-internal.hpp>
+#include <common/buffer-view.hpp>
+#include <common/macros.hpp>
+
+struct lttng_payload;
+struct lttng_payload_view;
+
+struct lttng_condition_session_consumed_size {
+       struct lttng_condition parent;
+       struct {
+               bool set;
+               uint64_t value;
+       } consumed_threshold_bytes;
+       char *session_name;
+};
+
+struct lttng_condition_session_consumed_size_comm {
+       uint64_t consumed_threshold_bytes;
+       /* Length includes the trailing \0. */
+       uint32_t session_name_len;
+       char session_name[];
+} LTTNG_PACKED;
+
+struct lttng_evaluation_session_consumed_size {
+       struct lttng_evaluation parent;
+       uint64_t session_consumed;
+};
+
+struct lttng_evaluation_session_consumed_size_comm {
+       uint64_t session_consumed;
+} LTTNG_PACKED;
+
+struct lttng_evaluation *lttng_evaluation_session_consumed_size_create(
+               uint64_t consumed);
+
+ssize_t lttng_condition_session_consumed_size_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_condition **condition);
+
+ssize_t lttng_evaluation_session_consumed_size_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_evaluation **evaluation);
+
+#endif /* LTTNG_CONDITION_SESSION_CONSUMED_SIZE_INTERNAL_H */
diff --git a/include/lttng/condition/session-rotation-internal.h b/include/lttng/condition/session-rotation-internal.h
deleted file mode 100644 (file)
index c723c6d..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CONDITION_SESSION_ROTATION_INTERNAL_H
-#define LTTNG_CONDITION_SESSION_ROTATION_INTERNAL_H
-
-#include <lttng/condition/session-rotation.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/evaluation-internal.h>
-#include "common/buffer-view.h"
-#include <lttng/location.h>
-#include <common/macros.h>
-
-struct lttng_condition_session_rotation {
-       struct lttng_condition parent;
-       char *session_name;
-};
-
-struct lttng_condition_session_rotation_comm {
-       /* Length includes the trailing \0. */
-       uint32_t session_name_len;
-       char session_name[];
-} LTTNG_PACKED;
-
-struct lttng_evaluation_session_rotation {
-       struct lttng_evaluation parent;
-       uint64_t id;
-       struct lttng_trace_archive_location *location;
-};
-
-struct lttng_evaluation_session_rotation_comm {
-       uint64_t id;
-       uint8_t has_location;
-} LTTNG_PACKED;
-
-ssize_t lttng_condition_session_rotation_ongoing_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_condition **condition);
-
-ssize_t lttng_condition_session_rotation_completed_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_condition **condition);
-
-struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create(
-                uint64_t id);
-
-/* Ownership of location is transferred to the evaluation. */
-struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create(
-               uint64_t id,
-               struct lttng_trace_archive_location *location);
-
-ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_evaluation **evaluation);
-
-ssize_t lttng_evaluation_session_rotation_completed_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_evaluation **evaluation);
-
-#endif /* LTTNG_CONDITION_SESSION_ROTATION_INTERNAL_H */
diff --git a/include/lttng/condition/session-rotation-internal.hpp b/include/lttng/condition/session-rotation-internal.hpp
new file mode 100644 (file)
index 0000000..e9a2984
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONDITION_SESSION_ROTATION_INTERNAL_H
+#define LTTNG_CONDITION_SESSION_ROTATION_INTERNAL_H
+
+#include <lttng/condition/session-rotation.h>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/evaluation-internal.hpp>
+#include "common/buffer-view.hpp"
+#include <lttng/location.h>
+#include <common/macros.hpp>
+
+struct lttng_condition_session_rotation {
+       struct lttng_condition parent;
+       char *session_name;
+};
+
+struct lttng_condition_session_rotation_comm {
+       /* Length includes the trailing \0. */
+       uint32_t session_name_len;
+       char session_name[];
+} LTTNG_PACKED;
+
+struct lttng_evaluation_session_rotation {
+       struct lttng_evaluation parent;
+       uint64_t id;
+       struct lttng_trace_archive_location *location;
+};
+
+struct lttng_evaluation_session_rotation_comm {
+       uint64_t id;
+       uint8_t has_location;
+} LTTNG_PACKED;
+
+ssize_t lttng_condition_session_rotation_ongoing_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_condition **condition);
+
+ssize_t lttng_condition_session_rotation_completed_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_condition **condition);
+
+struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create(
+                uint64_t id);
+
+/* Ownership of location is transferred to the evaluation. */
+struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create(
+               uint64_t id,
+               struct lttng_trace_archive_location *location);
+
+ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_evaluation **evaluation);
+
+ssize_t lttng_evaluation_session_rotation_completed_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_evaluation **evaluation);
+
+#endif /* LTTNG_CONDITION_SESSION_ROTATION_INTERNAL_H */
diff --git a/include/lttng/domain-internal.h b/include/lttng/domain-internal.h
deleted file mode 100644 (file)
index c34ba19..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2020 Simon Marchi <simon.marchi@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_DOMAIN_INTERNAL_H
-#define LTTNG_DOMAIN_INTERNAL_H
-
-#include "lttng/domain.h"
-#include "common/macros.h"
-
-const char *lttng_domain_type_str(enum lttng_domain_type domain_type);
-
-#endif /* LTTNG_DOMAIN_INTERNAL_H */
diff --git a/include/lttng/domain-internal.hpp b/include/lttng/domain-internal.hpp
new file mode 100644 (file)
index 0000000..4439c78
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2020 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_DOMAIN_INTERNAL_H
+#define LTTNG_DOMAIN_INTERNAL_H
+
+#include "lttng/domain.h"
+#include "common/macros.hpp"
+
+const char *lttng_domain_type_str(enum lttng_domain_type domain_type);
+
+#endif /* LTTNG_DOMAIN_INTERNAL_H */
diff --git a/include/lttng/endpoint-internal.h b/include/lttng/endpoint-internal.h
deleted file mode 100644 (file)
index 3ec1df9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ENDPOINT_INTERNAL_H
-#define LTTNG_ENDPOINT_INTERNAL_H
-
-#include <lttng/endpoint.h>
-#include <common/macros.h>
-
-enum lttng_endpoint_type {
-       LTTNG_ENDPOINT_TYPE_DEFAULT_SESSIOND_NOTIFICATION = 0,
-       LTTNG_ENDPOINT_TYPE_DEFAULT_SESSIOND_COMMAND = 1,
-};
-
-struct lttng_endpoint {
-       enum lttng_endpoint_type type;
-};
-
-#endif /* LTTNG_ENDPOINT_INTERNAL_H */
diff --git a/include/lttng/endpoint-internal.hpp b/include/lttng/endpoint-internal.hpp
new file mode 100644 (file)
index 0000000..5317f7f
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ENDPOINT_INTERNAL_H
+#define LTTNG_ENDPOINT_INTERNAL_H
+
+#include <lttng/endpoint.h>
+#include <common/macros.hpp>
+
+enum lttng_endpoint_type {
+       LTTNG_ENDPOINT_TYPE_DEFAULT_SESSIOND_NOTIFICATION = 0,
+       LTTNG_ENDPOINT_TYPE_DEFAULT_SESSIOND_COMMAND = 1,
+};
+
+struct lttng_endpoint {
+       enum lttng_endpoint_type type;
+};
+
+#endif /* LTTNG_ENDPOINT_INTERNAL_H */
diff --git a/include/lttng/error-query-internal.h b/include/lttng/error-query-internal.h
deleted file mode 100644 (file)
index 07e2280..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * error-query-internal.h
- *
- * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ERROR_QUERY_INTERNAL_H
-#define LTTNG_ERROR_QUERY_INTERNAL_H
-
-#include <lttng/lttng.h>
-#include <common/macros.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
-
-struct mi_writer;
-
-enum lttng_error_query_target_type {
-       LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER,
-       LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION,
-       LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION,
-};
-
-enum lttng_error_query_target_type lttng_error_query_get_target_type(
-               const struct lttng_error_query *query);
-
-const struct lttng_trigger *lttng_error_query_trigger_borrow_target(
-               const struct lttng_error_query *query);
-
-const struct lttng_trigger *lttng_error_query_condition_borrow_target(
-               const struct lttng_error_query *query);
-
-const struct lttng_trigger *lttng_error_query_action_borrow_trigger_target(
-               const struct lttng_error_query *query);
-
-struct lttng_action *lttng_error_query_action_borrow_action_target(
-               const struct lttng_error_query *query,
-               struct lttng_trigger *trigger);
-
-int lttng_error_query_serialize(const struct lttng_error_query *query,
-               struct lttng_payload *payload);
-
-ssize_t lttng_error_query_create_from_payload(struct lttng_payload_view *view,
-               struct lttng_error_query **query);
-
-int lttng_error_query_result_serialize(
-               const struct lttng_error_query_result *result,
-               struct lttng_payload *payload);
-
-ssize_t lttng_error_query_result_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_error_query_result **result);
-
-int lttng_error_query_results_serialize(
-               const struct lttng_error_query_results *results,
-               struct lttng_payload *payload);
-
-ssize_t lttng_error_query_results_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_error_query_results **results);
-
-struct lttng_error_query_result *
-lttng_error_query_result_counter_create(
-               const char *name, const char *description, uint64_t value);
-
-void lttng_error_query_result_destroy(struct lttng_error_query_result *result);
-
-struct lttng_error_query_results *lttng_error_query_results_create(void);
-
-/* Ownership of `result` is transferred on success. */
-int lttng_error_query_results_add_result(
-               struct lttng_error_query_results *results,
-               struct lttng_error_query_result *result);
-
-enum lttng_error_code lttng_error_query_results_mi_serialize(
-               const struct lttng_error_query_results *results,
-               struct mi_writer *writer);
-
-#endif /* LTTNG_ERROR_QUERY_INTERNAL_H */
diff --git a/include/lttng/error-query-internal.hpp b/include/lttng/error-query-internal.hpp
new file mode 100644 (file)
index 0000000..7bf4da7
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * error-query-internal.h
+ *
+ * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ERROR_QUERY_INTERNAL_H
+#define LTTNG_ERROR_QUERY_INTERNAL_H
+
+#include <lttng/lttng.h>
+#include <common/macros.hpp>
+#include <common/payload.hpp>
+#include <common/payload-view.hpp>
+
+struct mi_writer;
+
+enum lttng_error_query_target_type {
+       LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER,
+       LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION,
+       LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION,
+};
+
+enum lttng_error_query_target_type lttng_error_query_get_target_type(
+               const struct lttng_error_query *query);
+
+const struct lttng_trigger *lttng_error_query_trigger_borrow_target(
+               const struct lttng_error_query *query);
+
+const struct lttng_trigger *lttng_error_query_condition_borrow_target(
+               const struct lttng_error_query *query);
+
+const struct lttng_trigger *lttng_error_query_action_borrow_trigger_target(
+               const struct lttng_error_query *query);
+
+struct lttng_action *lttng_error_query_action_borrow_action_target(
+               const struct lttng_error_query *query,
+               struct lttng_trigger *trigger);
+
+int lttng_error_query_serialize(const struct lttng_error_query *query,
+               struct lttng_payload *payload);
+
+ssize_t lttng_error_query_create_from_payload(struct lttng_payload_view *view,
+               struct lttng_error_query **query);
+
+int lttng_error_query_result_serialize(
+               const struct lttng_error_query_result *result,
+               struct lttng_payload *payload);
+
+ssize_t lttng_error_query_result_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_error_query_result **result);
+
+int lttng_error_query_results_serialize(
+               const struct lttng_error_query_results *results,
+               struct lttng_payload *payload);
+
+ssize_t lttng_error_query_results_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_error_query_results **results);
+
+struct lttng_error_query_result *
+lttng_error_query_result_counter_create(
+               const char *name, const char *description, uint64_t value);
+
+void lttng_error_query_result_destroy(struct lttng_error_query_result *result);
+
+struct lttng_error_query_results *lttng_error_query_results_create(void);
+
+/* Ownership of `result` is transferred on success. */
+int lttng_error_query_results_add_result(
+               struct lttng_error_query_results *results,
+               struct lttng_error_query_result *result);
+
+enum lttng_error_code lttng_error_query_results_mi_serialize(
+               const struct lttng_error_query_results *results,
+               struct mi_writer *writer);
+
+#endif /* LTTNG_ERROR_QUERY_INTERNAL_H */
diff --git a/include/lttng/event-expr-internal.h b/include/lttng/event-expr-internal.h
deleted file mode 100644 (file)
index 469fd17..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_EXPR_INTERNAL_H
-#define LTTNG_EVENT_EXPR_INTERNAL_H
-
-#include <common/macros.h>
-#include <lttng/event-expr.h>
-
-struct lttng_bytecode;
-struct mi_writer;
-
-struct lttng_event_expr {
-       enum lttng_event_expr_type type;
-};
-
-/*
- * `LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD` and
- * `LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD`.
- */
-struct lttng_event_expr_field {
-       struct lttng_event_expr parent;
-       char *name;
-};
-
-/* `LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD` */
-struct lttng_event_expr_app_specific_context_field {
-       struct lttng_event_expr parent;
-       char *provider_name;
-       char *type_name;
-};
-
-/* `LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT` */
-struct lttng_event_expr_array_field_element {
-       struct lttng_event_expr parent;
-
-       /* Owned by this */
-       struct lttng_event_expr *array_field_expr;
-
-       unsigned int index;
-};
-
-/*
- * Returns whether or not `expr` is an l-value (locator value).
- */
-static inline
-bool lttng_event_expr_is_lvalue(const struct lttng_event_expr *expr)
-{
-       LTTNG_ASSERT(expr);
-       return expr->type == LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD ||
-                       expr->type == LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD ||
-                       expr->type == LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD ||
-                       expr->type == LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT;
-}
-
-int lttng_event_expr_to_bytecode(const struct lttng_event_expr *expr,
-               struct lttng_bytecode **bytecode_out);
-
-enum lttng_error_code lttng_event_expr_mi_serialize(
-               const struct lttng_event_expr *expression,
-               struct mi_writer *writer);
-
-#endif /* LTTNG_EVENT_EXPR_INTERNAL_H */
diff --git a/include/lttng/event-expr-internal.hpp b/include/lttng/event-expr-internal.hpp
new file mode 100644 (file)
index 0000000..07547e5
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_EXPR_INTERNAL_H
+#define LTTNG_EVENT_EXPR_INTERNAL_H
+
+#include <common/macros.hpp>
+#include <lttng/event-expr.h>
+
+struct lttng_bytecode;
+struct mi_writer;
+
+struct lttng_event_expr {
+       enum lttng_event_expr_type type;
+};
+
+/*
+ * `LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD` and
+ * `LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD`.
+ */
+struct lttng_event_expr_field {
+       struct lttng_event_expr parent;
+       char *name;
+};
+
+/* `LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD` */
+struct lttng_event_expr_app_specific_context_field {
+       struct lttng_event_expr parent;
+       char *provider_name;
+       char *type_name;
+};
+
+/* `LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT` */
+struct lttng_event_expr_array_field_element {
+       struct lttng_event_expr parent;
+
+       /* Owned by this */
+       struct lttng_event_expr *array_field_expr;
+
+       unsigned int index;
+};
+
+/*
+ * Returns whether or not `expr` is an l-value (locator value).
+ */
+static inline
+bool lttng_event_expr_is_lvalue(const struct lttng_event_expr *expr)
+{
+       LTTNG_ASSERT(expr);
+       return expr->type == LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD ||
+                       expr->type == LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD ||
+                       expr->type == LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD ||
+                       expr->type == LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT;
+}
+
+int lttng_event_expr_to_bytecode(const struct lttng_event_expr *expr,
+               struct lttng_bytecode **bytecode_out);
+
+enum lttng_error_code lttng_event_expr_mi_serialize(
+               const struct lttng_event_expr *expression,
+               struct mi_writer *writer);
+
+#endif /* LTTNG_EVENT_EXPR_INTERNAL_H */
diff --git a/include/lttng/event-field-value-internal.h b/include/lttng/event-field-value-internal.h
deleted file mode 100644 (file)
index 510420a..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_FIELD_VALUE_INTERNAL_H
-#define LTTNG_EVENT_FIELD_VALUE_INTERNAL_H
-
-#include <stdint.h>
-#include <lttng/event-field-value.h>
-#include <common/dynamic-array.h>
-
-struct lttng_event_field_value {
-       enum lttng_event_field_value_type type;
-};
-
-/*
- * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT`.
- */
-struct lttng_event_field_value_uint {
-       struct lttng_event_field_value parent;
-       uint64_t val;
-};
-
-/*
- * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT`.
- */
-struct lttng_event_field_value_int {
-       struct lttng_event_field_value parent;
-       int64_t val;
-};
-
-/*
- * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` and
- * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM` (base).
- */
-struct lttng_event_field_value_enum {
-       struct lttng_event_field_value parent;
-
-       /*
-        * Array of `char *` (owned by this).
-        */
-       struct lttng_dynamic_pointer_array labels;
-};
-
-/*
- * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM`.
- */
-struct lttng_event_field_value_enum_uint {
-       struct lttng_event_field_value_enum parent;
-       uint64_t val;
-};
-
-/*
- * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
- */
-struct lttng_event_field_value_enum_int {
-       struct lttng_event_field_value_enum parent;
-       int64_t val;
-};
-
-/* `LTTNG_EVENT_FIELD_VALUE_TYPE_REAL` */
-struct lttng_event_field_value_real {
-       struct lttng_event_field_value parent;
-       double val;
-};
-
-/* `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING` */
-struct lttng_event_field_value_string {
-       struct lttng_event_field_value parent;
-
-       /* Owned by this */
-       char *val;
-};
-
-/* `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING` */
-struct lttng_event_field_value_array {
-       struct lttng_event_field_value parent;
-
-       /*
-        * Array of `struct lttng_event_field_value *` (owned by this).
-        *
-        * A `NULL` element means it's unavailable
-        * (`LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE` status).
-        */
-       struct lttng_dynamic_pointer_array elems;
-};
-
-/*
- * This is internal since the session daemon knows nothing about the
- * enumeration fields produced by the kernel tracer. Indeed, the kernel tracer
- * manages its own metadata which remains opaque to the rest of the toolchain.
- *
- * Enumerations could be supported for the user space tracer, but it is not the
- * case right now.
- */
-
-/*
- * Sets `*count` to the number of labels of the enumeration event field
- * value `field_val`.
- *
- * Returns:
- *
- * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`:
- *     Success.
- *
- * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`:
- *     * `field_val` is `NULL`.
- *     * The type of `field_val` is not
- *       `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` or
- *       `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
- *     * `count` is `NULL`.
- */
-enum lttng_event_field_value_status
-lttng_event_field_value_enum_get_label_count(
-               const struct lttng_event_field_value *field_val,
-               unsigned int *count);
-
-/*
- * Returns the label at index `index` of the enumeration event field
- * value `field_val`, or `NULL` if:
- *
- * * `field_val` is `NULL`.
- * * The type of `field_val` is not
- *   `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` or
- *   `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
- * * `index` is greater than or equal to the label count of `field_val`,
- *   as returned by lttng_event_field_value_enum_get_label_count().
- */
-const char *lttng_event_field_value_enum_get_label_at_index(
-               const struct lttng_event_field_value *field_val,
-               unsigned int index);
-
-struct lttng_event_field_value *lttng_event_field_value_uint_create(
-               uint64_t val);
-
-struct lttng_event_field_value *lttng_event_field_value_int_create(
-               int64_t val);
-
-struct lttng_event_field_value *lttng_event_field_value_enum_uint_create(
-               uint64_t val);
-
-struct lttng_event_field_value *lttng_event_field_value_enum_int_create(
-               int64_t val);
-
-struct lttng_event_field_value *lttng_event_field_value_real_create(double val);
-
-struct lttng_event_field_value *lttng_event_field_value_string_create(
-               const char *val);
-
-struct lttng_event_field_value *lttng_event_field_value_string_create_with_size(
-               const char *val, size_t size);
-
-struct lttng_event_field_value *lttng_event_field_value_array_create(void);
-
-int lttng_event_field_value_enum_append_label(
-               struct lttng_event_field_value *field_val, const char *label);
-
-int lttng_event_field_value_enum_append_label_with_size(
-               struct lttng_event_field_value *field_val, const char *label,
-               size_t size);
-
-int lttng_event_field_value_array_append(
-               struct lttng_event_field_value *array_field_val,
-               struct lttng_event_field_value *field_val);
-
-int lttng_event_field_value_array_append_unavailable(
-               struct lttng_event_field_value *array_field_val);
-
-void lttng_event_field_value_destroy(struct lttng_event_field_value *field_val);
-
-#endif /* LTTNG_EVENT_FIELD_VALUE_INTERNAL_H */
diff --git a/include/lttng/event-field-value-internal.hpp b/include/lttng/event-field-value-internal.hpp
new file mode 100644 (file)
index 0000000..03ef896
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_FIELD_VALUE_INTERNAL_H
+#define LTTNG_EVENT_FIELD_VALUE_INTERNAL_H
+
+#include <stdint.h>
+#include <lttng/event-field-value.h>
+#include <common/dynamic-array.hpp>
+
+struct lttng_event_field_value {
+       enum lttng_event_field_value_type type;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT`.
+ */
+struct lttng_event_field_value_uint {
+       struct lttng_event_field_value parent;
+       uint64_t val;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT`.
+ */
+struct lttng_event_field_value_int {
+       struct lttng_event_field_value parent;
+       int64_t val;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` and
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM` (base).
+ */
+struct lttng_event_field_value_enum {
+       struct lttng_event_field_value parent;
+
+       /*
+        * Array of `char *` (owned by this).
+        */
+       struct lttng_dynamic_pointer_array labels;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM`.
+ */
+struct lttng_event_field_value_enum_uint {
+       struct lttng_event_field_value_enum parent;
+       uint64_t val;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
+ */
+struct lttng_event_field_value_enum_int {
+       struct lttng_event_field_value_enum parent;
+       int64_t val;
+};
+
+/* `LTTNG_EVENT_FIELD_VALUE_TYPE_REAL` */
+struct lttng_event_field_value_real {
+       struct lttng_event_field_value parent;
+       double val;
+};
+
+/* `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING` */
+struct lttng_event_field_value_string {
+       struct lttng_event_field_value parent;
+
+       /* Owned by this */
+       char *val;
+};
+
+/* `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING` */
+struct lttng_event_field_value_array {
+       struct lttng_event_field_value parent;
+
+       /*
+        * Array of `struct lttng_event_field_value *` (owned by this).
+        *
+        * A `NULL` element means it's unavailable
+        * (`LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE` status).
+        */
+       struct lttng_dynamic_pointer_array elems;
+};
+
+/*
+ * This is internal since the session daemon knows nothing about the
+ * enumeration fields produced by the kernel tracer. Indeed, the kernel tracer
+ * manages its own metadata which remains opaque to the rest of the toolchain.
+ *
+ * Enumerations could be supported for the user space tracer, but it is not the
+ * case right now.
+ */
+
+/*
+ * Sets `*count` to the number of labels of the enumeration event field
+ * value `field_val`.
+ *
+ * Returns:
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`:
+ *     Success.
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`:
+ *     * `field_val` is `NULL`.
+ *     * The type of `field_val` is not
+ *       `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` or
+ *       `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
+ *     * `count` is `NULL`.
+ */
+enum lttng_event_field_value_status
+lttng_event_field_value_enum_get_label_count(
+               const struct lttng_event_field_value *field_val,
+               unsigned int *count);
+
+/*
+ * Returns the label at index `index` of the enumeration event field
+ * value `field_val`, or `NULL` if:
+ *
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ *   `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` or
+ *   `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
+ * * `index` is greater than or equal to the label count of `field_val`,
+ *   as returned by lttng_event_field_value_enum_get_label_count().
+ */
+const char *lttng_event_field_value_enum_get_label_at_index(
+               const struct lttng_event_field_value *field_val,
+               unsigned int index);
+
+struct lttng_event_field_value *lttng_event_field_value_uint_create(
+               uint64_t val);
+
+struct lttng_event_field_value *lttng_event_field_value_int_create(
+               int64_t val);
+
+struct lttng_event_field_value *lttng_event_field_value_enum_uint_create(
+               uint64_t val);
+
+struct lttng_event_field_value *lttng_event_field_value_enum_int_create(
+               int64_t val);
+
+struct lttng_event_field_value *lttng_event_field_value_real_create(double val);
+
+struct lttng_event_field_value *lttng_event_field_value_string_create(
+               const char *val);
+
+struct lttng_event_field_value *lttng_event_field_value_string_create_with_size(
+               const char *val, size_t size);
+
+struct lttng_event_field_value *lttng_event_field_value_array_create(void);
+
+int lttng_event_field_value_enum_append_label(
+               struct lttng_event_field_value *field_val, const char *label);
+
+int lttng_event_field_value_enum_append_label_with_size(
+               struct lttng_event_field_value *field_val, const char *label,
+               size_t size);
+
+int lttng_event_field_value_array_append(
+               struct lttng_event_field_value *array_field_val,
+               struct lttng_event_field_value *field_val);
+
+int lttng_event_field_value_array_append_unavailable(
+               struct lttng_event_field_value *array_field_val);
+
+void lttng_event_field_value_destroy(struct lttng_event_field_value *field_val);
+
+#endif /* LTTNG_EVENT_FIELD_VALUE_INTERNAL_H */
diff --git a/include/lttng/event-internal.h b/include/lttng/event-internal.h
deleted file mode 100644 (file)
index 8d03fbd..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * event-internal.h
- *
- * Linux Trace Toolkit Control Library
- *
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_INTERNAL_H
-#define LTTNG_EVENT_INTERNAL_H
-
-#include <common/macros.h>
-#include <lttng/event.h>
-
-struct lttng_userspace_probe_location;
-
-struct lttng_event_extended {
-       /*
-        * exclusions and filter_expression are only set when the lttng_event
-        * was created/allocated by a list operation. These two elements must
-        * not be free'd as they are part of the same contiguous buffer that
-        * contains all events returned by the listing.
-        */
-       char *filter_expression;
-       struct {
-               unsigned int count;
-               /* Array of strings of fixed LTTNG_SYMBOL_NAME_LEN length. */
-               char *strings;
-       } exclusions;
-       struct lttng_userspace_probe_location *probe_location;
-};
-
-struct lttng_event *lttng_event_copy(const struct lttng_event *event);
-
-#endif /* LTTNG_EVENT_INTERNAL_H */
diff --git a/include/lttng/event-internal.hpp b/include/lttng/event-internal.hpp
new file mode 100644 (file)
index 0000000..81e0f1d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * event-internal.h
+ *
+ * Linux Trace Toolkit Control Library
+ *
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_INTERNAL_H
+#define LTTNG_EVENT_INTERNAL_H
+
+#include <common/macros.hpp>
+#include <lttng/event.h>
+
+struct lttng_userspace_probe_location;
+
+struct lttng_event_extended {
+       /*
+        * exclusions and filter_expression are only set when the lttng_event
+        * was created/allocated by a list operation. These two elements must
+        * not be free'd as they are part of the same contiguous buffer that
+        * contains all events returned by the listing.
+        */
+       char *filter_expression;
+       struct {
+               unsigned int count;
+               /* Array of strings of fixed LTTNG_SYMBOL_NAME_LEN length. */
+               char *strings;
+       } exclusions;
+       struct lttng_userspace_probe_location *probe_location;
+};
+
+struct lttng_event *lttng_event_copy(const struct lttng_event *event);
+
+#endif /* LTTNG_EVENT_INTERNAL_H */
diff --git a/include/lttng/event-rule/event-rule-internal.h b/include/lttng/event-rule/event-rule-internal.h
deleted file mode 100644 (file)
index 8026748..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_INTERNAL_H
-#define LTTNG_EVENT_RULE_INTERNAL_H
-
-#include <common/macros.h>
-#include <common/credentials.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/domain.h>
-#include <lttng/event.h>
-#include <lttng/event-rule/event-rule.h>
-#include <lttng/lttng-error.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <urcu/ref.h>
-
-struct lttng_payload;
-struct lttng_payload_view;
-struct mi_writer;
-
-enum lttng_event_rule_generate_exclusions_status {
-       LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK,
-       LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE,
-       LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR,
-       LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY,
-};
-
-typedef void (*event_rule_destroy_cb)(struct lttng_event_rule *event_rule);
-typedef bool (*event_rule_validate_cb)(
-               const struct lttng_event_rule *event_rule);
-typedef int (*event_rule_serialize_cb)(
-               const struct lttng_event_rule *event_rule,
-               struct lttng_payload *payload);
-typedef bool (*event_rule_equal_cb)(const struct lttng_event_rule *a,
-               const struct lttng_event_rule *b);
-typedef ssize_t (*event_rule_create_from_payload_cb)(
-               struct lttng_payload_view *view,
-               struct lttng_event_rule **event_rule);
-typedef enum lttng_error_code (*event_rule_generate_filter_bytecode_cb)(
-               struct lttng_event_rule *event_rule,
-               const struct lttng_credentials *creds);
-typedef const char *(*event_rule_get_filter_cb)(
-               const struct lttng_event_rule *event_rule);
-typedef const struct lttng_bytecode *(
-               *event_rule_get_filter_bytecode_cb)(
-               const struct lttng_event_rule *event_rule);
-typedef enum lttng_event_rule_generate_exclusions_status (
-               *event_rule_generate_exclusions_cb)(
-               const struct lttng_event_rule *event_rule,
-               struct lttng_event_exclusion **exclusions);
-typedef unsigned long (*event_rule_hash_cb)(
-               const struct lttng_event_rule *event_rule);
-typedef struct lttng_event *(*event_rule_generate_lttng_event_cb)(
-               const struct lttng_event_rule *event_rule);
-typedef enum lttng_error_code (*event_rule_mi_serialize_cb)(
-               const struct lttng_event_rule *event_rule,
-               struct mi_writer *writer);
-
-struct lttng_event_rule {
-       struct urcu_ref ref;
-       enum lttng_event_rule_type type;
-       event_rule_validate_cb validate;
-       event_rule_serialize_cb serialize;
-       event_rule_equal_cb equal;
-       event_rule_destroy_cb destroy;
-       event_rule_generate_filter_bytecode_cb generate_filter_bytecode;
-       event_rule_get_filter_cb get_filter;
-       event_rule_get_filter_bytecode_cb get_filter_bytecode;
-       event_rule_generate_exclusions_cb generate_exclusions;
-       event_rule_hash_cb hash;
-       event_rule_generate_lttng_event_cb generate_lttng_event;
-       event_rule_mi_serialize_cb mi_serialize;
-};
-
-struct lttng_event_rule_comm {
-       /* enum lttng_event_rule_type */
-       int8_t event_rule_type;
-       char payload[];
-};
-
-void lttng_event_rule_init(struct lttng_event_rule *event_rule,
-               enum lttng_event_rule_type type);
-
-bool lttng_event_rule_validate(const struct lttng_event_rule *event_rule);
-
-ssize_t lttng_event_rule_create_from_payload(
-               struct lttng_payload_view *payload,
-               struct lttng_event_rule **event_rule);
-
-int lttng_event_rule_serialize(const struct lttng_event_rule *event_rule,
-               struct lttng_payload *payload);
-
-bool lttng_event_rule_is_equal(const struct lttng_event_rule *a,
-               const struct lttng_event_rule *b);
-
-bool lttng_event_rule_get(struct lttng_event_rule *rule);
-
-void lttng_event_rule_put(struct lttng_event_rule *rule);
-
-enum lttng_domain_type lttng_event_rule_get_domain_type(
-               const struct lttng_event_rule *rule);
-
-enum lttng_error_code lttng_event_rule_generate_filter_bytecode(
-               struct lttng_event_rule *rule,
-               const struct lttng_credentials *creds);
-
-/*
- * If not present/implemented returns NULL.
- * Caller DOES NOT own the returned object.
- */
-const char *lttng_event_rule_get_filter(const struct lttng_event_rule *rule);
-
-/*
- * If not present/implemented returns NULL.
- * Caller DOES NOT own the returned object.
- */
-const struct lttng_bytecode *lttng_event_rule_get_filter_bytecode(
-               const struct lttng_event_rule *rule);
-
-/*
- * If not present/implemented return NULL.
- * Caller OWNS the returned object.
- */
-enum lttng_event_rule_generate_exclusions_status
-lttng_event_rule_generate_exclusions(const struct lttng_event_rule *rule,
-               struct lttng_event_exclusion **exclusions);
-
-const char *lttng_event_rule_type_str(enum lttng_event_rule_type type);
-
-unsigned long lttng_event_rule_hash(const struct lttng_event_rule *rule);
-
-/*
- * This is a compatibility helper allowing us to generate a sessiond-side (not
- * communication) `struct lttng_event` object from an event rule.
- *
- * This effectively bridges older parts of the code using those structures and
- * new event-rule based code.
- *
- * The caller owns the returned object.
- */
-struct lttng_event *lttng_event_rule_generate_lttng_event(
-               const struct lttng_event_rule *rule);
-
-/* Test if an event rule targets an agent domain. */
-bool lttng_event_rule_targets_agent_domain(const struct lttng_event_rule *rule);
-
-enum lttng_error_code lttng_event_rule_mi_serialize(
-               const struct lttng_event_rule *rule, struct mi_writer *writer);
-
-#endif /* LTTNG_EVENT_RULE_INTERNAL_H */
diff --git a/include/lttng/event-rule/event-rule-internal.hpp b/include/lttng/event-rule/event-rule-internal.hpp
new file mode 100644 (file)
index 0000000..46fb981
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_INTERNAL_H
+#define LTTNG_EVENT_RULE_INTERNAL_H
+
+#include <common/macros.hpp>
+#include <common/credentials.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <lttng/domain.h>
+#include <lttng/event.h>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/lttng-error.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <urcu/ref.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+struct mi_writer;
+
+enum lttng_event_rule_generate_exclusions_status {
+       LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK,
+       LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE,
+       LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR,
+       LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY,
+};
+
+typedef void (*event_rule_destroy_cb)(struct lttng_event_rule *event_rule);
+typedef bool (*event_rule_validate_cb)(
+               const struct lttng_event_rule *event_rule);
+typedef int (*event_rule_serialize_cb)(
+               const struct lttng_event_rule *event_rule,
+               struct lttng_payload *payload);
+typedef bool (*event_rule_equal_cb)(const struct lttng_event_rule *a,
+               const struct lttng_event_rule *b);
+typedef ssize_t (*event_rule_create_from_payload_cb)(
+               struct lttng_payload_view *view,
+               struct lttng_event_rule **event_rule);
+typedef enum lttng_error_code (*event_rule_generate_filter_bytecode_cb)(
+               struct lttng_event_rule *event_rule,
+               const struct lttng_credentials *creds);
+typedef const char *(*event_rule_get_filter_cb)(
+               const struct lttng_event_rule *event_rule);
+typedef const struct lttng_bytecode *(
+               *event_rule_get_filter_bytecode_cb)(
+               const struct lttng_event_rule *event_rule);
+typedef enum lttng_event_rule_generate_exclusions_status (
+               *event_rule_generate_exclusions_cb)(
+               const struct lttng_event_rule *event_rule,
+               struct lttng_event_exclusion **exclusions);
+typedef unsigned long (*event_rule_hash_cb)(
+               const struct lttng_event_rule *event_rule);
+typedef struct lttng_event *(*event_rule_generate_lttng_event_cb)(
+               const struct lttng_event_rule *event_rule);
+typedef enum lttng_error_code (*event_rule_mi_serialize_cb)(
+               const struct lttng_event_rule *event_rule,
+               struct mi_writer *writer);
+
+struct lttng_event_rule {
+       struct urcu_ref ref;
+       enum lttng_event_rule_type type;
+       event_rule_validate_cb validate;
+       event_rule_serialize_cb serialize;
+       event_rule_equal_cb equal;
+       event_rule_destroy_cb destroy;
+       event_rule_generate_filter_bytecode_cb generate_filter_bytecode;
+       event_rule_get_filter_cb get_filter;
+       event_rule_get_filter_bytecode_cb get_filter_bytecode;
+       event_rule_generate_exclusions_cb generate_exclusions;
+       event_rule_hash_cb hash;
+       event_rule_generate_lttng_event_cb generate_lttng_event;
+       event_rule_mi_serialize_cb mi_serialize;
+};
+
+struct lttng_event_rule_comm {
+       /* enum lttng_event_rule_type */
+       int8_t event_rule_type;
+       char payload[];
+};
+
+void lttng_event_rule_init(struct lttng_event_rule *event_rule,
+               enum lttng_event_rule_type type);
+
+bool lttng_event_rule_validate(const struct lttng_event_rule *event_rule);
+
+ssize_t lttng_event_rule_create_from_payload(
+               struct lttng_payload_view *payload,
+               struct lttng_event_rule **event_rule);
+
+int lttng_event_rule_serialize(const struct lttng_event_rule *event_rule,
+               struct lttng_payload *payload);
+
+bool lttng_event_rule_is_equal(const struct lttng_event_rule *a,
+               const struct lttng_event_rule *b);
+
+bool lttng_event_rule_get(struct lttng_event_rule *rule);
+
+void lttng_event_rule_put(struct lttng_event_rule *rule);
+
+enum lttng_domain_type lttng_event_rule_get_domain_type(
+               const struct lttng_event_rule *rule);
+
+enum lttng_error_code lttng_event_rule_generate_filter_bytecode(
+               struct lttng_event_rule *rule,
+               const struct lttng_credentials *creds);
+
+/*
+ * If not present/implemented returns NULL.
+ * Caller DOES NOT own the returned object.
+ */
+const char *lttng_event_rule_get_filter(const struct lttng_event_rule *rule);
+
+/*
+ * If not present/implemented returns NULL.
+ * Caller DOES NOT own the returned object.
+ */
+const struct lttng_bytecode *lttng_event_rule_get_filter_bytecode(
+               const struct lttng_event_rule *rule);
+
+/*
+ * If not present/implemented return NULL.
+ * Caller OWNS the returned object.
+ */
+enum lttng_event_rule_generate_exclusions_status
+lttng_event_rule_generate_exclusions(const struct lttng_event_rule *rule,
+               struct lttng_event_exclusion **exclusions);
+
+const char *lttng_event_rule_type_str(enum lttng_event_rule_type type);
+
+unsigned long lttng_event_rule_hash(const struct lttng_event_rule *rule);
+
+/*
+ * This is a compatibility helper allowing us to generate a sessiond-side (not
+ * communication) `struct lttng_event` object from an event rule.
+ *
+ * This effectively bridges older parts of the code using those structures and
+ * new event-rule based code.
+ *
+ * The caller owns the returned object.
+ */
+struct lttng_event *lttng_event_rule_generate_lttng_event(
+               const struct lttng_event_rule *rule);
+
+/* Test if an event rule targets an agent domain. */
+bool lttng_event_rule_targets_agent_domain(const struct lttng_event_rule *rule);
+
+enum lttng_error_code lttng_event_rule_mi_serialize(
+               const struct lttng_event_rule *rule, struct mi_writer *writer);
+
+#endif /* LTTNG_EVENT_RULE_INTERNAL_H */
diff --git a/include/lttng/event-rule/jul-logging-internal.h b/include/lttng/event-rule/jul-logging-internal.h
deleted file mode 100644 (file)
index 21a99eb..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_JUL_LOGGING_INTERNAL_H
-#define LTTNG_EVENT_RULE_JUL_LOGGING_INTERNAL_H
-
-#include <common/payload-view.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/jul-logging.h>
-#include <lttng/event.h>
-#include <lttng/log-level-rule-internal.h>
-
-struct lttng_event_rule_jul_logging {
-       struct lttng_event_rule parent;
-
-       /* Name pattern. */
-       char *pattern;
-
-       /* Filter. */
-       char *filter_expression;
-
-       /* Log level. */
-       struct lttng_log_level_rule *log_level_rule;
-
-       /* internal use only. */
-       struct {
-               char *filter;
-               struct lttng_bytecode *bytecode;
-       } internal_filter;
-};
-
-struct lttng_event_rule_jul_logging_comm {
-       /* Includes terminator `\0`. */
-       uint32_t pattern_len;
-       /* Includes terminator `\0`. */
-       uint32_t filter_expression_len;
-       /*  enum lttng_log_level_rule_comm + payload if any */
-       uint32_t log_level_rule_len;
-       /*
-        * Payload is composed of, in that order:
-        *   - pattern (null terminated),
-        *   - filter expression (null terminated),
-        *   - log level rule serialized object,
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-ssize_t lttng_event_rule_jul_logging_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_event_rule **rule);
-
-#endif /* LTTNG_EVENT_RULE_JUL_LOGGING_INTERNAL_H */
diff --git a/include/lttng/event-rule/jul-logging-internal.hpp b/include/lttng/event-rule/jul-logging-internal.hpp
new file mode 100644 (file)
index 0000000..b769f0f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_JUL_LOGGING_INTERNAL_H
+#define LTTNG_EVENT_RULE_JUL_LOGGING_INTERNAL_H
+
+#include <common/payload-view.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/jul-logging.h>
+#include <lttng/event.h>
+#include <lttng/log-level-rule-internal.hpp>
+
+struct lttng_event_rule_jul_logging {
+       struct lttng_event_rule parent;
+
+       /* Name pattern. */
+       char *pattern;
+
+       /* Filter. */
+       char *filter_expression;
+
+       /* Log level. */
+       struct lttng_log_level_rule *log_level_rule;
+
+       /* internal use only. */
+       struct {
+               char *filter;
+               struct lttng_bytecode *bytecode;
+       } internal_filter;
+};
+
+struct lttng_event_rule_jul_logging_comm {
+       /* Includes terminator `\0`. */
+       uint32_t pattern_len;
+       /* Includes terminator `\0`. */
+       uint32_t filter_expression_len;
+       /*  enum lttng_log_level_rule_comm + payload if any */
+       uint32_t log_level_rule_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - pattern (null terminated),
+        *   - filter expression (null terminated),
+        *   - log level rule serialized object,
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_jul_logging_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_JUL_LOGGING_INTERNAL_H */
diff --git a/include/lttng/event-rule/kernel-kprobe-internal.h b/include/lttng/event-rule/kernel-kprobe-internal.h
deleted file mode 100644 (file)
index 16ac2bd..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_KERNEL_KPROBE_INTERNAL_H
-#define LTTNG_EVENT_RULE_KERNEL_KPROBE_INTERNAL_H
-
-#include <common/payload-view.h>
-#include <common/macros.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/kernel-kprobe.h>
-
-struct lttng_event_rule_kernel_kprobe {
-       struct lttng_event_rule parent;
-       char *name;
-       struct lttng_kernel_probe_location *location;
-};
-
-struct lttng_event_rule_kernel_kprobe_comm {
-       /* Includes terminator `\0`. */
-       uint32_t name_len;
-       uint32_t location_len;
-       /*
-        * Payload is composed of, in that order:
-        *   - name (null terminated),
-        *   - kernel probe location object.
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-ssize_t lttng_event_rule_kernel_kprobe_create_from_payload(
-               struct lttng_payload_view *payload,
-               struct lttng_event_rule **rule);
-
-#endif /* LTTNG_EVENT_RULE_KERNEL_KPROBE_INTERNAL_H */
diff --git a/include/lttng/event-rule/kernel-kprobe-internal.hpp b/include/lttng/event-rule/kernel-kprobe-internal.hpp
new file mode 100644 (file)
index 0000000..5b49979
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_KERNEL_KPROBE_INTERNAL_H
+#define LTTNG_EVENT_RULE_KERNEL_KPROBE_INTERNAL_H
+
+#include <common/payload-view.hpp>
+#include <common/macros.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/kernel-kprobe.h>
+
+struct lttng_event_rule_kernel_kprobe {
+       struct lttng_event_rule parent;
+       char *name;
+       struct lttng_kernel_probe_location *location;
+};
+
+struct lttng_event_rule_kernel_kprobe_comm {
+       /* Includes terminator `\0`. */
+       uint32_t name_len;
+       uint32_t location_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - name (null terminated),
+        *   - kernel probe location object.
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_kernel_kprobe_create_from_payload(
+               struct lttng_payload_view *payload,
+               struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_KERNEL_KPROBE_INTERNAL_H */
diff --git a/include/lttng/event-rule/kernel-syscall-internal.h b/include/lttng/event-rule/kernel-syscall-internal.h
deleted file mode 100644 (file)
index 3012381..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_KERNEL_SYSCALL_INTERNAL_H
-#define LTTNG_EVENT_RULE_KERNEL_SYSCALL_INTERNAL_H
-
-#include <common/payload-view.h>
-#include <common/macros.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/kernel-syscall.h>
-
-struct lttng_event_rule_kernel_syscall {
-       struct lttng_event_rule parent;
-       enum lttng_event_rule_kernel_syscall_emission_site emission_site;
-       char *pattern;
-       char *filter_expression;
-
-       /* Internal use only. */
-       struct {
-               char *filter;
-               struct lttng_bytecode *bytecode;
-       } internal_filter;
-};
-
-struct lttng_event_rule_kernel_syscall_comm {
-       uint32_t emission_site;
-       /* Includes terminator `\0`. */
-       uint32_t pattern_len;
-       /* Includes terminator `\0`. */
-       uint32_t filter_expression_len;
-       /*
-        * Payload is composed of, in that order:
-        *   - Pattern (null terminated),
-        *   - Filter expression (null terminated).
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-ssize_t lttng_event_rule_kernel_syscall_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_event_rule **rule);
-
-const char *lttng_event_rule_kernel_syscall_emission_site_str(
-               enum lttng_event_rule_kernel_syscall_emission_site emission_site);
-
-#endif /* LTTNG_EVENT_RULE_KERNEL_SYSCALL_INTERNAL_H */
diff --git a/include/lttng/event-rule/kernel-syscall-internal.hpp b/include/lttng/event-rule/kernel-syscall-internal.hpp
new file mode 100644 (file)
index 0000000..2ca1823
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_KERNEL_SYSCALL_INTERNAL_H
+#define LTTNG_EVENT_RULE_KERNEL_SYSCALL_INTERNAL_H
+
+#include <common/payload-view.hpp>
+#include <common/macros.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/kernel-syscall.h>
+
+struct lttng_event_rule_kernel_syscall {
+       struct lttng_event_rule parent;
+       enum lttng_event_rule_kernel_syscall_emission_site emission_site;
+       char *pattern;
+       char *filter_expression;
+
+       /* Internal use only. */
+       struct {
+               char *filter;
+               struct lttng_bytecode *bytecode;
+       } internal_filter;
+};
+
+struct lttng_event_rule_kernel_syscall_comm {
+       uint32_t emission_site;
+       /* Includes terminator `\0`. */
+       uint32_t pattern_len;
+       /* Includes terminator `\0`. */
+       uint32_t filter_expression_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - Pattern (null terminated),
+        *   - Filter expression (null terminated).
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_kernel_syscall_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_event_rule **rule);
+
+const char *lttng_event_rule_kernel_syscall_emission_site_str(
+               enum lttng_event_rule_kernel_syscall_emission_site emission_site);
+
+#endif /* LTTNG_EVENT_RULE_KERNEL_SYSCALL_INTERNAL_H */
diff --git a/include/lttng/event-rule/kernel-tracepoint-internal.h b/include/lttng/event-rule/kernel-tracepoint-internal.h
deleted file mode 100644 (file)
index e16596e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_KERNEL_TRACEPOINT_INTERNAL_H
-#define LTTNG_EVENT_RULE_KERNEL_TRACEPOINT_INTERNAL_H
-
-#include <common/payload-view.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/kernel-tracepoint.h>
-#include <lttng/event.h>
-
-struct lttng_event_rule_kernel_tracepoint {
-       struct lttng_event_rule parent;
-
-       /* Name pattern. */
-       char *pattern;
-
-       /* Filter. */
-       char *filter_expression;
-
-       /* internal use only. */
-       struct {
-               char *filter;
-               struct lttng_bytecode *bytecode;
-       } internal_filter;
-};
-
-struct lttng_event_rule_kernel_tracepoint_comm {
-       /* Includes terminator `\0`. */
-       uint32_t pattern_len;
-       /* Includes terminator `\0`. */
-       uint32_t filter_expression_len;
-       /*
-        * Payload is composed of, in that order:
-        *   - pattern (null terminated),
-        *   - filter expression (null terminated),
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-ssize_t lttng_event_rule_kernel_tracepoint_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_event_rule **rule);
-
-#endif /* LTTNG_EVENT_RULE_KERNEL_TRACEPOINT_INTERNAL_H */
diff --git a/include/lttng/event-rule/kernel-tracepoint-internal.hpp b/include/lttng/event-rule/kernel-tracepoint-internal.hpp
new file mode 100644 (file)
index 0000000..d800eef
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_KERNEL_TRACEPOINT_INTERNAL_H
+#define LTTNG_EVENT_RULE_KERNEL_TRACEPOINT_INTERNAL_H
+
+#include <common/payload-view.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/kernel-tracepoint.h>
+#include <lttng/event.h>
+
+struct lttng_event_rule_kernel_tracepoint {
+       struct lttng_event_rule parent;
+
+       /* Name pattern. */
+       char *pattern;
+
+       /* Filter. */
+       char *filter_expression;
+
+       /* internal use only. */
+       struct {
+               char *filter;
+               struct lttng_bytecode *bytecode;
+       } internal_filter;
+};
+
+struct lttng_event_rule_kernel_tracepoint_comm {
+       /* Includes terminator `\0`. */
+       uint32_t pattern_len;
+       /* Includes terminator `\0`. */
+       uint32_t filter_expression_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - pattern (null terminated),
+        *   - filter expression (null terminated),
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_kernel_tracepoint_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_KERNEL_TRACEPOINT_INTERNAL_H */
diff --git a/include/lttng/event-rule/kernel-uprobe-internal.h b/include/lttng/event-rule/kernel-uprobe-internal.h
deleted file mode 100644 (file)
index d8ce557..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_KERNEL_UPROBE_INTERNAL_H
-#define LTTNG_EVENT_RULE_KERNEL_UPROBE_INTERNAL_H
-
-#include <common/payload-view.h>
-#include <common/macros.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/kernel-uprobe.h>
-
-struct lttng_event_rule_kernel_uprobe {
-       struct lttng_event_rule parent;
-       char *name;
-       struct lttng_userspace_probe_location *location;
-};
-
-struct lttng_event_rule_kernel_uprobe_comm {
-       /* Includes terminator `\0`. */
-       uint32_t name_len;
-       /* Includes terminator `\0`. */
-       uint32_t location_len;
-       /*
-        * Payload is composed of, in that order:
-        *   - name (null terminated),
-        *   - user space probe location object.
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-ssize_t lttng_event_rule_kernel_uprobe_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_event_rule **rule);
-
-struct lttng_userspace_probe_location *
-lttng_event_rule_kernel_uprobe_get_location_mutable(
-               const struct lttng_event_rule *rule);
-
-#endif /* LTTNG_EVENT_RULE_KERNEL_UPROBE_INTERNAL_H */
diff --git a/include/lttng/event-rule/kernel-uprobe-internal.hpp b/include/lttng/event-rule/kernel-uprobe-internal.hpp
new file mode 100644 (file)
index 0000000..f9a1931
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_KERNEL_UPROBE_INTERNAL_H
+#define LTTNG_EVENT_RULE_KERNEL_UPROBE_INTERNAL_H
+
+#include <common/payload-view.hpp>
+#include <common/macros.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/kernel-uprobe.h>
+
+struct lttng_event_rule_kernel_uprobe {
+       struct lttng_event_rule parent;
+       char *name;
+       struct lttng_userspace_probe_location *location;
+};
+
+struct lttng_event_rule_kernel_uprobe_comm {
+       /* Includes terminator `\0`. */
+       uint32_t name_len;
+       /* Includes terminator `\0`. */
+       uint32_t location_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - name (null terminated),
+        *   - user space probe location object.
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_kernel_uprobe_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_event_rule **rule);
+
+struct lttng_userspace_probe_location *
+lttng_event_rule_kernel_uprobe_get_location_mutable(
+               const struct lttng_event_rule *rule);
+
+#endif /* LTTNG_EVENT_RULE_KERNEL_UPROBE_INTERNAL_H */
diff --git a/include/lttng/event-rule/log4j-logging-internal.h b/include/lttng/event-rule/log4j-logging-internal.h
deleted file mode 100644 (file)
index 7a1ac28..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_LOG4J_LOGGING_INTERNAL_H
-#define LTTNG_EVENT_RULE_LOG4J_LOGGING_INTERNAL_H
-
-#include <common/payload-view.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/log4j-logging.h>
-#include <lttng/event.h>
-#include <lttng/log-level-rule-internal.h>
-
-struct lttng_event_rule_log4j_logging {
-       struct lttng_event_rule parent;
-
-       /* Name pattern. */
-       char *pattern;
-
-       /* Filter. */
-       char *filter_expression;
-
-       /* Log level. */
-       struct lttng_log_level_rule *log_level_rule;
-
-       /* internal use only. */
-       struct {
-               char *filter;
-               struct lttng_bytecode *bytecode;
-       } internal_filter;
-};
-
-struct lttng_event_rule_log4j_logging_comm {
-       /* Includes terminator `\0`. */
-       uint32_t pattern_len;
-       /* Includes terminator `\0`. */
-       uint32_t filter_expression_len;
-       /*  enum lttng_log_level_rule_comm + payload if any */
-       uint32_t log_level_rule_len;
-       /*
-        * Payload is composed of, in that order:
-        *   - pattern (null terminated),
-        *   - filter expression (null terminated),
-        *   - log level rule serialized object,
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-ssize_t lttng_event_rule_log4j_logging_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_event_rule **rule);
-
-#endif /* LTTNG_EVENT_RULE_LOG4J_LOGGING_INTERNAL_H */
diff --git a/include/lttng/event-rule/log4j-logging-internal.hpp b/include/lttng/event-rule/log4j-logging-internal.hpp
new file mode 100644 (file)
index 0000000..a65e74b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_LOG4J_LOGGING_INTERNAL_H
+#define LTTNG_EVENT_RULE_LOG4J_LOGGING_INTERNAL_H
+
+#include <common/payload-view.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/log4j-logging.h>
+#include <lttng/event.h>
+#include <lttng/log-level-rule-internal.hpp>
+
+struct lttng_event_rule_log4j_logging {
+       struct lttng_event_rule parent;
+
+       /* Name pattern. */
+       char *pattern;
+
+       /* Filter. */
+       char *filter_expression;
+
+       /* Log level. */
+       struct lttng_log_level_rule *log_level_rule;
+
+       /* internal use only. */
+       struct {
+               char *filter;
+               struct lttng_bytecode *bytecode;
+       } internal_filter;
+};
+
+struct lttng_event_rule_log4j_logging_comm {
+       /* Includes terminator `\0`. */
+       uint32_t pattern_len;
+       /* Includes terminator `\0`. */
+       uint32_t filter_expression_len;
+       /*  enum lttng_log_level_rule_comm + payload if any */
+       uint32_t log_level_rule_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - pattern (null terminated),
+        *   - filter expression (null terminated),
+        *   - log level rule serialized object,
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_log4j_logging_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_LOG4J_LOGGING_INTERNAL_H */
diff --git a/include/lttng/event-rule/python-logging-internal.h b/include/lttng/event-rule/python-logging-internal.h
deleted file mode 100644 (file)
index 9f6f7fe..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_PYTHON_LOGGING_INTERNAL_H
-#define LTTNG_EVENT_RULE_PYTHON_LOGGING_INTERNAL_H
-
-#include <common/payload-view.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/python-logging.h>
-#include <lttng/event.h>
-#include <lttng/log-level-rule-internal.h>
-
-struct lttng_event_rule_python_logging {
-       struct lttng_event_rule parent;
-
-       /* Name pattern. */
-       char *pattern;
-
-       /* Filter. */
-       char *filter_expression;
-
-       /* Log level. */
-       struct lttng_log_level_rule *log_level_rule;
-
-       /* internal use only. */
-       struct {
-               char *filter;
-               struct lttng_bytecode *bytecode;
-       } internal_filter;
-};
-
-struct lttng_event_rule_python_logging_comm {
-       /* Includes terminator `\0`. */
-       uint32_t pattern_len;
-       /* Includes terminator `\0`. */
-       uint32_t filter_expression_len;
-       /*  enum lttng_log_level_rule_comm + payload if any */
-       uint32_t log_level_rule_len;
-       /*
-        * Payload is composed of, in that order:
-        *   - pattern (null terminated),
-        *   - filter expression (null terminated),
-        *   - log level rule serialized object,
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-ssize_t lttng_event_rule_python_logging_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_event_rule **rule);
-
-#endif /* LTTNG_EVENT_RULE_PYTHON_LOGGING_INTERNAL_H */
diff --git a/include/lttng/event-rule/python-logging-internal.hpp b/include/lttng/event-rule/python-logging-internal.hpp
new file mode 100644 (file)
index 0000000..d23f4e2
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_PYTHON_LOGGING_INTERNAL_H
+#define LTTNG_EVENT_RULE_PYTHON_LOGGING_INTERNAL_H
+
+#include <common/payload-view.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/python-logging.h>
+#include <lttng/event.h>
+#include <lttng/log-level-rule-internal.hpp>
+
+struct lttng_event_rule_python_logging {
+       struct lttng_event_rule parent;
+
+       /* Name pattern. */
+       char *pattern;
+
+       /* Filter. */
+       char *filter_expression;
+
+       /* Log level. */
+       struct lttng_log_level_rule *log_level_rule;
+
+       /* internal use only. */
+       struct {
+               char *filter;
+               struct lttng_bytecode *bytecode;
+       } internal_filter;
+};
+
+struct lttng_event_rule_python_logging_comm {
+       /* Includes terminator `\0`. */
+       uint32_t pattern_len;
+       /* Includes terminator `\0`. */
+       uint32_t filter_expression_len;
+       /*  enum lttng_log_level_rule_comm + payload if any */
+       uint32_t log_level_rule_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - pattern (null terminated),
+        *   - filter expression (null terminated),
+        *   - log level rule serialized object,
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_python_logging_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_PYTHON_LOGGING_INTERNAL_H */
diff --git a/include/lttng/event-rule/user-tracepoint-internal.h b/include/lttng/event-rule/user-tracepoint-internal.h
deleted file mode 100644 (file)
index 9cd8b05..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_EVENT_RULE_USER_TRACEPOINT_INTERNAL_H
-#define LTTNG_EVENT_RULE_USER_TRACEPOINT_INTERNAL_H
-
-#include <common/payload-view.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <lttng/domain.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/user-tracepoint.h>
-#include <lttng/event.h>
-#include <lttng/log-level-rule-internal.h>
-
-struct lttng_event_rule_user_tracepoint {
-       struct lttng_event_rule parent;
-
-       /* Name pattern. */
-       char *pattern;
-
-       /* Filter. */
-       char *filter_expression;
-
-       /* Log level. */
-       struct lttng_log_level_rule *log_level_rule;
-
-       /* Exclusions. */
-       struct lttng_dynamic_pointer_array exclusions;
-
-       /* internal use only. */
-       struct {
-               char *filter;
-               struct lttng_bytecode *bytecode;
-       } internal_filter;
-};
-
-struct lttng_event_rule_user_tracepoint_comm {
-       /* Includes terminator `\0`. */
-       uint32_t pattern_len;
-       /* Includes terminator `\0`. */
-       uint32_t filter_expression_len;
-       /*  enum lttng_log_level_rule_comm + payload if any */
-       uint32_t log_level_rule_len;
-       uint32_t exclusions_count;
-       uint32_t exclusions_len;
-       /*
-        * Payload is composed of, in that order:
-        *   - pattern (null terminated),
-        *   - filter expression (null terminated),
-        *   - log level rule serialized object,
-        *   - exclusions (32 bit length + null terminated string).
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-ssize_t lttng_event_rule_user_tracepoint_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_event_rule **rule);
-
-#endif /* LTTNG_EVENT_RULE_USER_TRACEPOINT_INTERNAL_H */
diff --git a/include/lttng/event-rule/user-tracepoint-internal.hpp b/include/lttng/event-rule/user-tracepoint-internal.hpp
new file mode 100644 (file)
index 0000000..1960a8a
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_RULE_USER_TRACEPOINT_INTERNAL_H
+#define LTTNG_EVENT_RULE_USER_TRACEPOINT_INTERNAL_H
+
+#include <common/payload-view.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/domain.h>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/user-tracepoint.h>
+#include <lttng/event.h>
+#include <lttng/log-level-rule-internal.hpp>
+
+struct lttng_event_rule_user_tracepoint {
+       struct lttng_event_rule parent;
+
+       /* Name pattern. */
+       char *pattern;
+
+       /* Filter. */
+       char *filter_expression;
+
+       /* Log level. */
+       struct lttng_log_level_rule *log_level_rule;
+
+       /* Exclusions. */
+       struct lttng_dynamic_pointer_array exclusions;
+
+       /* internal use only. */
+       struct {
+               char *filter;
+               struct lttng_bytecode *bytecode;
+       } internal_filter;
+};
+
+struct lttng_event_rule_user_tracepoint_comm {
+       /* Includes terminator `\0`. */
+       uint32_t pattern_len;
+       /* Includes terminator `\0`. */
+       uint32_t filter_expression_len;
+       /*  enum lttng_log_level_rule_comm + payload if any */
+       uint32_t log_level_rule_len;
+       uint32_t exclusions_count;
+       uint32_t exclusions_len;
+       /*
+        * Payload is composed of, in that order:
+        *   - pattern (null terminated),
+        *   - filter expression (null terminated),
+        *   - log level rule serialized object,
+        *   - exclusions (32 bit length + null terminated string).
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+ssize_t lttng_event_rule_user_tracepoint_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_event_rule **rule);
+
+#endif /* LTTNG_EVENT_RULE_USER_TRACEPOINT_INTERNAL_H */
diff --git a/include/lttng/health-internal.h b/include/lttng/health-internal.h
deleted file mode 100644 (file)
index ceda0a8..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-#ifndef HEALTH_INTERNAL_H
-#define HEALTH_INTERNAL_H
-
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <common/compat/time.h>
-#include <pthread.h>
-#include <urcu/tls-compat.h>
-#include <urcu/uatomic.h>
-#include <urcu/list.h>
-#include <lttng/health.h>
-#include <common/macros.h>
-
-/*
- * These are the value added to the current state depending of the position in
- * the thread where is either waiting on a poll() or running in the code.
- */
-#define HEALTH_POLL_VALUE      (1UL << 0)
-#define HEALTH_CODE_VALUE      (1UL << 1)
-
-#define HEALTH_IS_IN_POLL(x)   ((x) & HEALTH_POLL_VALUE)
-
-struct health_app;
-
-enum health_flags {
-       HEALTH_ERROR                     = (1U << 0),
-};
-
-struct health_state {
-       /*
-        * last counter and last_time are only read and updated by the health_check
-        * thread (single updater).
-        */
-       unsigned long last;
-       struct timespec last_time;
-
-       /*
-        * current and flags are updated by multiple threads concurrently.
-        */
-       unsigned long current;          /* progress counter, updated atomically */
-       enum health_flags flags;        /* other flags, updated atomically */
-       int type;                       /* Indicates the nature of the thread. */
-       /* Node of the global TLS state list. */
-       struct cds_list_head node;
-};
-
-enum health_cmd {
-       HEALTH_CMD_CHECK                = 0,
-};
-
-struct health_comm_msg {
-       uint32_t cmd;           /* enum health_cmd */
-} LTTNG_PACKED;
-
-struct health_comm_reply {
-       uint64_t ret_code;      /* bitmask of threads in bad health */
-} LTTNG_PACKED;
-
-/* Declare TLS health state. */
-extern DECLARE_URCU_TLS(struct health_state, health_state);
-
-/*
- * Update current counter by 1 to indicate that the thread entered or left a
- * blocking state caused by a poll(). If the counter's value is not an even
- * number (meaning a code execution flow), an LTTNG_ASSERT() is raised.
- */
-static inline void health_poll_entry(void)
-{
-       /* Code MUST be in code execution state which is an even number. */
-       LTTNG_ASSERT(!(uatomic_read(&URCU_TLS(health_state).current)
-                               & HEALTH_POLL_VALUE));
-
-       uatomic_add(&URCU_TLS(health_state).current, HEALTH_POLL_VALUE);
-}
-
-/*
- * Update current counter by 1 indicating the exit of a poll or blocking call.
- * If the counter's value is not an odd number (a poll execution), an LTTNG_ASSERT()
- * is raised.
- */
-static inline void health_poll_exit(void)
-{
-       /* Code MUST be in poll execution state which is an odd number. */
-       LTTNG_ASSERT(uatomic_read(&URCU_TLS(health_state).current)
-                               & HEALTH_POLL_VALUE);
-
-       uatomic_add(&URCU_TLS(health_state).current, HEALTH_POLL_VALUE);
-}
-
-/*
- * Update current counter by 2 indicates progress in execution of a
- * thread.
- */
-static inline void health_code_update(void)
-{
-       uatomic_add(&URCU_TLS(health_state).current, HEALTH_CODE_VALUE);
-}
-
-/*
- * Set health "error" flag.
- */
-static inline void health_error(void)
-{
-       uatomic_or(&URCU_TLS(health_state).flags, HEALTH_ERROR);
-}
-
-struct health_app *health_app_create(int nr_types);
-void health_app_destroy(struct health_app *ha);
-int health_check_state(struct health_app *ha, int type);
-void health_register(struct health_app *ha, int type);
-void health_unregister(struct health_app *ha);
-
-#endif /* HEALTH_INTERNAL_H */
diff --git a/include/lttng/health-internal.hpp b/include/lttng/health-internal.hpp
new file mode 100644 (file)
index 0000000..67bdc6a
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef HEALTH_INTERNAL_H
+#define HEALTH_INTERNAL_H
+
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <common/compat/time.hpp>
+#include <pthread.h>
+#include <urcu/tls-compat.h>
+#include <urcu/uatomic.h>
+#include <urcu/list.h>
+#include <lttng/health.h>
+#include <common/macros.hpp>
+
+/*
+ * These are the value added to the current state depending of the position in
+ * the thread where is either waiting on a poll() or running in the code.
+ */
+#define HEALTH_POLL_VALUE      (1UL << 0)
+#define HEALTH_CODE_VALUE      (1UL << 1)
+
+#define HEALTH_IS_IN_POLL(x)   ((x) & HEALTH_POLL_VALUE)
+
+struct health_app;
+
+enum health_flags {
+       HEALTH_ERROR                     = (1U << 0),
+};
+
+struct health_state {
+       /*
+        * last counter and last_time are only read and updated by the health_check
+        * thread (single updater).
+        */
+       unsigned long last;
+       struct timespec last_time;
+
+       /*
+        * current and flags are updated by multiple threads concurrently.
+        */
+       unsigned long current;          /* progress counter, updated atomically */
+       enum health_flags flags;        /* other flags, updated atomically */
+       int type;                       /* Indicates the nature of the thread. */
+       /* Node of the global TLS state list. */
+       struct cds_list_head node;
+};
+
+enum health_cmd {
+       HEALTH_CMD_CHECK                = 0,
+};
+
+struct health_comm_msg {
+       uint32_t cmd;           /* enum health_cmd */
+} LTTNG_PACKED;
+
+struct health_comm_reply {
+       uint64_t ret_code;      /* bitmask of threads in bad health */
+} LTTNG_PACKED;
+
+/* Declare TLS health state. */
+extern DECLARE_URCU_TLS(struct health_state, health_state);
+
+/*
+ * Update current counter by 1 to indicate that the thread entered or left a
+ * blocking state caused by a poll(). If the counter's value is not an even
+ * number (meaning a code execution flow), an LTTNG_ASSERT() is raised.
+ */
+static inline void health_poll_entry(void)
+{
+       /* Code MUST be in code execution state which is an even number. */
+       LTTNG_ASSERT(!(uatomic_read(&URCU_TLS(health_state).current)
+                               & HEALTH_POLL_VALUE));
+
+       uatomic_add(&URCU_TLS(health_state).current, HEALTH_POLL_VALUE);
+}
+
+/*
+ * Update current counter by 1 indicating the exit of a poll or blocking call.
+ * If the counter's value is not an odd number (a poll execution), an LTTNG_ASSERT()
+ * is raised.
+ */
+static inline void health_poll_exit(void)
+{
+       /* Code MUST be in poll execution state which is an odd number. */
+       LTTNG_ASSERT(uatomic_read(&URCU_TLS(health_state).current)
+                               & HEALTH_POLL_VALUE);
+
+       uatomic_add(&URCU_TLS(health_state).current, HEALTH_POLL_VALUE);
+}
+
+/*
+ * Update current counter by 2 indicates progress in execution of a
+ * thread.
+ */
+static inline void health_code_update(void)
+{
+       uatomic_add(&URCU_TLS(health_state).current, HEALTH_CODE_VALUE);
+}
+
+/*
+ * Set health "error" flag.
+ */
+static inline void health_error(void)
+{
+       uatomic_or(&URCU_TLS(health_state).flags, HEALTH_ERROR);
+}
+
+struct health_app *health_app_create(int nr_types);
+void health_app_destroy(struct health_app *ha);
+int health_check_state(struct health_app *ha, int type);
+void health_register(struct health_app *ha, int type);
+void health_unregister(struct health_app *ha);
+
+#endif /* HEALTH_INTERNAL_H */
diff --git a/include/lttng/kernel-probe-internal.h b/include/lttng/kernel-probe-internal.h
deleted file mode 100644 (file)
index 2d2ab86..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_KERNEL_PROBE_INTERNAL_H
-#define LTTNG_KERNEL_PROBE_INTERNAL_H
-
-#include <common/fd-handle.h>
-#include <common/macros.h>
-#include <lttng/lttng-error.h>
-#include <lttng/kernel-probe.h>
-#include <lttng/lttng-error.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-struct lttng_payload;
-struct lttng_payload_view;
-struct lttng_dynamic_buffer;
-struct mi_writer;
-
-typedef bool (*kernel_probe_location_equal_cb)(
-               const struct lttng_kernel_probe_location *a,
-               const struct lttng_kernel_probe_location *b);
-typedef int (*kernel_probe_location_serialize_cb)(
-               const struct lttng_kernel_probe_location *kernel_probe_location,
-               struct lttng_payload *payload);
-typedef bool (*kernel_probe_location_equal_cb)(
-               const struct lttng_kernel_probe_location *a,
-               const struct lttng_kernel_probe_location *b);
-typedef ssize_t (*kernel_probe_location_create_from_payload_cb)(
-               struct lttng_payload_view *view,
-               struct lttng_kernel_probe_location **kernel_probe_location);
-typedef unsigned long (*kernel_probe_location_hash_cb)(
-               const struct lttng_kernel_probe_location *location);
-typedef enum lttng_error_code (*kernel_probe_location_mi_serialize_cb)(
-               const struct lttng_kernel_probe_location *location,
-               struct mi_writer *writer);
-
-struct lttng_kernel_probe_location_comm {
-       /* enum lttng_kernel_probe_location_type */
-       int8_t type;
-       /*
-        * Payload is composed of, in that order,
-        *   - type-specific payload
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-struct lttng_kernel_probe_location_symbol_comm {
-       /* Includes the trailing \0. */
-       uint32_t symbol_len;
-       /* The offset from the symbol. */
-       uint64_t offset;
-       /*
-        * Payload is composed of, in that order,
-        *   - symbol name (with trailing \0).
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-struct lttng_kernel_probe_location_address_comm {
-       uint64_t address;
-} LTTNG_PACKED;
-
-/* Common ancestor of all kernel probe locations. */
-struct lttng_kernel_probe_location {
-       enum lttng_kernel_probe_location_type type;
-       kernel_probe_location_equal_cb equal;
-       kernel_probe_location_serialize_cb serialize;
-       kernel_probe_location_hash_cb hash;
-       kernel_probe_location_mi_serialize_cb mi_serialize;
-};
-
-struct lttng_kernel_probe_location_symbol {
-       struct lttng_kernel_probe_location parent;
-       char *symbol_name;
-       uint64_t offset;
-};
-
-struct lttng_kernel_probe_location_address {
-       struct lttng_kernel_probe_location parent;
-       uint64_t address;
-};
-
-int lttng_kernel_probe_location_serialize(
-               const struct lttng_kernel_probe_location *location,
-               struct lttng_payload *payload);
-
-ssize_t lttng_kernel_probe_location_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_kernel_probe_location **probe_location);
-
-bool lttng_kernel_probe_location_is_equal(
-               const struct lttng_kernel_probe_location *a,
-               const struct lttng_kernel_probe_location *b);
-
-struct lttng_kernel_probe_location *lttng_kernel_probe_location_copy(
-               const struct lttng_kernel_probe_location *location);
-
-unsigned long lttng_kernel_probe_location_hash(
-               const struct lttng_kernel_probe_location *location);
-
-enum lttng_error_code lttng_kernel_probe_location_mi_serialize(
-               const struct lttng_kernel_probe_location *location,
-               struct mi_writer *writer);
-
-#endif /* LTTNG_KERNEL_PROBE_INTERNAL_H */
diff --git a/include/lttng/kernel-probe-internal.hpp b/include/lttng/kernel-probe-internal.hpp
new file mode 100644 (file)
index 0000000..07c546f
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_KERNEL_PROBE_INTERNAL_H
+#define LTTNG_KERNEL_PROBE_INTERNAL_H
+
+#include <common/fd-handle.hpp>
+#include <common/macros.hpp>
+#include <lttng/lttng-error.h>
+#include <lttng/kernel-probe.h>
+#include <lttng/lttng-error.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+struct lttng_dynamic_buffer;
+struct mi_writer;
+
+typedef bool (*kernel_probe_location_equal_cb)(
+               const struct lttng_kernel_probe_location *a,
+               const struct lttng_kernel_probe_location *b);
+typedef int (*kernel_probe_location_serialize_cb)(
+               const struct lttng_kernel_probe_location *kernel_probe_location,
+               struct lttng_payload *payload);
+typedef bool (*kernel_probe_location_equal_cb)(
+               const struct lttng_kernel_probe_location *a,
+               const struct lttng_kernel_probe_location *b);
+typedef ssize_t (*kernel_probe_location_create_from_payload_cb)(
+               struct lttng_payload_view *view,
+               struct lttng_kernel_probe_location **kernel_probe_location);
+typedef unsigned long (*kernel_probe_location_hash_cb)(
+               const struct lttng_kernel_probe_location *location);
+typedef enum lttng_error_code (*kernel_probe_location_mi_serialize_cb)(
+               const struct lttng_kernel_probe_location *location,
+               struct mi_writer *writer);
+
+struct lttng_kernel_probe_location_comm {
+       /* enum lttng_kernel_probe_location_type */
+       int8_t type;
+       /*
+        * Payload is composed of, in that order,
+        *   - type-specific payload
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_kernel_probe_location_symbol_comm {
+       /* Includes the trailing \0. */
+       uint32_t symbol_len;
+       /* The offset from the symbol. */
+       uint64_t offset;
+       /*
+        * Payload is composed of, in that order,
+        *   - symbol name (with trailing \0).
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_kernel_probe_location_address_comm {
+       uint64_t address;
+} LTTNG_PACKED;
+
+/* Common ancestor of all kernel probe locations. */
+struct lttng_kernel_probe_location {
+       enum lttng_kernel_probe_location_type type;
+       kernel_probe_location_equal_cb equal;
+       kernel_probe_location_serialize_cb serialize;
+       kernel_probe_location_hash_cb hash;
+       kernel_probe_location_mi_serialize_cb mi_serialize;
+};
+
+struct lttng_kernel_probe_location_symbol {
+       struct lttng_kernel_probe_location parent;
+       char *symbol_name;
+       uint64_t offset;
+};
+
+struct lttng_kernel_probe_location_address {
+       struct lttng_kernel_probe_location parent;
+       uint64_t address;
+};
+
+int lttng_kernel_probe_location_serialize(
+               const struct lttng_kernel_probe_location *location,
+               struct lttng_payload *payload);
+
+ssize_t lttng_kernel_probe_location_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_kernel_probe_location **probe_location);
+
+bool lttng_kernel_probe_location_is_equal(
+               const struct lttng_kernel_probe_location *a,
+               const struct lttng_kernel_probe_location *b);
+
+struct lttng_kernel_probe_location *lttng_kernel_probe_location_copy(
+               const struct lttng_kernel_probe_location *location);
+
+unsigned long lttng_kernel_probe_location_hash(
+               const struct lttng_kernel_probe_location *location);
+
+enum lttng_error_code lttng_kernel_probe_location_mi_serialize(
+               const struct lttng_kernel_probe_location *location,
+               struct mi_writer *writer);
+
+#endif /* LTTNG_KERNEL_PROBE_INTERNAL_H */
diff --git a/include/lttng/load-internal.h b/include/lttng/load-internal.h
deleted file mode 100644 (file)
index 9284741..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright (C) 2014 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_LOAD_INTERNAL_ABI_H
-#define LTTNG_LOAD_INTERNAL_ABI_H
-
-#include <limits.h>
-#include <stdint.h>
-
-#include <lttng/constant.h>
-#include <common/macros.h>
-#include <common/config/session-config.h>
-
-/*
- * Object used by the load_session API. This is opaque to the public library.
- */
-struct lttng_load_session_attr {
-       /* Name of the session to load, empty string means all. */
-       char session_name[LTTNG_NAME_MAX];
-       /* URL of the session configuration file to load. */
-       char input_url[PATH_MAX];
-       /* Overwrite the session if it exists. */
-       uint32_t overwrite;
-       /* The raw override url for getter */
-       char *raw_override_url;
-       /* The raw override path url for getter */
-       char *raw_override_path_url;
-       /* The raw override ctrl url for getter */
-       char *raw_override_ctrl_url;
-       /* The raw override data url for getter */
-       char *raw_override_data_url;
-       /* Override struct */
-       struct config_load_session_override_attr *override_attr;
-} LTTNG_PACKED;
-
-#endif /* LTTNG_LOAD_INTERNAL_ABI_H */
diff --git a/include/lttng/load-internal.hpp b/include/lttng/load-internal.hpp
new file mode 100644 (file)
index 0000000..ef09ffd
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2014 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_LOAD_INTERNAL_ABI_H
+#define LTTNG_LOAD_INTERNAL_ABI_H
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <lttng/constant.h>
+#include <common/macros.hpp>
+#include <common/config/session-config.hpp>
+
+/*
+ * Object used by the load_session API. This is opaque to the public library.
+ */
+struct lttng_load_session_attr {
+       /* Name of the session to load, empty string means all. */
+       char session_name[LTTNG_NAME_MAX];
+       /* URL of the session configuration file to load. */
+       char input_url[PATH_MAX];
+       /* Overwrite the session if it exists. */
+       uint32_t overwrite;
+       /* The raw override url for getter */
+       char *raw_override_url;
+       /* The raw override path url for getter */
+       char *raw_override_path_url;
+       /* The raw override ctrl url for getter */
+       char *raw_override_ctrl_url;
+       /* The raw override data url for getter */
+       char *raw_override_data_url;
+       /* Override struct */
+       struct config_load_session_override_attr *override_attr;
+} LTTNG_PACKED;
+
+#endif /* LTTNG_LOAD_INTERNAL_ABI_H */
diff --git a/include/lttng/location-internal.h b/include/lttng/location-internal.h
deleted file mode 100644 (file)
index 33498c9..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_LOCATION_INTERNAL_H
-#define LTTNG_LOCATION_INTERNAL_H
-
-#include <lttng/location.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <common/macros.h>
-#include <sys/types.h>
-#include <urcu/ref.h>
-
-/*
- * The public API assumes that trace archive locations are always
- * provided as "constant". This means that the user of liblttng-ctl never
- * has to destroy a trace archive location. Hence, users of liblttng-ctl
- * have no visibility of the reference counting of archive locations.
- */
-struct lttng_trace_archive_location {
-       struct urcu_ref ref;
-       enum lttng_trace_archive_location_type type;
-       union {
-               struct {
-                       char *absolute_path;
-               } local;
-               struct {
-                       char *host;
-                       enum lttng_trace_archive_location_relay_protocol_type protocol;
-                       struct {
-                               uint16_t control, data;
-                       } ports;
-                       char *relative_path;
-               } relay;
-       } types;
-};
-
-struct lttng_trace_archive_location_comm {
-       /* A value from enum lttng_trace_archive_location_type */
-       int8_t type;
-       union {
-               struct {
-                       /* Includes the trailing \0. */
-                       uint32_t absolute_path_len;
-               } LTTNG_PACKED local;
-               struct {
-                       /* Includes the trailing \0. */
-                       uint32_t hostname_len;
-                       /*
-                        * A value from
-                        * enum lttng_trace_archive_location_relay_protocol_type.
-                        */
-                       int8_t protocol;
-                       struct {
-                               uint16_t control, data;
-                       } ports;
-                       /* Includes the trailing \0. */
-                       uint32_t relative_path_len;
-               } LTTNG_PACKED relay;
-       } LTTNG_PACKED types;
-       /*
-        * Payload is composed of:
-        * - LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL
-        *   - absolute path, including \0
-        * - LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY
-        *   - hostname, including \0
-        *   - relative path, including \0
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-
-struct lttng_trace_archive_location *lttng_trace_archive_location_local_create(
-               const char *path);
-
-struct lttng_trace_archive_location *lttng_trace_archive_location_relay_create(
-               const char *host,
-               enum lttng_trace_archive_location_relay_protocol_type protocol,
-               uint16_t control_port, uint16_t data_port,
-               const char *relative_path);
-
-ssize_t lttng_trace_archive_location_create_from_buffer(
-               const struct lttng_buffer_view *buffer,
-               struct lttng_trace_archive_location **location);
-
-ssize_t lttng_trace_archive_location_serialize(
-               const struct lttng_trace_archive_location *location,
-               struct lttng_dynamic_buffer *buffer);
-
-void lttng_trace_archive_location_get(
-               struct lttng_trace_archive_location *location);
-
-void lttng_trace_archive_location_put(
-               struct lttng_trace_archive_location *location);
-
-#endif /* LTTNG_LOCATION_INTERNAL_H */
diff --git a/include/lttng/location-internal.hpp b/include/lttng/location-internal.hpp
new file mode 100644 (file)
index 0000000..4daeed0
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_LOCATION_INTERNAL_H
+#define LTTNG_LOCATION_INTERNAL_H
+
+#include <lttng/location.h>
+#include <common/dynamic-buffer.hpp>
+#include <common/buffer-view.hpp>
+#include <common/macros.hpp>
+#include <sys/types.h>
+#include <urcu/ref.h>
+
+/*
+ * The public API assumes that trace archive locations are always
+ * provided as "constant". This means that the user of liblttng-ctl never
+ * has to destroy a trace archive location. Hence, users of liblttng-ctl
+ * have no visibility of the reference counting of archive locations.
+ */
+struct lttng_trace_archive_location {
+       struct urcu_ref ref;
+       enum lttng_trace_archive_location_type type;
+       union {
+               struct {
+                       char *absolute_path;
+               } local;
+               struct {
+                       char *host;
+                       enum lttng_trace_archive_location_relay_protocol_type protocol;
+                       struct {
+                               uint16_t control, data;
+                       } ports;
+                       char *relative_path;
+               } relay;
+       } types;
+};
+
+struct lttng_trace_archive_location_comm {
+       /* A value from enum lttng_trace_archive_location_type */
+       int8_t type;
+       union {
+               struct {
+                       /* Includes the trailing \0. */
+                       uint32_t absolute_path_len;
+               } LTTNG_PACKED local;
+               struct {
+                       /* Includes the trailing \0. */
+                       uint32_t hostname_len;
+                       /*
+                        * A value from
+                        * enum lttng_trace_archive_location_relay_protocol_type.
+                        */
+                       int8_t protocol;
+                       struct {
+                               uint16_t control, data;
+                       } ports;
+                       /* Includes the trailing \0. */
+                       uint32_t relative_path_len;
+               } LTTNG_PACKED relay;
+       } LTTNG_PACKED types;
+       /*
+        * Payload is composed of:
+        * - LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL
+        *   - absolute path, including \0
+        * - LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY
+        *   - hostname, including \0
+        *   - relative path, including \0
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+
+struct lttng_trace_archive_location *lttng_trace_archive_location_local_create(
+               const char *path);
+
+struct lttng_trace_archive_location *lttng_trace_archive_location_relay_create(
+               const char *host,
+               enum lttng_trace_archive_location_relay_protocol_type protocol,
+               uint16_t control_port, uint16_t data_port,
+               const char *relative_path);
+
+ssize_t lttng_trace_archive_location_create_from_buffer(
+               const struct lttng_buffer_view *buffer,
+               struct lttng_trace_archive_location **location);
+
+ssize_t lttng_trace_archive_location_serialize(
+               const struct lttng_trace_archive_location *location,
+               struct lttng_dynamic_buffer *buffer);
+
+void lttng_trace_archive_location_get(
+               struct lttng_trace_archive_location *location);
+
+void lttng_trace_archive_location_put(
+               struct lttng_trace_archive_location *location);
+
+#endif /* LTTNG_LOCATION_INTERNAL_H */
diff --git a/include/lttng/log-level-rule-internal.h b/include/lttng/log-level-rule-internal.h
deleted file mode 100644 (file)
index ac0f74b..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_LOG_LEVEL_RULE_INTERNAL_H
-#define LTTNG_LOG_LEVEL_RULE_INTERNAL_H
-
-#include <stdint.h>
-
-#include <common/buffer-view.h>
-#include <common/dynamic-array.h>
-#include <common/macros.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/event.h>
-#include <lttng/log-level-rule.h>
-#include <lttng/lttng-error.h>
-
-struct mi_writer;
-
-/*
- * For now only a single backing struct is used for both type of log level
- * rule (exactly, as_severe) since both only have require "level" as property.
- */
-struct lttng_log_level_rule {
-       enum lttng_log_level_rule_type type;
-       int level;
-};
-
-struct lttng_log_level_rule_comm {
-       /* enum lttng_log_level_rule_type */
-       int8_t type;
-       int32_t level;
-};
-
-ssize_t lttng_log_level_rule_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_log_level_rule **rule);
-
-int lttng_log_level_rule_serialize(const struct lttng_log_level_rule *rule,
-               struct lttng_payload *payload);
-
-bool lttng_log_level_rule_is_equal(const struct lttng_log_level_rule *a,
-               const struct lttng_log_level_rule *b);
-
-struct lttng_log_level_rule *lttng_log_level_rule_copy(
-               const struct lttng_log_level_rule *source);
-
-void lttng_log_level_rule_to_loglevel(
-               const struct lttng_log_level_rule *log_level_rule,
-               enum lttng_loglevel_type *loglevel_type,
-               int *loglevel_value);
-
-unsigned long lttng_log_level_rule_hash(
-               const struct lttng_log_level_rule *log_level_rule);
-
-enum lttng_error_code lttng_log_level_rule_mi_serialize(
-               const struct lttng_log_level_rule *rule,
-               struct mi_writer *writer);
-
-#endif /* LTTNG_LOG_LEVEL_RULE_INTERNAL_H */
diff --git a/include/lttng/log-level-rule-internal.hpp b/include/lttng/log-level-rule-internal.hpp
new file mode 100644 (file)
index 0000000..71447cf
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_LOG_LEVEL_RULE_INTERNAL_H
+#define LTTNG_LOG_LEVEL_RULE_INTERNAL_H
+
+#include <stdint.h>
+
+#include <common/buffer-view.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/macros.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/event.h>
+#include <lttng/log-level-rule.h>
+#include <lttng/lttng-error.h>
+
+struct mi_writer;
+
+/*
+ * For now only a single backing struct is used for both type of log level
+ * rule (exactly, as_severe) since both only have require "level" as property.
+ */
+struct lttng_log_level_rule {
+       enum lttng_log_level_rule_type type;
+       int level;
+};
+
+struct lttng_log_level_rule_comm {
+       /* enum lttng_log_level_rule_type */
+       int8_t type;
+       int32_t level;
+};
+
+ssize_t lttng_log_level_rule_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_log_level_rule **rule);
+
+int lttng_log_level_rule_serialize(const struct lttng_log_level_rule *rule,
+               struct lttng_payload *payload);
+
+bool lttng_log_level_rule_is_equal(const struct lttng_log_level_rule *a,
+               const struct lttng_log_level_rule *b);
+
+struct lttng_log_level_rule *lttng_log_level_rule_copy(
+               const struct lttng_log_level_rule *source);
+
+void lttng_log_level_rule_to_loglevel(
+               const struct lttng_log_level_rule *log_level_rule,
+               enum lttng_loglevel_type *loglevel_type,
+               int *loglevel_value);
+
+unsigned long lttng_log_level_rule_hash(
+               const struct lttng_log_level_rule *log_level_rule);
+
+enum lttng_error_code lttng_log_level_rule_mi_serialize(
+               const struct lttng_log_level_rule *rule,
+               struct mi_writer *writer);
+
+#endif /* LTTNG_LOG_LEVEL_RULE_INTERNAL_H */
diff --git a/include/lttng/notification/channel-internal.h b/include/lttng/notification/channel-internal.h
deleted file mode 100644 (file)
index befdca0..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H
-#define LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H
-
-#include <lttng/notification/channel.h>
-#include <common/macros.h>
-#include <common/payload.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <pthread.h>
-#include <urcu/list.h>
-
-/*
- * Protocol version change log:
- * - v1.0
- *   - Initial implementation of the notification channel protocol,
- *   - Supported conditions are LOW/HIGH buffer usage conditions,
- * - v1.1
- *   - New condition type "LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE" added,
- *   - New condition type "LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING" added,
- *   - New condition type "LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED" added,
- */
-#define LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR 1
-#define LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR 1
-
-enum lttng_notification_channel_message_type {
-       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN = -1,
-       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE = 0,
-       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE = 1,
-       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE = 2,
-       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY = 3,
-       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION = 4,
-       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED = 5,
-};
-
-struct lttng_notification_channel_message {
-       /* enum lttng_notification_channel_message_type */
-       int8_t type;
-       /* Size of the payload following this field. */
-       uint32_t size;
-       /* Number of FDs sent. */
-       uint32_t fds;
-       char payload[];
-} LTTNG_PACKED;
-
-struct lttng_notification_channel_command_handshake {
-       uint8_t major;
-       uint8_t minor;
-} LTTNG_PACKED;
-
-struct lttng_notification_channel_command_reply {
-       /* enum lttng_notification_channel_status */
-       int8_t status;
-} LTTNG_PACKED;
-
-struct pending_notification {
-       /* NULL means "notification dropped". */
-       struct lttng_notification *notification;
-       struct cds_list_head node;
-};
-
-/*
- * The notification channel protocol is bidirectional and accommodates
- * synchronous and asynchronous communication modes:
- *
- *   - Synchronous: commands emitted by the client to which a reply is expected
- *     (e.g. subscribing/unsubscribing to conditions),
- *   - Asynchronous: notifications which are sent by the lttng_endpoint to the
- *     client as one of the subscribed condition has occurred.
- *
- * The nature of this hybrid communication mode means that asynchronous messages
- * (e.g. notifications) may be interleaved between synchronous messages (e.g. a
- * command and its reply).
- *
- * Notifications that are received between a command and its reply and enqueued
- * in the pending_notifications list.
- */
-struct lttng_notification_channel {
-       pthread_mutex_t lock;
-       int socket;
-       struct {
-               /* Count of pending notifications. */
-               unsigned int count;
-               /* List of struct pending_notification. */
-               struct cds_list_head list;
-       } pending_notifications;
-       struct lttng_payload reception_payload;
-       /* Sessiond notification protocol version. */
-       struct {
-               bool set;
-               int8_t major, minor;
-       } version;
-};
-
-#endif /* LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H */
diff --git a/include/lttng/notification/channel-internal.hpp b/include/lttng/notification/channel-internal.hpp
new file mode 100644 (file)
index 0000000..3364704
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H
+#define LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H
+
+#include <lttng/notification/channel.h>
+#include <common/macros.hpp>
+#include <common/payload.hpp>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <urcu/list.h>
+
+/*
+ * Protocol version change log:
+ * - v1.0
+ *   - Initial implementation of the notification channel protocol,
+ *   - Supported conditions are LOW/HIGH buffer usage conditions,
+ * - v1.1
+ *   - New condition type "LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE" added,
+ *   - New condition type "LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING" added,
+ *   - New condition type "LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED" added,
+ */
+#define LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR 1
+#define LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR 1
+
+enum lttng_notification_channel_message_type {
+       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN = -1,
+       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE = 0,
+       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE = 1,
+       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE = 2,
+       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY = 3,
+       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION = 4,
+       LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED = 5,
+};
+
+struct lttng_notification_channel_message {
+       /* enum lttng_notification_channel_message_type */
+       int8_t type;
+       /* Size of the payload following this field. */
+       uint32_t size;
+       /* Number of FDs sent. */
+       uint32_t fds;
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_notification_channel_command_handshake {
+       uint8_t major;
+       uint8_t minor;
+} LTTNG_PACKED;
+
+struct lttng_notification_channel_command_reply {
+       /* enum lttng_notification_channel_status */
+       int8_t status;
+} LTTNG_PACKED;
+
+struct pending_notification {
+       /* NULL means "notification dropped". */
+       struct lttng_notification *notification;
+       struct cds_list_head node;
+};
+
+/*
+ * The notification channel protocol is bidirectional and accommodates
+ * synchronous and asynchronous communication modes:
+ *
+ *   - Synchronous: commands emitted by the client to which a reply is expected
+ *     (e.g. subscribing/unsubscribing to conditions),
+ *   - Asynchronous: notifications which are sent by the lttng_endpoint to the
+ *     client as one of the subscribed condition has occurred.
+ *
+ * The nature of this hybrid communication mode means that asynchronous messages
+ * (e.g. notifications) may be interleaved between synchronous messages (e.g. a
+ * command and its reply).
+ *
+ * Notifications that are received between a command and its reply and enqueued
+ * in the pending_notifications list.
+ */
+struct lttng_notification_channel {
+       pthread_mutex_t lock;
+       int socket;
+       struct {
+               /* Count of pending notifications. */
+               unsigned int count;
+               /* List of struct pending_notification. */
+               struct cds_list_head list;
+       } pending_notifications;
+       struct lttng_payload reception_payload;
+       /* Sessiond notification protocol version. */
+       struct {
+               bool set;
+               int8_t major, minor;
+       } version;
+};
+
+#endif /* LTTNG_NOTIFICATION_CHANNEL_INTERNAL_H */
diff --git a/include/lttng/notification/notification-internal.h b/include/lttng/notification/notification-internal.h
deleted file mode 100644 (file)
index 7e601b0..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_NOTIFICATION_INTERNAL_H
-#define LTTNG_NOTIFICATION_INTERNAL_H
-
-#include <lttng/notification/notification.h>
-#include <common/macros.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <sys/types.h>
-
-struct lttng_payload;
-struct lttng_payload_view;
-
-struct lttng_notification {
-       struct lttng_trigger *trigger;
-       struct lttng_evaluation *evaluation;
-};
-
-struct lttng_notification_comm {
-       /* Size of the payload following this field. */
-       uint32_t length;
-       /* Trigger and evaluation objects follow. */
-       char payload[];
-} LTTNG_PACKED;
-
-struct lttng_notification *lttng_notification_create(
-               struct lttng_trigger *trigger,
-               struct lttng_evaluation *evaluation);
-
-int lttng_notification_serialize(const struct lttng_notification *notification,
-               struct lttng_payload *payload);
-
-ssize_t lttng_notification_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_notification **notification);
-
-#endif /* LTTNG_NOTIFICATION_INTERNAL_H */
diff --git a/include/lttng/notification/notification-internal.hpp b/include/lttng/notification/notification-internal.hpp
new file mode 100644 (file)
index 0000000..37c8f2a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_NOTIFICATION_INTERNAL_H
+#define LTTNG_NOTIFICATION_INTERNAL_H
+
+#include <lttng/notification/notification.h>
+#include <common/macros.hpp>
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+
+struct lttng_notification {
+       struct lttng_trigger *trigger;
+       struct lttng_evaluation *evaluation;
+};
+
+struct lttng_notification_comm {
+       /* Size of the payload following this field. */
+       uint32_t length;
+       /* Trigger and evaluation objects follow. */
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_notification *lttng_notification_create(
+               struct lttng_trigger *trigger,
+               struct lttng_evaluation *evaluation);
+
+int lttng_notification_serialize(const struct lttng_notification *notification,
+               struct lttng_payload *payload);
+
+ssize_t lttng_notification_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_notification **notification);
+
+#endif /* LTTNG_NOTIFICATION_INTERNAL_H */
diff --git a/include/lttng/ref-internal.h b/include/lttng/ref-internal.h
deleted file mode 100644 (file)
index a02ae4c..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef LTTNG_REF_INTERNAL_H
-#define LTTNG_REF_INTERNAL_H
-
-/*
- * LTTng - Non thread-safe reference counting
- *
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-
-typedef void (*lttng_release_func)(void *);
-
-struct lttng_ref {
-       unsigned long count;
-       lttng_release_func release;
-};
-
-static inline
-void lttng_ref_init(struct lttng_ref *ref, lttng_release_func release)
-{
-       LTTNG_ASSERT(ref);
-       ref->count = 1;
-       ref->release = release;
-}
-
-static inline
-void lttng_ref_get(struct lttng_ref *ref)
-{
-       LTTNG_ASSERT(ref);
-       ref->count++;
-       /* Overflow check. */
-       LTTNG_ASSERT(ref->count);
-}
-
-static inline
-void lttng_ref_put(struct lttng_ref *ref)
-{
-       LTTNG_ASSERT(ref);
-       /* Underflow check. */
-       LTTNG_ASSERT(ref->count);
-       if (caa_unlikely((--ref->count) == 0)) {
-               ref->release(ref);
-       }
-}
-
-#endif /* LTTNG_REF_INTERNAL_H */
diff --git a/include/lttng/ref-internal.hpp b/include/lttng/ref-internal.hpp
new file mode 100644 (file)
index 0000000..a02ae4c
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef LTTNG_REF_INTERNAL_H
+#define LTTNG_REF_INTERNAL_H
+
+/*
+ * LTTng - Non thread-safe reference counting
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+
+typedef void (*lttng_release_func)(void *);
+
+struct lttng_ref {
+       unsigned long count;
+       lttng_release_func release;
+};
+
+static inline
+void lttng_ref_init(struct lttng_ref *ref, lttng_release_func release)
+{
+       LTTNG_ASSERT(ref);
+       ref->count = 1;
+       ref->release = release;
+}
+
+static inline
+void lttng_ref_get(struct lttng_ref *ref)
+{
+       LTTNG_ASSERT(ref);
+       ref->count++;
+       /* Overflow check. */
+       LTTNG_ASSERT(ref->count);
+}
+
+static inline
+void lttng_ref_put(struct lttng_ref *ref)
+{
+       LTTNG_ASSERT(ref);
+       /* Underflow check. */
+       LTTNG_ASSERT(ref->count);
+       if (caa_unlikely((--ref->count) == 0)) {
+               ref->release(ref);
+       }
+}
+
+#endif /* LTTNG_REF_INTERNAL_H */
diff --git a/include/lttng/rotate-internal.h b/include/lttng/rotate-internal.h
deleted file mode 100644 (file)
index 0296efe..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_ROTATE_INTERNAL_ABI_H
-#define LTTNG_ROTATE_INTERNAL_ABI_H
-
-#include <limits.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#include <lttng/constant.h>
-#include <lttng/rotation.h>
-#include <common/macros.h>
-
-/*
- * Object returned by the rotate session API.
- * This is opaque to the public library.
- */
-struct lttng_rotation_handle {
-       char session_name[LTTNG_NAME_MAX];
-       /*
-        * ID of the rotate command.
-        * This matches the session->rotate_count, so the handle is valid until
-        * the next rotate command. After that, the rotation_get_state command
-        * returns the "expired" state.
-        */
-       uint64_t rotation_id;
-       /*
-        * Where the rotated (readable) trace has been stored when the
-        * rotation is completed.
-        */
-       struct lttng_trace_archive_location *archive_location;
-};
-
-struct lttng_rotation_schedule {
-       enum lttng_rotation_schedule_type type;
-};
-
-struct lttng_rotation_schedule_size_threshold {
-       struct lttng_rotation_schedule parent;
-       struct {
-               bool set;
-               uint64_t bytes;
-       } size;
-};
-
-struct lttng_rotation_schedule_periodic {
-       struct lttng_rotation_schedule parent;
-       struct {
-               bool set;
-               uint64_t us;
-       } period;
-};
-
-struct lttng_rotation_schedules {
-       /*
-        * Only one rotation schedule per type is supported for now.
-        * Schedules are owned by this object.
-        */
-       unsigned int count;
-       struct lttng_rotation_schedule *schedules[2];
-};
-
-/*
- * Internal objects between lttng-ctl and the session daemon, the values
- * are then copied to the user's lttng_rotation_handle object.
- */
-
-/* For the LTTNG_ROTATE_SESSION command. */
-struct lttng_rotate_session_return {
-       uint64_t rotation_id;
-} LTTNG_PACKED;
-
-/* For the LTTNG_ROTATION_GET_INFO command. */
-struct lttng_rotation_get_info_return {
-       /* Represents values defined in enum lttng_rotation_state. */
-       int32_t status;
-       /*
-        * Represents values defined in enum lttng_trace_archive_location_type.
-        */
-       int8_t location_type;
-       union {
-               struct {
-                       char absolute_path[LTTNG_PATH_MAX];
-               } LTTNG_PACKED local;
-               struct {
-                       char host[LTTNG_HOST_NAME_MAX];
-                       /*
-                        * Represents values defined in
-                        * enum lttng_trace_archive_location_relay_protocol_type.
-                        */
-                       int8_t protocol;
-                       struct {
-                               uint16_t control;
-                               uint16_t data;
-                       } LTTNG_PACKED ports;
-                       char relative_path[LTTNG_PATH_MAX];
-               } LTTNG_PACKED relay;
-       } location;
-} LTTNG_PACKED;
-
-/* For the LTTNG_SESSION_LIST_SCHEDULES command. */
-struct lttng_session_list_schedules_return {
-       struct {
-               uint8_t set;
-               uint64_t value;
-       } LTTNG_PACKED periodic;
-       struct {
-               uint8_t set;
-               uint64_t value;
-       } LTTNG_PACKED size;
-} LTTNG_PACKED;
-
-#endif /* LTTNG_ROTATE_INTERNAL_ABI_H */
diff --git a/include/lttng/rotate-internal.hpp b/include/lttng/rotate-internal.hpp
new file mode 100644 (file)
index 0000000..076f50a
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_ROTATE_INTERNAL_ABI_H
+#define LTTNG_ROTATE_INTERNAL_ABI_H
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <lttng/constant.h>
+#include <lttng/rotation.h>
+#include <common/macros.hpp>
+
+/*
+ * Object returned by the rotate session API.
+ * This is opaque to the public library.
+ */
+struct lttng_rotation_handle {
+       char session_name[LTTNG_NAME_MAX];
+       /*
+        * ID of the rotate command.
+        * This matches the session->rotate_count, so the handle is valid until
+        * the next rotate command. After that, the rotation_get_state command
+        * returns the "expired" state.
+        */
+       uint64_t rotation_id;
+       /*
+        * Where the rotated (readable) trace has been stored when the
+        * rotation is completed.
+        */
+       struct lttng_trace_archive_location *archive_location;
+};
+
+struct lttng_rotation_schedule {
+       enum lttng_rotation_schedule_type type;
+};
+
+struct lttng_rotation_schedule_size_threshold {
+       struct lttng_rotation_schedule parent;
+       struct {
+               bool set;
+               uint64_t bytes;
+       } size;
+};
+
+struct lttng_rotation_schedule_periodic {
+       struct lttng_rotation_schedule parent;
+       struct {
+               bool set;
+               uint64_t us;
+       } period;
+};
+
+struct lttng_rotation_schedules {
+       /*
+        * Only one rotation schedule per type is supported for now.
+        * Schedules are owned by this object.
+        */
+       unsigned int count;
+       struct lttng_rotation_schedule *schedules[2];
+};
+
+/*
+ * Internal objects between lttng-ctl and the session daemon, the values
+ * are then copied to the user's lttng_rotation_handle object.
+ */
+
+/* For the LTTNG_ROTATE_SESSION command. */
+struct lttng_rotate_session_return {
+       uint64_t rotation_id;
+} LTTNG_PACKED;
+
+/* For the LTTNG_ROTATION_GET_INFO command. */
+struct lttng_rotation_get_info_return {
+       /* Represents values defined in enum lttng_rotation_state. */
+       int32_t status;
+       /*
+        * Represents values defined in enum lttng_trace_archive_location_type.
+        */
+       int8_t location_type;
+       union {
+               struct {
+                       char absolute_path[LTTNG_PATH_MAX];
+               } LTTNG_PACKED local;
+               struct {
+                       char host[LTTNG_HOST_NAME_MAX];
+                       /*
+                        * Represents values defined in
+                        * enum lttng_trace_archive_location_relay_protocol_type.
+                        */
+                       int8_t protocol;
+                       struct {
+                               uint16_t control;
+                               uint16_t data;
+                       } LTTNG_PACKED ports;
+                       char relative_path[LTTNG_PATH_MAX];
+               } LTTNG_PACKED relay;
+       } location;
+} LTTNG_PACKED;
+
+/* For the LTTNG_SESSION_LIST_SCHEDULES command. */
+struct lttng_session_list_schedules_return {
+       struct {
+               uint8_t set;
+               uint64_t value;
+       } LTTNG_PACKED periodic;
+       struct {
+               uint8_t set;
+               uint64_t value;
+       } LTTNG_PACKED size;
+} LTTNG_PACKED;
+
+#endif /* LTTNG_ROTATE_INTERNAL_ABI_H */
diff --git a/include/lttng/save-internal.h b/include/lttng/save-internal.h
deleted file mode 100644 (file)
index 1af3f87..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_SAVE_INTERNAL_ABI_H
-#define LTTNG_SAVE_INTERNAL_ABI_H
-
-#include <limits.h>
-#include <stdint.h>
-
-#include <lttng/constant.h>
-#include <common/macros.h>
-
-/*
- * Object used by the save_session API. This is opaque to the public library.
- */
-struct lttng_save_session_attr {
-       /* Name of the session to save, empty string means all. */
-       char session_name[LTTNG_NAME_MAX];
-       /* Destination of the session configuration. See lttng(1) for URL format. */
-       char configuration_url[PATH_MAX];
-       /* Overwrite the session configuration file if it exists. */
-       uint8_t overwrite;
-       /* Omit the sessions' name(s). */
-       uint8_t omit_name;
-       /* Omit the sessions' output(s). */
-       uint8_t omit_output;
-} LTTNG_PACKED;
-
-#endif /* LTTNG_SAVE_INTERNAL_ABI_H */
diff --git a/include/lttng/save-internal.hpp b/include/lttng/save-internal.hpp
new file mode 100644 (file)
index 0000000..6b2bb94
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_SAVE_INTERNAL_ABI_H
+#define LTTNG_SAVE_INTERNAL_ABI_H
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <lttng/constant.h>
+#include <common/macros.hpp>
+
+/*
+ * Object used by the save_session API. This is opaque to the public library.
+ */
+struct lttng_save_session_attr {
+       /* Name of the session to save, empty string means all. */
+       char session_name[LTTNG_NAME_MAX];
+       /* Destination of the session configuration. See lttng(1) for URL format. */
+       char configuration_url[PATH_MAX];
+       /* Overwrite the session configuration file if it exists. */
+       uint8_t overwrite;
+       /* Omit the sessions' name(s). */
+       uint8_t omit_name;
+       /* Omit the sessions' output(s). */
+       uint8_t omit_output;
+} LTTNG_PACKED;
+
+#endif /* LTTNG_SAVE_INTERNAL_ABI_H */
diff --git a/include/lttng/session-descriptor-internal.h b/include/lttng/session-descriptor-internal.h
deleted file mode 100644 (file)
index f438d48..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_SESSION_DESCRIPTOR_INTERNAL_H
-#define LTTNG_SESSION_DESCRIPTOR_INTERNAL_H
-
-#include <lttng/session-descriptor.h>
-#include <lttng/lttng-error.h>
-#include <common/uri.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <stdbool.h>
-
-/* Note that these enums are used as part of the lttnctl protocol. */
-enum lttng_session_descriptor_type {
-       LTTNG_SESSION_DESCRIPTOR_TYPE_UNKNOWN = -1,
-       /*
-        * The output type determines whether this is a no-output, local,
-        * or networked tracing session.
-        */
-       LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR = 1,
-       LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT = 2,
-       LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE = 3,
-};
-
-enum lttng_session_descriptor_output_type {
-       LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE = 0,
-       LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL = 1,
-       LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK = 2,
-};
-
-ssize_t lttng_session_descriptor_create_from_buffer(
-               const struct lttng_buffer_view *view,
-               struct lttng_session_descriptor **descriptor);
-
-int lttng_session_descriptor_serialize(
-               const struct lttng_session_descriptor *descriptor,
-               struct lttng_dynamic_buffer *buffer);
-
-enum lttng_session_descriptor_type
-lttng_session_descriptor_get_type(
-               const struct lttng_session_descriptor *descriptor);
-
-enum lttng_session_descriptor_output_type
-lttng_session_descriptor_get_output_type(
-               const struct lttng_session_descriptor *descriptor);
-
-void lttng_session_descriptor_get_local_output_uri(
-               const struct lttng_session_descriptor *descriptor,
-               struct lttng_uri *local_uri);
-
-void lttng_session_descriptor_get_network_output_uris(
-               const struct lttng_session_descriptor *descriptor,
-               struct lttng_uri *control,
-               struct lttng_uri *data);
-
-unsigned long long
-lttng_session_descriptor_live_get_timer_interval(
-               const struct lttng_session_descriptor *descriptor);
-
-int lttng_session_descriptor_set_session_name(
-               struct lttng_session_descriptor *descriptor,
-               const char *name);
-
-bool lttng_session_descriptor_is_output_destination_initialized(
-               const struct lttng_session_descriptor *descriptor);
-
-bool lttng_session_descriptor_has_output_directory(
-               const struct lttng_session_descriptor *descriptor);
-
-enum lttng_error_code lttng_session_descriptor_set_default_output(
-               struct lttng_session_descriptor *descriptor,
-               time_t *session_creation_time,
-               const char *absolute_home_path);
-
-int lttng_session_descriptor_assign(
-               struct lttng_session_descriptor *dst_descriptor,
-               const struct lttng_session_descriptor *src_descriptor);
-
-#endif /* LTTNG_SESSION_DESCRIPTOR_INTERNAL_H */
diff --git a/include/lttng/session-descriptor-internal.hpp b/include/lttng/session-descriptor-internal.hpp
new file mode 100644 (file)
index 0000000..c132f56
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_SESSION_DESCRIPTOR_INTERNAL_H
+#define LTTNG_SESSION_DESCRIPTOR_INTERNAL_H
+
+#include <lttng/session-descriptor.h>
+#include <lttng/lttng-error.h>
+#include <common/uri.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/buffer-view.hpp>
+#include <stdbool.h>
+
+/* Note that these enums are used as part of the lttnctl protocol. */
+enum lttng_session_descriptor_type {
+       LTTNG_SESSION_DESCRIPTOR_TYPE_UNKNOWN = -1,
+       /*
+        * The output type determines whether this is a no-output, local,
+        * or networked tracing session.
+        */
+       LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR = 1,
+       LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT = 2,
+       LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE = 3,
+};
+
+enum lttng_session_descriptor_output_type {
+       LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE = 0,
+       LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL = 1,
+       LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK = 2,
+};
+
+ssize_t lttng_session_descriptor_create_from_buffer(
+               const struct lttng_buffer_view *view,
+               struct lttng_session_descriptor **descriptor);
+
+int lttng_session_descriptor_serialize(
+               const struct lttng_session_descriptor *descriptor,
+               struct lttng_dynamic_buffer *buffer);
+
+enum lttng_session_descriptor_type
+lttng_session_descriptor_get_type(
+               const struct lttng_session_descriptor *descriptor);
+
+enum lttng_session_descriptor_output_type
+lttng_session_descriptor_get_output_type(
+               const struct lttng_session_descriptor *descriptor);
+
+void lttng_session_descriptor_get_local_output_uri(
+               const struct lttng_session_descriptor *descriptor,
+               struct lttng_uri *local_uri);
+
+void lttng_session_descriptor_get_network_output_uris(
+               const struct lttng_session_descriptor *descriptor,
+               struct lttng_uri *control,
+               struct lttng_uri *data);
+
+unsigned long long
+lttng_session_descriptor_live_get_timer_interval(
+               const struct lttng_session_descriptor *descriptor);
+
+int lttng_session_descriptor_set_session_name(
+               struct lttng_session_descriptor *descriptor,
+               const char *name);
+
+bool lttng_session_descriptor_is_output_destination_initialized(
+               const struct lttng_session_descriptor *descriptor);
+
+bool lttng_session_descriptor_has_output_directory(
+               const struct lttng_session_descriptor *descriptor);
+
+enum lttng_error_code lttng_session_descriptor_set_default_output(
+               struct lttng_session_descriptor *descriptor,
+               time_t *session_creation_time,
+               const char *absolute_home_path);
+
+int lttng_session_descriptor_assign(
+               struct lttng_session_descriptor *dst_descriptor,
+               const struct lttng_session_descriptor *src_descriptor);
+
+#endif /* LTTNG_SESSION_DESCRIPTOR_INTERNAL_H */
diff --git a/include/lttng/session-internal.h b/include/lttng/session-internal.h
deleted file mode 100644 (file)
index 305c3f5..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_SESSION_INTERNAL_H
-#define LTTNG_SESSION_INTERNAL_H
-
-#include <lttng/constant.h>
-#include <common/macros.h>
-
-struct lttng_session_extended {
-       struct {
-               uint64_t value;
-               uint8_t is_set;
-       } LTTNG_PACKED creation_time;
-} LTTNG_PACKED;
-
-#endif /* LTTNG_SESSION_INTERNAL_H */
diff --git a/include/lttng/session-internal.hpp b/include/lttng/session-internal.hpp
new file mode 100644 (file)
index 0000000..7f73b96
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_SESSION_INTERNAL_H
+#define LTTNG_SESSION_INTERNAL_H
+
+#include <lttng/constant.h>
+#include <common/macros.hpp>
+
+struct lttng_session_extended {
+       struct {
+               uint64_t value;
+               uint8_t is_set;
+       } LTTNG_PACKED creation_time;
+} LTTNG_PACKED;
+
+#endif /* LTTNG_SESSION_INTERNAL_H */
diff --git a/include/lttng/snapshot-internal.h b/include/lttng/snapshot-internal.h
deleted file mode 100644 (file)
index 78c7413..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_SNAPSHOT_INTERNAL_ABI_H
-#define LTTNG_SNAPSHOT_INTERNAL_ABI_H
-
-#include <limits.h>
-#include <stdint.h>
-#include <lttng/constant.h>
-#include <common/macros.h>
-
-/*
- * Object used for the snapshot API. This is opaque to the public library.
- */
-struct lttng_snapshot_output {
-       /*
-        * ID of the snapshot output. This is only used when they are listed. It is
-        * assigned by the session daemon so when adding an output, this value will
-        * not be used.
-        */
-       uint32_t id;
-       /*
-        * Maximum size in bytes of the snapshot meaning the total size of all
-        * stream combined. A value of 0 is unlimited.
-        */
-       uint64_t max_size;
-       /* Name of the output so it can be recognized easily when listing them. */
-       char name[LTTNG_NAME_MAX];
-       /* Destination of the output. See lttng(1) for URL format. */
-       char ctrl_url[PATH_MAX];
-       /* Destination of the output. See lttng(1) for URL format. */
-       char data_url[PATH_MAX];
-} LTTNG_PACKED;
-
-/*
- * Snapshot output list object opaque to the user.
- */
-struct lttng_snapshot_output_list {
-       /*
-        * The position in the output array. This is changed by a get_next call.
-        */
-       int index;
-
-       /*
-        * Number of element in the array.
-        */
-       size_t count;
-
-       /*
-        * Contains snapshot output object.
-        */
-       struct lttng_snapshot_output *array;
-};
-
-#endif /* LTTNG_SNAPSHOT_INTERNAL_ABI_H */
diff --git a/include/lttng/snapshot-internal.hpp b/include/lttng/snapshot-internal.hpp
new file mode 100644 (file)
index 0000000..c60a196
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_SNAPSHOT_INTERNAL_ABI_H
+#define LTTNG_SNAPSHOT_INTERNAL_ABI_H
+
+#include <limits.h>
+#include <stdint.h>
+#include <lttng/constant.h>
+#include <common/macros.hpp>
+
+/*
+ * Object used for the snapshot API. This is opaque to the public library.
+ */
+struct lttng_snapshot_output {
+       /*
+        * ID of the snapshot output. This is only used when they are listed. It is
+        * assigned by the session daemon so when adding an output, this value will
+        * not be used.
+        */
+       uint32_t id;
+       /*
+        * Maximum size in bytes of the snapshot meaning the total size of all
+        * stream combined. A value of 0 is unlimited.
+        */
+       uint64_t max_size;
+       /* Name of the output so it can be recognized easily when listing them. */
+       char name[LTTNG_NAME_MAX];
+       /* Destination of the output. See lttng(1) for URL format. */
+       char ctrl_url[PATH_MAX];
+       /* Destination of the output. See lttng(1) for URL format. */
+       char data_url[PATH_MAX];
+} LTTNG_PACKED;
+
+/*
+ * Snapshot output list object opaque to the user.
+ */
+struct lttng_snapshot_output_list {
+       /*
+        * The position in the output array. This is changed by a get_next call.
+        */
+       int index;
+
+       /*
+        * Number of element in the array.
+        */
+       size_t count;
+
+       /*
+        * Contains snapshot output object.
+        */
+       struct lttng_snapshot_output *array;
+};
+
+#endif /* LTTNG_SNAPSHOT_INTERNAL_ABI_H */
diff --git a/include/lttng/trigger/trigger-internal.h b/include/lttng/trigger/trigger-internal.h
deleted file mode 100644 (file)
index dab46ae..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_TRIGGER_INTERNAL_H
-#define LTTNG_TRIGGER_INTERNAL_H
-
-#include <common/credentials.h>
-#include <common/dynamic-array.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <lttng/lttng.h>
-#include <pthread.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <urcu/ref.h>
-
-struct lttng_payload;
-struct lttng_payload_view;
-struct mi_writer;
-struct mi_lttng_error_query_callbacks;
-
-struct lttng_trigger {
-       /* Reference counting is only exposed to internal users. */
-       struct urcu_ref ref;
-
-       struct lttng_condition *condition;
-       struct lttng_action *action;
-       char *name;
-       /* For now only the uid portion of the credentials is used. */
-       struct lttng_credentials creds;
-       /*
-        * Internal use only.
-        * The unique token passed to the tracer to identify an event-rule
-        * notification.
-        */
-       LTTNG_OPTIONAL(uint64_t) tracer_token;
-
-       /*
-        * Is the trigger registered?
-        *
-        * This is necessary since a reference holder might be interested in the
-        * overall state of the trigger from the point of view of its owner.
-        *
-        * The main user is the action executor since we want to prevent the
-        * execution of actions related to a trigger that is unregistered.
-        *
-        * Not considered for `is_equal`.
-        */
-       bool registered;
-
-       /*
-        * A "hidden" trigger is a trigger that is not externally listed.
-        * It is used to hide triggers that are used internally by the session
-        * daemon so that they can't be listed nor unregistered by external
-        * clients.
-        *
-        * This is a property that can only be set internally by the session
-        * daemon. As such, it is not serialized nor set by a
-        * "create_from_buffer" constructor.
-        *
-        * The hidden property is preserved by copies.
-        *
-        * Note that notifications originating from an "hidden" trigger will not
-        * be sent to clients that are not within the session daemon's process.
-        */
-       bool is_hidden;
-
-       /*
-        * The lock is used to protect against concurrent trigger execution and
-        * trigger removal.
-        */
-       pthread_mutex_t lock;
-};
-
-struct lttng_triggers {
-       struct lttng_dynamic_pointer_array array;
-};
-
-struct lttng_trigger_comm {
-       /*
-        * Credentials, only the uid portion is used for now.
-        * Used as an override when desired by the root user.
-        */
-       uint64_t uid;
-       /*
-        * Length of the variable length payload (name, condition, and
-        * an action).
-        */
-       uint32_t length;
-       /* Includes '\0' terminator. */
-       uint32_t name_length;
-       /* A null-terminated name, a condition, and an action follow. */
-       char payload[];
-} LTTNG_PACKED;
-
-struct lttng_triggers_comm {
-       uint32_t count;
-       uint32_t length;
-       /* Count * lttng_trigger_comm structure */
-       char payload[];
-};
-
-ssize_t lttng_trigger_create_from_payload(struct lttng_payload_view *view,
-               struct lttng_trigger **trigger);
-
-int lttng_trigger_serialize(const struct lttng_trigger *trigger,
-               struct lttng_payload *payload);
-
-bool lttng_trigger_validate(const struct lttng_trigger *trigger);
-
-int lttng_trigger_assign_name(
-               struct lttng_trigger *dst, const struct lttng_trigger *src);
-
-void lttng_trigger_set_tracer_token(
-               struct lttng_trigger *trigger, uint64_t token);
-
-uint64_t lttng_trigger_get_tracer_token(const struct lttng_trigger *trigger);
-
-int lttng_trigger_generate_name(struct lttng_trigger *trigger,
-               uint64_t unique_id);
-
-bool lttng_trigger_is_equal(
-               const struct lttng_trigger *a, const struct lttng_trigger *b);
-
-bool lttng_trigger_is_hidden(const struct lttng_trigger *trigger);
-
-void lttng_trigger_set_hidden(struct lttng_trigger *trigger);
-
-void lttng_trigger_get(struct lttng_trigger *trigger);
-
-void lttng_trigger_put(struct lttng_trigger *trigger);
-
-/*
- * Serialize a trigger to a mi_writer.
- * Return LTTNG_OK in success, other enum lttng_error_code on error.
- */
-enum lttng_error_code lttng_trigger_mi_serialize(const struct lttng_trigger *trigger,
-               struct mi_writer *writer,
-               const struct mi_lttng_error_query_callbacks
-                               *error_query_callbacks);
-
-/*
- * Allocate a new set of triggers.
- * The returned object must be freed via lttng_triggers_destroy.
- */
-struct lttng_triggers *lttng_triggers_create(void);
-
-/*
- * Return the a pointer to a mutable element at index "index" of an
- * lttng_triggers set.
- *
- * This differs from the public `lttng_triggers_get_at_index` in that
- * the returned pointer to a mutable trigger.
- *
- * The ownership of the trigger set element is NOT transfered.
- * The returned object can NOT be freed via lttng_trigger_destroy.
- */
-struct lttng_trigger *lttng_triggers_borrow_mutable_at_index(
-               const struct lttng_triggers *triggers, unsigned int index);
-
-/*
- * Add a trigger to the triggers set.
- *
- * A reference to the added trigger is acquired on behalf of the trigger set
- * on success.
- */
-int lttng_triggers_add(
-               struct lttng_triggers *triggers, struct lttng_trigger *trigger);
-
-/*
- * Remove all triggers marked as hidden from the provided trigger set.
- */
-int lttng_triggers_remove_hidden_triggers(struct lttng_triggers *triggers);
-
-/*
- * Serialize a trigger set to an lttng_payload object.
- * Return LTTNG_OK on success, negative lttng error code on error.
- */
-int lttng_triggers_serialize(const struct lttng_triggers *triggers,
-               struct lttng_payload *payload);
-
-ssize_t lttng_triggers_create_from_payload(struct lttng_payload_view *view,
-               struct lttng_triggers **triggers);
-
-/*
- * Serialize a trigger set to a mi_writer.
- * Return LTTNG_OK in success, other enum lttng_error_code on error.
- */
-enum lttng_error_code lttng_triggers_mi_serialize(const struct lttng_triggers *triggers,
-               struct mi_writer *writer,
-               const struct mi_lttng_error_query_callbacks
-                               *error_query_callbacks);
-
-const struct lttng_credentials *lttng_trigger_get_credentials(
-               const struct lttng_trigger *trigger);
-
-void lttng_trigger_set_credentials(struct lttng_trigger *trigger,
-               const struct lttng_credentials *creds);
-
-/*
- * Return the type of any underlying domain restriction. If no particular
- * requirement is present, returns LTTNG_DOMAIN_NONE.
- */
-enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction(
-               const struct lttng_trigger *trigger);
-
-/*
- * Generate any bytecode related to the trigger.
- * On success LTTNG_OK. On error, returns lttng_error code.
- */
-enum lttng_error_code lttng_trigger_generate_bytecode(
-               struct lttng_trigger *trigger,
-               const struct lttng_credentials *creds);
-
-/*
- * Note that the trigger object is not locked by "copy" as it is const and
- * used with a number of 'const' triggers. If the trigger could be shared at
- * the moment of the copy, it is the caller's responsability to lock it for
- * the duration of the copy.
- */
-struct lttng_trigger *lttng_trigger_copy(const struct lttng_trigger *trigger);
-
-/*
- * A given trigger needs a tracer notifier if
- *  it has an event-rule condition,
- *  AND
- *  it has one or more sessiond-execution action.
- */
-bool lttng_trigger_needs_tracer_notifier(const struct lttng_trigger *trigger);
-
-void lttng_trigger_set_as_registered(struct lttng_trigger *trigger);
-
-void lttng_trigger_set_as_unregistered(struct lttng_trigger *trigger);
-
-/*
- * The trigger must be locked before calling lttng_trigger_is_registered.
- *
- * The lock is necessary since a trigger can be unregistered at any time.
- *
- * Manipulations requiring that the trigger be registered must always acquire
- * the trigger lock for the duration of the manipulation using
- * `lttng_trigger_lock` and `lttng_trigger_unlock`.
- */
-bool lttng_trigger_is_registered(struct lttng_trigger *trigger);
-
-void lttng_trigger_lock(struct lttng_trigger *trigger);
-
-void lttng_trigger_unlock(struct lttng_trigger *trigger);
-
-enum lttng_trigger_status lttng_trigger_add_error_results(
-               const struct lttng_trigger *trigger,
-               struct lttng_error_query_results *results);
-
-enum lttng_trigger_status lttng_trigger_condition_add_error_results(
-               const struct lttng_trigger *trigger,
-               struct lttng_error_query_results *results);
-
-enum lttng_trigger_status lttng_trigger_add_action_error_query_results(
-               struct lttng_trigger *trigger,
-               struct lttng_error_query_results *results);
-
-/*
- * Set the trigger name.
- *
- * A name is optional.
- * A name will be assigned on trigger registration if no name is set.
- *
- * The name is copied.
- *
- * Return LTTNG_TRIGGER_STATUS_OK on success, LTTNG_TRIGGER_STATUS_INVALID
- * if invalid parameters are passed.
- */
-enum lttng_trigger_status lttng_trigger_set_name(
-               struct lttng_trigger *trigger, const char *name);
-
-#endif /* LTTNG_TRIGGER_INTERNAL_H */
diff --git a/include/lttng/trigger/trigger-internal.hpp b/include/lttng/trigger/trigger-internal.hpp
new file mode 100644 (file)
index 0000000..206e7df
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_TRIGGER_INTERNAL_H
+#define LTTNG_TRIGGER_INTERNAL_H
+
+#include <common/credentials.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/lttng.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <urcu/ref.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+struct mi_writer;
+struct mi_lttng_error_query_callbacks;
+
+struct lttng_trigger {
+       /* Reference counting is only exposed to internal users. */
+       struct urcu_ref ref;
+
+       struct lttng_condition *condition;
+       struct lttng_action *action;
+       char *name;
+       /* For now only the uid portion of the credentials is used. */
+       struct lttng_credentials creds;
+       /*
+        * Internal use only.
+        * The unique token passed to the tracer to identify an event-rule
+        * notification.
+        */
+       LTTNG_OPTIONAL(uint64_t) tracer_token;
+
+       /*
+        * Is the trigger registered?
+        *
+        * This is necessary since a reference holder might be interested in the
+        * overall state of the trigger from the point of view of its owner.
+        *
+        * The main user is the action executor since we want to prevent the
+        * execution of actions related to a trigger that is unregistered.
+        *
+        * Not considered for `is_equal`.
+        */
+       bool registered;
+
+       /*
+        * A "hidden" trigger is a trigger that is not externally listed.
+        * It is used to hide triggers that are used internally by the session
+        * daemon so that they can't be listed nor unregistered by external
+        * clients.
+        *
+        * This is a property that can only be set internally by the session
+        * daemon. As such, it is not serialized nor set by a
+        * "create_from_buffer" constructor.
+        *
+        * The hidden property is preserved by copies.
+        *
+        * Note that notifications originating from an "hidden" trigger will not
+        * be sent to clients that are not within the session daemon's process.
+        */
+       bool is_hidden;
+
+       /*
+        * The lock is used to protect against concurrent trigger execution and
+        * trigger removal.
+        */
+       pthread_mutex_t lock;
+};
+
+struct lttng_triggers {
+       struct lttng_dynamic_pointer_array array;
+};
+
+struct lttng_trigger_comm {
+       /*
+        * Credentials, only the uid portion is used for now.
+        * Used as an override when desired by the root user.
+        */
+       uint64_t uid;
+       /*
+        * Length of the variable length payload (name, condition, and
+        * an action).
+        */
+       uint32_t length;
+       /* Includes '\0' terminator. */
+       uint32_t name_length;
+       /* A null-terminated name, a condition, and an action follow. */
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_triggers_comm {
+       uint32_t count;
+       uint32_t length;
+       /* Count * lttng_trigger_comm structure */
+       char payload[];
+};
+
+ssize_t lttng_trigger_create_from_payload(struct lttng_payload_view *view,
+               struct lttng_trigger **trigger);
+
+int lttng_trigger_serialize(const struct lttng_trigger *trigger,
+               struct lttng_payload *payload);
+
+bool lttng_trigger_validate(const struct lttng_trigger *trigger);
+
+int lttng_trigger_assign_name(
+               struct lttng_trigger *dst, const struct lttng_trigger *src);
+
+void lttng_trigger_set_tracer_token(
+               struct lttng_trigger *trigger, uint64_t token);
+
+uint64_t lttng_trigger_get_tracer_token(const struct lttng_trigger *trigger);
+
+int lttng_trigger_generate_name(struct lttng_trigger *trigger,
+               uint64_t unique_id);
+
+bool lttng_trigger_is_equal(
+               const struct lttng_trigger *a, const struct lttng_trigger *b);
+
+bool lttng_trigger_is_hidden(const struct lttng_trigger *trigger);
+
+void lttng_trigger_set_hidden(struct lttng_trigger *trigger);
+
+void lttng_trigger_get(struct lttng_trigger *trigger);
+
+void lttng_trigger_put(struct lttng_trigger *trigger);
+
+/*
+ * Serialize a trigger to a mi_writer.
+ * Return LTTNG_OK in success, other enum lttng_error_code on error.
+ */
+enum lttng_error_code lttng_trigger_mi_serialize(const struct lttng_trigger *trigger,
+               struct mi_writer *writer,
+               const struct mi_lttng_error_query_callbacks
+                               *error_query_callbacks);
+
+/*
+ * Allocate a new set of triggers.
+ * The returned object must be freed via lttng_triggers_destroy.
+ */
+struct lttng_triggers *lttng_triggers_create(void);
+
+/*
+ * Return the a pointer to a mutable element at index "index" of an
+ * lttng_triggers set.
+ *
+ * This differs from the public `lttng_triggers_get_at_index` in that
+ * the returned pointer to a mutable trigger.
+ *
+ * The ownership of the trigger set element is NOT transfered.
+ * The returned object can NOT be freed via lttng_trigger_destroy.
+ */
+struct lttng_trigger *lttng_triggers_borrow_mutable_at_index(
+               const struct lttng_triggers *triggers, unsigned int index);
+
+/*
+ * Add a trigger to the triggers set.
+ *
+ * A reference to the added trigger is acquired on behalf of the trigger set
+ * on success.
+ */
+int lttng_triggers_add(
+               struct lttng_triggers *triggers, struct lttng_trigger *trigger);
+
+/*
+ * Remove all triggers marked as hidden from the provided trigger set.
+ */
+int lttng_triggers_remove_hidden_triggers(struct lttng_triggers *triggers);
+
+/*
+ * Serialize a trigger set to an lttng_payload object.
+ * Return LTTNG_OK on success, negative lttng error code on error.
+ */
+int lttng_triggers_serialize(const struct lttng_triggers *triggers,
+               struct lttng_payload *payload);
+
+ssize_t lttng_triggers_create_from_payload(struct lttng_payload_view *view,
+               struct lttng_triggers **triggers);
+
+/*
+ * Serialize a trigger set to a mi_writer.
+ * Return LTTNG_OK in success, other enum lttng_error_code on error.
+ */
+enum lttng_error_code lttng_triggers_mi_serialize(const struct lttng_triggers *triggers,
+               struct mi_writer *writer,
+               const struct mi_lttng_error_query_callbacks
+                               *error_query_callbacks);
+
+const struct lttng_credentials *lttng_trigger_get_credentials(
+               const struct lttng_trigger *trigger);
+
+void lttng_trigger_set_credentials(struct lttng_trigger *trigger,
+               const struct lttng_credentials *creds);
+
+/*
+ * Return the type of any underlying domain restriction. If no particular
+ * requirement is present, returns LTTNG_DOMAIN_NONE.
+ */
+enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction(
+               const struct lttng_trigger *trigger);
+
+/*
+ * Generate any bytecode related to the trigger.
+ * On success LTTNG_OK. On error, returns lttng_error code.
+ */
+enum lttng_error_code lttng_trigger_generate_bytecode(
+               struct lttng_trigger *trigger,
+               const struct lttng_credentials *creds);
+
+/*
+ * Note that the trigger object is not locked by "copy" as it is const and
+ * used with a number of 'const' triggers. If the trigger could be shared at
+ * the moment of the copy, it is the caller's responsability to lock it for
+ * the duration of the copy.
+ */
+struct lttng_trigger *lttng_trigger_copy(const struct lttng_trigger *trigger);
+
+/*
+ * A given trigger needs a tracer notifier if
+ *  it has an event-rule condition,
+ *  AND
+ *  it has one or more sessiond-execution action.
+ */
+bool lttng_trigger_needs_tracer_notifier(const struct lttng_trigger *trigger);
+
+void lttng_trigger_set_as_registered(struct lttng_trigger *trigger);
+
+void lttng_trigger_set_as_unregistered(struct lttng_trigger *trigger);
+
+/*
+ * The trigger must be locked before calling lttng_trigger_is_registered.
+ *
+ * The lock is necessary since a trigger can be unregistered at any time.
+ *
+ * Manipulations requiring that the trigger be registered must always acquire
+ * the trigger lock for the duration of the manipulation using
+ * `lttng_trigger_lock` and `lttng_trigger_unlock`.
+ */
+bool lttng_trigger_is_registered(struct lttng_trigger *trigger);
+
+void lttng_trigger_lock(struct lttng_trigger *trigger);
+
+void lttng_trigger_unlock(struct lttng_trigger *trigger);
+
+enum lttng_trigger_status lttng_trigger_add_error_results(
+               const struct lttng_trigger *trigger,
+               struct lttng_error_query_results *results);
+
+enum lttng_trigger_status lttng_trigger_condition_add_error_results(
+               const struct lttng_trigger *trigger,
+               struct lttng_error_query_results *results);
+
+enum lttng_trigger_status lttng_trigger_add_action_error_query_results(
+               struct lttng_trigger *trigger,
+               struct lttng_error_query_results *results);
+
+/*
+ * Set the trigger name.
+ *
+ * A name is optional.
+ * A name will be assigned on trigger registration if no name is set.
+ *
+ * The name is copied.
+ *
+ * Return LTTNG_TRIGGER_STATUS_OK on success, LTTNG_TRIGGER_STATUS_INVALID
+ * if invalid parameters are passed.
+ */
+enum lttng_trigger_status lttng_trigger_set_name(
+               struct lttng_trigger *trigger, const char *name);
+
+#endif /* LTTNG_TRIGGER_INTERNAL_H */
diff --git a/include/lttng/userspace-probe-internal.h b/include/lttng/userspace-probe-internal.h
deleted file mode 100644 (file)
index 5e960c1..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright (C) 2018 Francis Deslauriers <francis.deslauriers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_USERSPACE_PROBE_INTERNAL_H
-#define LTTNG_USERSPACE_PROBE_INTERNAL_H
-
-#include <lttng/userspace-probe.h>
-#include <common/macros.h>
-#include <common/fd-handle.h>
-#include <stdbool.h>
-
-struct lttng_payload;
-struct lttng_payload_view;
-struct lttng_dynamic_buffer;
-struct mi_writer;
-
-typedef bool (*userspace_probe_location_equal_cb)(
-               const struct lttng_userspace_probe_location *a,
-               const struct lttng_userspace_probe_location *b);
-typedef unsigned long (*userspace_probe_location_hash_cb)(
-               const struct lttng_userspace_probe_location *location);
-typedef enum lttng_error_code (*userspace_probe_location_mi)(
-               const struct lttng_userspace_probe_location *location,
-               struct mi_writer);
-
-/*
- * No elf-specific comm structure is defined since no elf-specific payload is
- * currently needed.
- */
-struct lttng_userspace_probe_location_lookup_method_comm {
-       /* enum lttng_userspace_probe_location_lookup_method_type */
-       int8_t type;
-       /* type-specific payload */
-       char payload[];
-};
-
-/* Common ancestor of all userspace probe location lookup methods. */
-struct lttng_userspace_probe_location_lookup_method {
-       enum lttng_userspace_probe_location_lookup_method_type type;
-};
-
-struct lttng_userspace_probe_location_lookup_method_elf {
-       struct lttng_userspace_probe_location_lookup_method parent;
-};
-
-struct lttng_userspace_probe_location_lookup_method_sdt {
-       struct lttng_userspace_probe_location_lookup_method parent;
-};
-
-struct lttng_userspace_probe_location_comm {
-       /* enum lttng_userspace_probe_location_type */
-       int8_t type;
-       /*
-        * Payload is composed of, in that order,
-        *   - type-specific payload
-        *   - struct lttng_userspace_probe_location_lookup_method_comm
-        */
-       char payload[];
-};
-
-struct lttng_userspace_probe_location_function_comm {
-       /* Both lengths include the trailing \0. */
-       uint32_t function_name_len;
-       uint32_t binary_path_len;
-       /*
-        * Payload is composed of, in that order,
-        *   - function name (with trailing \0),
-        *   - absolute binary path (with trailing \0)
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-struct lttng_userspace_probe_location_tracepoint_comm {
-       /* The three lengths include the trailing \0. */
-       uint32_t probe_name_len;
-       uint32_t provider_name_len;
-       uint32_t binary_path_len;
-       /*
-        * Payload is composed of, in that order,
-        *   - probe name (with trailing \0),
-        *   - provider name (with trailing \0),
-        *   - absolute binary path (with trailing \0)
-        */
-       char payload[];
-} LTTNG_PACKED;
-
-/* Common ancestor of all userspace probe locations. */
-struct lttng_userspace_probe_location {
-       enum lttng_userspace_probe_location_type type;
-       struct lttng_userspace_probe_location_lookup_method *lookup_method;
-       userspace_probe_location_equal_cb equal;
-       userspace_probe_location_hash_cb hash;
-       userspace_probe_location_hash_cb mi;
-};
-
-struct lttng_userspace_probe_location_function {
-       struct lttng_userspace_probe_location parent;
-       char *function_name;
-       char *binary_path;
-       /*
-        * binary_fd is a file descriptor to the executable file. It's open
-        * early on to keep the backing inode valid over the course of the
-        * intrumentation and use. It prevents deletion and reuse races.
-        */
-       struct fd_handle *binary_fd_handle;
-       enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type;
-};
-
-struct lttng_userspace_probe_location_tracepoint {
-       struct lttng_userspace_probe_location parent;
-       char *probe_name;
-       char *provider_name;
-       char *binary_path;
-       /*
-        * binary_fd is a file descriptor to the executable file. It's open
-        * early on to keep the backing inode valid over the course of the
-        * intrumentation and use. It prevents deletion and reuse races.
-        */
-       struct fd_handle *binary_fd_handle;
-};
-
-int lttng_userspace_probe_location_serialize(
-               const struct lttng_userspace_probe_location *location,
-               struct lttng_payload *payload);
-
-int lttng_userspace_probe_location_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_userspace_probe_location **probe_location);
-
-/*
- * Returns a version of the location that is serialized to a contiguous region
- * of memory. Pass NULL to buffer to only get the storage requirement of the
- * flattened userspace probe location.
- */
-int lttng_userspace_probe_location_flatten(
-               const struct lttng_userspace_probe_location *location,
-               struct lttng_dynamic_buffer *buffer);
-
-struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
-               const struct lttng_userspace_probe_location *location);
-
-bool lttng_userspace_probe_location_lookup_method_is_equal(
-               const struct lttng_userspace_probe_location_lookup_method *a,
-               const struct lttng_userspace_probe_location_lookup_method *b);
-
-bool lttng_userspace_probe_location_is_equal(
-               const struct lttng_userspace_probe_location *a,
-               const struct lttng_userspace_probe_location *b);
-
-unsigned long lttng_userspace_probe_location_hash(
-               const struct lttng_userspace_probe_location *location);
-
-enum lttng_error_code lttng_userspace_probe_location_mi_serialize(
-               const struct lttng_userspace_probe_location *location,
-               struct mi_writer *writer);
-
-#endif /* LTTNG_USERSPACE_PROBE_INTERNAL_H */
diff --git a/include/lttng/userspace-probe-internal.hpp b/include/lttng/userspace-probe-internal.hpp
new file mode 100644 (file)
index 0000000..392242d
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2018 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_USERSPACE_PROBE_INTERNAL_H
+#define LTTNG_USERSPACE_PROBE_INTERNAL_H
+
+#include <lttng/userspace-probe.h>
+#include <common/macros.hpp>
+#include <common/fd-handle.hpp>
+#include <stdbool.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+struct lttng_dynamic_buffer;
+struct mi_writer;
+
+typedef bool (*userspace_probe_location_equal_cb)(
+               const struct lttng_userspace_probe_location *a,
+               const struct lttng_userspace_probe_location *b);
+typedef unsigned long (*userspace_probe_location_hash_cb)(
+               const struct lttng_userspace_probe_location *location);
+typedef enum lttng_error_code (*userspace_probe_location_mi)(
+               const struct lttng_userspace_probe_location *location,
+               struct mi_writer);
+
+/*
+ * No elf-specific comm structure is defined since no elf-specific payload is
+ * currently needed.
+ */
+struct lttng_userspace_probe_location_lookup_method_comm {
+       /* enum lttng_userspace_probe_location_lookup_method_type */
+       int8_t type;
+       /* type-specific payload */
+       char payload[];
+};
+
+/* Common ancestor of all userspace probe location lookup methods. */
+struct lttng_userspace_probe_location_lookup_method {
+       enum lttng_userspace_probe_location_lookup_method_type type;
+};
+
+struct lttng_userspace_probe_location_lookup_method_elf {
+       struct lttng_userspace_probe_location_lookup_method parent;
+};
+
+struct lttng_userspace_probe_location_lookup_method_sdt {
+       struct lttng_userspace_probe_location_lookup_method parent;
+};
+
+struct lttng_userspace_probe_location_comm {
+       /* enum lttng_userspace_probe_location_type */
+       int8_t type;
+       /*
+        * Payload is composed of, in that order,
+        *   - type-specific payload
+        *   - struct lttng_userspace_probe_location_lookup_method_comm
+        */
+       char payload[];
+};
+
+struct lttng_userspace_probe_location_function_comm {
+       /* Both lengths include the trailing \0. */
+       uint32_t function_name_len;
+       uint32_t binary_path_len;
+       /*
+        * Payload is composed of, in that order,
+        *   - function name (with trailing \0),
+        *   - absolute binary path (with trailing \0)
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_userspace_probe_location_tracepoint_comm {
+       /* The three lengths include the trailing \0. */
+       uint32_t probe_name_len;
+       uint32_t provider_name_len;
+       uint32_t binary_path_len;
+       /*
+        * Payload is composed of, in that order,
+        *   - probe name (with trailing \0),
+        *   - provider name (with trailing \0),
+        *   - absolute binary path (with trailing \0)
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+/* Common ancestor of all userspace probe locations. */
+struct lttng_userspace_probe_location {
+       enum lttng_userspace_probe_location_type type;
+       struct lttng_userspace_probe_location_lookup_method *lookup_method;
+       userspace_probe_location_equal_cb equal;
+       userspace_probe_location_hash_cb hash;
+       userspace_probe_location_hash_cb mi;
+};
+
+struct lttng_userspace_probe_location_function {
+       struct lttng_userspace_probe_location parent;
+       char *function_name;
+       char *binary_path;
+       /*
+        * binary_fd is a file descriptor to the executable file. It's open
+        * early on to keep the backing inode valid over the course of the
+        * intrumentation and use. It prevents deletion and reuse races.
+        */
+       struct fd_handle *binary_fd_handle;
+       enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type;
+};
+
+struct lttng_userspace_probe_location_tracepoint {
+       struct lttng_userspace_probe_location parent;
+       char *probe_name;
+       char *provider_name;
+       char *binary_path;
+       /*
+        * binary_fd is a file descriptor to the executable file. It's open
+        * early on to keep the backing inode valid over the course of the
+        * intrumentation and use. It prevents deletion and reuse races.
+        */
+       struct fd_handle *binary_fd_handle;
+};
+
+int lttng_userspace_probe_location_serialize(
+               const struct lttng_userspace_probe_location *location,
+               struct lttng_payload *payload);
+
+int lttng_userspace_probe_location_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_userspace_probe_location **probe_location);
+
+/*
+ * Returns a version of the location that is serialized to a contiguous region
+ * of memory. Pass NULL to buffer to only get the storage requirement of the
+ * flattened userspace probe location.
+ */
+int lttng_userspace_probe_location_flatten(
+               const struct lttng_userspace_probe_location *location,
+               struct lttng_dynamic_buffer *buffer);
+
+struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
+               const struct lttng_userspace_probe_location *location);
+
+bool lttng_userspace_probe_location_lookup_method_is_equal(
+               const struct lttng_userspace_probe_location_lookup_method *a,
+               const struct lttng_userspace_probe_location_lookup_method *b);
+
+bool lttng_userspace_probe_location_is_equal(
+               const struct lttng_userspace_probe_location *a,
+               const struct lttng_userspace_probe_location *b);
+
+unsigned long lttng_userspace_probe_location_hash(
+               const struct lttng_userspace_probe_location *location);
+
+enum lttng_error_code lttng_userspace_probe_location_mi_serialize(
+               const struct lttng_userspace_probe_location *location,
+               struct mi_writer *writer);
+
+#endif /* LTTNG_USERSPACE_PROBE_INTERNAL_H */
diff --git a/include/version.h b/include/version.h
deleted file mode 100644 (file)
index 9bd5e0c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Raphaël Beamonte <raphael.beamonte@gmail.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef VERSION_H
-#define VERSION_H
-
-#include <version.i>
-
-#endif /* VERSION_H */
diff --git a/include/version.hpp b/include/version.hpp
new file mode 100644 (file)
index 0000000..9bd5e0c
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2013-2014 Raphaël Beamonte <raphael.beamonte@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef VERSION_H
+#define VERSION_H
+
+#include <version.i>
+
+#endif /* VERSION_H */
index 37fc6d5244ca85ad30dfeebdfa464f826aee06af..570cfcaa0d43803168207af67e8270329f7bb7b3 100644 (file)
@@ -4,17 +4,17 @@ lttnglibexec_PROGRAMS = lttng-consumerd
 
 lttng_consumerd_SOURCES = \
        lttng-consumerd.cpp \
-       lttng-consumerd.h \
+       lttng-consumerd.hpp \
        health-consumerd.cpp \
-       health-consumerd.h
+       health-consumerd.hpp
 
 lttng_consumerd_LDADD = \
-          $(top_builddir)/src/common/consumer/libconsumer.la \
-          $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \
+          $(top_builddir)/src/common/libconsumer.la \
+          $(top_builddir)/src/common/libsessiond-comm.la \
           $(top_builddir)/src/common/libcommon.la \
-          $(top_builddir)/src/common/index/libindex.la \
-          $(top_builddir)/src/common/health/libhealth.la \
-          $(top_builddir)/src/common/testpoint/libtestpoint.la
+          $(top_builddir)/src/common/libindex.la \
+          $(top_builddir)/src/common/libhealth.la \
+          $(top_builddir)/src/common/libtestpoint.la
 
 lttng_consumerd_LDFLAGS = -rdynamic
 
index ec30af5ddc1f1fd5517365bd94622da89278c17c..a2ffaf432ec6ad81adeb48cd8bfe8d09ae66cc9e 100644 (file)
 #include <ulimit.h>
 #include <inttypes.h>
 
-#include <common/defaults.h>
-#include <common/common.h>
-#include <common/consumer/consumer.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/compat/poll.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/utils.h>
-
-#include "lttng-consumerd.h"
-#include "health-consumerd.h"
+#include <common/defaults.hpp>
+#include <common/common.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/compat/poll.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/utils.hpp>
+
+#include "lttng-consumerd.hpp"
+#include "health-consumerd.hpp"
 
 /* Global health check unix path */
 static char health_unix_sock_path[PATH_MAX];
diff --git a/src/bin/lttng-consumerd/health-consumerd.h b/src/bin/lttng-consumerd/health-consumerd.h
deleted file mode 100644 (file)
index 42ec9ea..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef HEALTH_CONSUMERD_H
-#define HEALTH_CONSUMERD_H
-
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- */
-
-#include <lttng/health-internal.h>
-
-enum health_type_consumerd {
-       HEALTH_CONSUMERD_TYPE_CHANNEL           = 0,
-       HEALTH_CONSUMERD_TYPE_METADATA          = 1,
-       HEALTH_CONSUMERD_TYPE_DATA              = 2,
-       HEALTH_CONSUMERD_TYPE_SESSIOND          = 3,
-       HEALTH_CONSUMERD_TYPE_METADATA_TIMER    = 4,
-
-       NR_HEALTH_CONSUMERD_TYPES,
-};
-
-/* Consumerd health monitoring */
-extern struct health_app *health_consumerd;
-
-void *thread_manage_health(void *data);
-
-extern int health_quit_pipe[2];
-
-#endif /* HEALTH_CONSUMERD_H */
diff --git a/src/bin/lttng-consumerd/health-consumerd.hpp b/src/bin/lttng-consumerd/health-consumerd.hpp
new file mode 100644 (file)
index 0000000..1723e66
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef HEALTH_CONSUMERD_H
+#define HEALTH_CONSUMERD_H
+
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ */
+
+#include <lttng/health-internal.hpp>
+
+enum health_type_consumerd {
+       HEALTH_CONSUMERD_TYPE_CHANNEL           = 0,
+       HEALTH_CONSUMERD_TYPE_METADATA          = 1,
+       HEALTH_CONSUMERD_TYPE_DATA              = 2,
+       HEALTH_CONSUMERD_TYPE_SESSIOND          = 3,
+       HEALTH_CONSUMERD_TYPE_METADATA_TIMER    = 4,
+
+       NR_HEALTH_CONSUMERD_TYPES,
+};
+
+/* Consumerd health monitoring */
+extern struct health_app *health_consumerd;
+
+void *thread_manage_health(void *data);
+
+extern int health_quit_pipe[2];
+
+#endif /* HEALTH_CONSUMERD_H */
index dbcda885eede04a0a92a3189a975247de80ce4f2..ffe53041287dd9234a7cdadbedf861d7182c433d 100644 (file)
 #include <urcu/compiler.h>
 #include <ulimit.h>
 
-#include <common/defaults.h>
-#include <common/common.h>
-#include <common/consumer/consumer.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/compat/poll.h>
-#include <common/compat/getenv.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/utils.h>
-
-#include "lttng-consumerd.h"
-#include "health-consumerd.h"
+#include <common/defaults.hpp>
+#include <common/common.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/compat/poll.hpp>
+#include <common/compat/getenv.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/utils.hpp>
+
+#include "lttng-consumerd.hpp"
+#include "health-consumerd.hpp"
 
 /* threads (channel handling, poll, metadata, sessiond) */
 
diff --git a/src/bin/lttng-consumerd/lttng-consumerd.h b/src/bin/lttng-consumerd/lttng-consumerd.h
deleted file mode 100644 (file)
index 354f7f3..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_CONSUMERD_H
-#define _LTTNG_CONSUMERD_H
-
-
-#define NR_LTTNG_CONSUMER_READY                1
-extern int lttng_consumer_ready;
-
-extern const char *tracing_group_name;
-
-/*
- * This function is dlsym-ed from a test, so needs to be exported.  Making it
- * have a C linkage name makes it easier, as it avoids having to look up a
- * mangled name.
- */
-extern "C" LTTNG_EXPORT
-enum lttng_consumer_type lttng_consumer_get_type();
-
-#endif /* _LTTNG_CONSUMERD_H */
diff --git a/src/bin/lttng-consumerd/lttng-consumerd.hpp b/src/bin/lttng-consumerd/lttng-consumerd.hpp
new file mode 100644 (file)
index 0000000..354f7f3
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_CONSUMERD_H
+#define _LTTNG_CONSUMERD_H
+
+
+#define NR_LTTNG_CONSUMER_READY                1
+extern int lttng_consumer_ready;
+
+extern const char *tracing_group_name;
+
+/*
+ * This function is dlsym-ed from a test, so needs to be exported.  Making it
+ * have a C linkage name makes it easier, as it avoids having to look up a
+ * mangled name.
+ */
+extern "C" LTTNG_EXPORT
+enum lttng_consumer_type lttng_consumer_get_type();
+
+#endif /* _LTTNG_CONSUMERD_H */
diff --git a/src/bin/lttng-consumerd/testpoint.h b/src/bin/lttng-consumerd/testpoint.h
deleted file mode 100644 (file)
index e0b8b3e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef CONSUMERD_TESTPOINT_H
-#define CONSUMERD_TESTPOINT_H
-
-#include <common/testpoint/testpoint.h>
-
-/* Testpoints, internal use only */
-TESTPOINT_DECL(consumerd_data_thread_poll);
-
-#endif /* CONSUMERD_TESTPOINT_H */
diff --git a/src/bin/lttng-consumerd/testpoint.hpp b/src/bin/lttng-consumerd/testpoint.hpp
new file mode 100644 (file)
index 0000000..da7eed5
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef CONSUMERD_TESTPOINT_H
+#define CONSUMERD_TESTPOINT_H
+
+#include <common/testpoint/testpoint.hpp>
+
+/* Testpoints, internal use only */
+TESTPOINT_DECL(consumerd_data_thread_poll);
+
+#endif /* CONSUMERD_TESTPOINT_H */
index b4231f3e99e739ca5a47bddd39987f918e0fab9c..209045c7ecaf5f810435f8d758f73bd1c4cf0be9 100644 (file)
@@ -11,4 +11,4 @@ bin_PROGRAMS = lttng-crash
 lttng_crash_SOURCES = lttng-crash.cpp
 
 lttng_crash_LDADD = $(top_builddir)/src/common/libcommon.la \
-                       $(top_builddir)/src/common/config/libconfig.la
+                       $(top_builddir)/src/common/libconfig.la
index 3f5ea3759a668a8dc5d6e43e58b19a8471c2766d..796850f55cf8b007c9029a3c5250477adef94abc 100644 (file)
 #include <unistd.h>
 #include <ctype.h>
 #include <dirent.h>
-#include <common/compat/endian.h>
+#include <common/compat/endian.hpp>
 #include <inttypes.h>
 #include <stdbool.h>
 
-#include <version.h>
+#include <version.hpp>
 #include <lttng/lttng.h>
-#include <common/common.h>
-#include <common/spawn-viewer.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/spawn-viewer.hpp>
+#include <common/utils.hpp>
 
 #define COPY_BUFLEN            4096
 #define RB_CRASH_DUMP_ABI_LEN  32
index 10ad3a0ab4317b1fe9d1a114dd30f01a15ff9841..5bfc9ac54528b93fb7cbf541f2740527e1376065 100644 (file)
@@ -9,30 +9,30 @@ endif
 
 bin_PROGRAMS = lttng-relayd
 
-lttng_relayd_SOURCES = main.cpp lttng-relayd.h utils.h utils.cpp cmd.h \
-                       index.cpp index.h live.cpp live.h ctf-trace.cpp ctf-trace.h \
-                       cmd-2-1.cpp cmd-2-1.h \
-                       cmd-2-2.cpp cmd-2-2.h \
-                       cmd-2-4.cpp cmd-2-4.h \
-                       cmd-2-11.cpp cmd-2-11.h \
-                       health-relayd.cpp health-relayd.h \
-                       lttng-viewer-abi.h testpoint.h \
-                       viewer-stream.h viewer-stream.cpp \
-                       session.cpp session.h \
-                       stream.cpp stream.h \
-                       connection.cpp connection.h \
-                       viewer-session.cpp viewer-session.h \
-                       tracefile-array.cpp tracefile-array.h \
-                       tcp_keep_alive.cpp tcp_keep_alive.h \
-                       sessiond-trace-chunks.cpp sessiond-trace-chunks.h \
-                       backward-compatibility-group-by.cpp backward-compatibility-group-by.h
+lttng_relayd_SOURCES = main.cpp lttng-relayd.hpp utils.hpp utils.cpp cmd.hpp \
+                       index.cpp index.hpp live.cpp live.hpp ctf-trace.cpp ctf-trace.hpp \
+                       cmd-2-1.cpp cmd-2-1.hpp \
+                       cmd-2-2.cpp cmd-2-2.hpp \
+                       cmd-2-4.cpp cmd-2-4.hpp \
+                       cmd-2-11.cpp cmd-2-11.hpp \
+                       health-relayd.cpp health-relayd.hpp \
+                       lttng-viewer-abi.hpp testpoint.hpp \
+                       viewer-stream.hpp viewer-stream.cpp \
+                       session.cpp session.hpp \
+                       stream.cpp stream.hpp \
+                       connection.cpp connection.hpp \
+                       viewer-session.cpp viewer-session.hpp \
+                       tracefile-array.cpp tracefile-array.hpp \
+                       tcp_keep_alive.cpp tcp_keep_alive.hpp \
+                       sessiond-trace-chunks.cpp sessiond-trace-chunks.hpp \
+                       backward-compatibility-group-by.cpp backward-compatibility-group-by.hpp
 
 # link on liblttngctl for check if relayd is already alive.
 lttng_relayd_LDADD = $(URCU_LIBS) \
                $(top_builddir)/src/common/libcommon.la \
-               $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \
-               $(top_builddir)/src/common/hashtable/libhashtable.la \
-               $(top_builddir)/src/common/compat/libcompat.la \
-               $(top_builddir)/src/common/index/libindex.la \
-               $(top_builddir)/src/common/health/libhealth.la \
-               $(top_builddir)/src/common/testpoint/libtestpoint.la
+               $(top_builddir)/src/common/libsessiond-comm.la \
+               $(top_builddir)/src/common/libhashtable.la \
+               $(top_builddir)/src/common/libcompat.la \
+               $(top_builddir)/src/common/libindex.la \
+               $(top_builddir)/src/common/libhealth.la \
+               $(top_builddir)/src/common/libtestpoint.la
index f0454a56b70a0c2db24a632323d8df62f462c525..e1d289d98748090e9fada15a72c8536d52b675f6 100644 (file)
@@ -5,17 +5,17 @@
  *
  */
 
-#include "common/time.h"
+#include "common/time.hpp"
 #include <regex.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/utils.hpp>
 
-#include "backward-compatibility-group-by.h"
+#include "backward-compatibility-group-by.hpp"
 
 #define DATETIME_REGEX \
        ".*-[1-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9]-[0-2][0-9][0-5][0-9][0-5][0-9]$"
diff --git a/src/bin/lttng-relayd/backward-compatibility-group-by.h b/src/bin/lttng-relayd/backward-compatibility-group-by.h
deleted file mode 100644 (file)
index 4cf7462..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef BACKWARD_COMPATIBILITY_GROUP_BY_H
-#define BACKWARD_COMPATIBILITY_GROUP_BY_H
-
-#include <time.h>
-
-char *backward_compat_group_by_session(const char *path,
-               const char *local_session_name,
-               time_t session_creation_time);
-
-#endif /* BACKWARD_COMPATIBILITY_GROUP_BY_H */
diff --git a/src/bin/lttng-relayd/backward-compatibility-group-by.hpp b/src/bin/lttng-relayd/backward-compatibility-group-by.hpp
new file mode 100644 (file)
index 0000000..4cf7462
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef BACKWARD_COMPATIBILITY_GROUP_BY_H
+#define BACKWARD_COMPATIBILITY_GROUP_BY_H
+
+#include <time.h>
+
+char *backward_compat_group_by_session(const char *path,
+               const char *local_session_name,
+               time_t session_creation_time);
+
+#endif /* BACKWARD_COMPATIBILITY_GROUP_BY_H */
index 1f939dd07428a45fdee4ea610c8cebf45dbd2dd1..9befdd606ac6b8f0db8b7d0a36b2dc9148285f50 100644 (file)
@@ -9,13 +9,13 @@
 
 #define _LGPL_SOURCE
 
-#include <common/common.h>
-#include <common/sessiond-comm/relayd.h>
-#include <common/compat/string.h>
+#include <common/common.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/compat/string.hpp>
 #include <lttng/constant.h>
 
-#include "cmd-2-1.h"
-#include "utils.h"
+#include "cmd-2-1.hpp"
+#include "utils.hpp"
 
 /*
  * cmd_recv_stream_2_1 allocates path_name and channel_name.
diff --git a/src/bin/lttng-relayd/cmd-2-1.h b/src/bin/lttng-relayd/cmd-2-1.h
deleted file mode 100644 (file)
index 7040e4f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef RELAYD_CMD_2_1_H
-#define RELAYD_CMD_2_1_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include "lttng-relayd.h"
-#include <common/buffer-view.h>
-
-int cmd_recv_stream_2_1(const struct lttng_buffer_view *payload,
-               char **path_name, char **channel_name);
-
-#endif /* RELAYD_CMD_2_1_H */
diff --git a/src/bin/lttng-relayd/cmd-2-1.hpp b/src/bin/lttng-relayd/cmd-2-1.hpp
new file mode 100644 (file)
index 0000000..147069b
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef RELAYD_CMD_2_1_H
+#define RELAYD_CMD_2_1_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "lttng-relayd.hpp"
+#include <common/buffer-view.hpp>
+
+int cmd_recv_stream_2_1(const struct lttng_buffer_view *payload,
+               char **path_name, char **channel_name);
+
+#endif /* RELAYD_CMD_2_1_H */
index aa97dd0f0e0ddfd3e36f7e7857876f70c80864a7..7c750c61de307e9ec19844c35af3908f520d8cfa 100644 (file)
@@ -8,15 +8,15 @@
 #define _LGPL_SOURCE
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/sessiond-comm/relayd.h>
+#include <common/common.hpp>
+#include <common/sessiond-comm/relayd.hpp>
 
-#include <common/compat/endian.h>
-#include <common/compat/string.h>
+#include <common/compat/endian.hpp>
+#include <common/compat/string.hpp>
 #include <lttng/constant.h>
 
-#include "cmd-2-11.h"
-#include "utils.h"
+#include "cmd-2-11.hpp"
+#include "utils.hpp"
 
 int cmd_create_session_2_11(const struct lttng_buffer_view *payload,
                char *session_name, char *hostname, char *base_path,
diff --git a/src/bin/lttng-relayd/cmd-2-11.h b/src/bin/lttng-relayd/cmd-2-11.h
deleted file mode 100644 (file)
index b3a3a99..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2018 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef RELAYD_CMD_2_11_H
-#define RELAYD_CMD_2_11_H
-
-#include "lttng-relayd.h"
-#include <common/buffer-view.h>
-#include <common/uuid.h>
-
-int cmd_create_session_2_11(const struct lttng_buffer_view *payload,
-               char *session_name, char *hostname, char *base_path,
-               uint32_t *live_timer, bool *snapshot,
-               uint64_t *id_sessiond, lttng_uuid sessiond_uuid,
-               bool *has_current_chunk, uint64_t *current_chunk_id,
-               time_t *creation_time,
-               bool *session_name_contains_creation_time);
-
-int cmd_recv_stream_2_11(const struct lttng_buffer_view *payload,
-               char **ret_path_name, char **ret_channel_name,
-               uint64_t *tracefile_size, uint64_t *tracefile_count,
-               uint64_t *trace_archive_id);
-
-#endif /* RELAYD_CMD_2_11_H */
diff --git a/src/bin/lttng-relayd/cmd-2-11.hpp b/src/bin/lttng-relayd/cmd-2-11.hpp
new file mode 100644 (file)
index 0000000..4b004f0
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef RELAYD_CMD_2_11_H
+#define RELAYD_CMD_2_11_H
+
+#include "lttng-relayd.hpp"
+#include <common/buffer-view.hpp>
+#include <common/uuid.hpp>
+
+int cmd_create_session_2_11(const struct lttng_buffer_view *payload,
+               char *session_name, char *hostname, char *base_path,
+               uint32_t *live_timer, bool *snapshot,
+               uint64_t *id_sessiond, lttng_uuid sessiond_uuid,
+               bool *has_current_chunk, uint64_t *current_chunk_id,
+               time_t *creation_time,
+               bool *session_name_contains_creation_time);
+
+int cmd_recv_stream_2_11(const struct lttng_buffer_view *payload,
+               char **ret_path_name, char **ret_channel_name,
+               uint64_t *tracefile_size, uint64_t *tracefile_count,
+               uint64_t *trace_archive_id);
+
+#endif /* RELAYD_CMD_2_11_H */
index bd18714af840626d0291382205a33bd6a4054563..3d9af63a313f5f2a9ff6bf9a6f451d62dcf25578 100644 (file)
@@ -9,16 +9,16 @@
 
 #define _LGPL_SOURCE
 
-#include <common/common.h>
-#include <common/sessiond-comm/relayd.h>
+#include <common/common.hpp>
+#include <common/sessiond-comm/relayd.hpp>
 
-#include <common/compat/endian.h>
-#include <common/compat/string.h>
+#include <common/compat/endian.hpp>
+#include <common/compat/string.hpp>
 #include <lttng/constant.h>
 
-#include "cmd-2-2.h"
-#include "cmd-2-1.h"
-#include "utils.h"
+#include "cmd-2-2.hpp"
+#include "cmd-2-1.hpp"
+#include "utils.hpp"
 
 /*
  * cmd_recv_stream_2_2 allocates path_name and channel_name.
diff --git a/src/bin/lttng-relayd/cmd-2-2.h b/src/bin/lttng-relayd/cmd-2-2.h
deleted file mode 100644 (file)
index e754ace..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef RELAYD_CMD_2_2_H
-#define RELAYD_CMD_2_2_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include "lttng-relayd.h"
-#include <common/buffer-view.h>
-
-int cmd_recv_stream_2_2(const struct lttng_buffer_view *payload,
-               char **path_name, char **channel_name,
-               uint64_t *tracefile_size, uint64_t *tracefile_count);
-
-#endif /* RELAYD_CMD_2_2_H */
diff --git a/src/bin/lttng-relayd/cmd-2-2.hpp b/src/bin/lttng-relayd/cmd-2-2.hpp
new file mode 100644 (file)
index 0000000..010bbb1
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef RELAYD_CMD_2_2_H
+#define RELAYD_CMD_2_2_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "lttng-relayd.hpp"
+#include <common/buffer-view.hpp>
+
+int cmd_recv_stream_2_2(const struct lttng_buffer_view *payload,
+               char **path_name, char **channel_name,
+               uint64_t *tracefile_size, uint64_t *tracefile_count);
+
+#endif /* RELAYD_CMD_2_2_H */
index 7abc371f06732056bf61435d8bf71750cdb3a774..7b546c7f661d5babd2161c0e51abb98d0f250036 100644 (file)
@@ -9,15 +9,15 @@
 
 #define _LGPL_SOURCE
 
-#include <common/common.h>
-#include <common/sessiond-comm/relayd.h>
+#include <common/common.hpp>
+#include <common/sessiond-comm/relayd.hpp>
 
-#include <common/compat/endian.h>
-#include <common/compat/string.h>
+#include <common/compat/endian.hpp>
+#include <common/compat/string.hpp>
 #include <lttng/constant.h>
 
-#include "cmd-2-4.h"
-#include "lttng-relayd.h"
+#include "cmd-2-4.hpp"
+#include "lttng-relayd.hpp"
 
 int cmd_create_session_2_4(const struct lttng_buffer_view *payload,
                char *session_name, char *hostname,
diff --git a/src/bin/lttng-relayd/cmd-2-4.h b/src/bin/lttng-relayd/cmd-2-4.h
deleted file mode 100644 (file)
index 0949287..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef RELAYD_CMD_2_4_H
-#define RELAYD_CMD_2_4_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include "lttng-relayd.h"
-#include <common/buffer-view.h>
-
-int cmd_create_session_2_4(const struct lttng_buffer_view *payload,
-               char *session_name, char *hostname,
-               uint32_t *live_timer, bool *snapshot);
-
-#endif /* RELAYD_CMD_2_4_H */
diff --git a/src/bin/lttng-relayd/cmd-2-4.hpp b/src/bin/lttng-relayd/cmd-2-4.hpp
new file mode 100644 (file)
index 0000000..b3d105c
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef RELAYD_CMD_2_4_H
+#define RELAYD_CMD_2_4_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "lttng-relayd.hpp"
+#include <common/buffer-view.hpp>
+
+int cmd_create_session_2_4(const struct lttng_buffer_view *payload,
+               char *session_name, char *hostname,
+               uint32_t *live_timer, bool *snapshot);
+
+#endif /* RELAYD_CMD_2_4_H */
diff --git a/src/bin/lttng-relayd/cmd.h b/src/bin/lttng-relayd/cmd.h
deleted file mode 100644 (file)
index 86668b4..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef RELAYD_CMD_H
-#define RELAYD_CMD_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include "cmd-2-1.h"
-#include "cmd-2-2.h"
-#include "cmd-2-4.h"
-#include "cmd-2-11.h"
-
-#endif /* RELAYD_CMD_H */
diff --git a/src/bin/lttng-relayd/cmd.hpp b/src/bin/lttng-relayd/cmd.hpp
new file mode 100644 (file)
index 0000000..24e361a
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef RELAYD_CMD_H
+#define RELAYD_CMD_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "cmd-2-1.hpp"
+#include "cmd-2-2.hpp"
+#include "cmd-2-4.hpp"
+#include "cmd-2-11.hpp"
+
+#endif /* RELAYD_CMD_H */
index 98ffad29f986de121db5b607c9a9cfd7b0918abb..c1e58aba3430f0fbbbedb89cb42261731cc94b3d 100644 (file)
@@ -8,12 +8,12 @@
  */
 
 #define _LGPL_SOURCE
-#include <common/common.h>
+#include <common/common.hpp>
 #include <urcu/rculist.h>
 
-#include "connection.h"
-#include "stream.h"
-#include "viewer-session.h"
+#include "connection.hpp"
+#include "stream.hpp"
+#include "viewer-session.hpp"
 
 bool connection_get(struct relay_connection *conn)
 {
diff --git a/src/bin/lttng-relayd/connection.h b/src/bin/lttng-relayd/connection.h
deleted file mode 100644 (file)
index 98ca915..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-#ifndef _CONNECTION_H
-#define _CONNECTION_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <limits.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <urcu.h>
-#include <urcu/wfcqueue.h>
-#include <urcu/list.h>
-
-#include <common/hashtable/hashtable.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/sessiond-comm/relayd.h>
-#include <common/dynamic-buffer.h>
-
-#include "session.h"
-
-enum connection_type {
-       RELAY_CONNECTION_UNKNOWN    = 0,
-       RELAY_DATA                  = 1,
-       RELAY_CONTROL               = 2,
-       RELAY_VIEWER_COMMAND        = 3,
-       RELAY_VIEWER_NOTIFICATION   = 4,
-};
-
-enum data_connection_state {
-       DATA_CONNECTION_STATE_RECEIVE_HEADER = 0,
-       DATA_CONNECTION_STATE_RECEIVE_PAYLOAD = 1,
-};
-
-enum ctrl_connection_state {
-       CTRL_CONNECTION_STATE_RECEIVE_HEADER = 0,
-       CTRL_CONNECTION_STATE_RECEIVE_PAYLOAD = 1,
-};
-
-struct data_connection_state_receive_header {
-       uint64_t received, left_to_receive;
-       char header_reception_buffer[sizeof(struct lttcomm_relayd_data_hdr)];
-};
-
-struct data_connection_state_receive_payload {
-       uint64_t received, left_to_receive;
-       struct lttcomm_relayd_data_hdr header;
-       bool rotate_index;
-};
-
-struct ctrl_connection_state_receive_header {
-       uint64_t received, left_to_receive;
-};
-
-struct ctrl_connection_state_receive_payload {
-       uint64_t received, left_to_receive;
-       struct lttcomm_relayd_hdr header;
-};
-
-/*
- * Internal structure to map a socket with the corresponding session.
- * A hashtable indexed on the socket FD is used for the lookups.
- *
- * Connections are assumed to be accessed from a single thread. Live
- * connections between the relay and a live client are only accessed
- * from the live worker thread.
- *
- * The connections between the consumerd/sessiond and the relayd are only
- * handled by the "main" worker thread (as in, the worker thread in main.c).
- *
- * This is why there are no back references to connections from the
- * sessions and session list.
- */
-struct relay_connection {
-       struct lttcomm_sock *sock;
-       struct cds_wfcq_node qnode;
-
-       enum connection_type type;
-       /*
-        * session is only ever set for RELAY_CONTROL connection type.
-        */
-       struct relay_session *session;
-       /*
-        * viewer_session is only ever set for RELAY_VIEWER_COMMAND
-        * connection type.
-        */
-       struct relay_viewer_session *viewer_session;
-
-       /*
-        * Protocol version to use for this connection. Only valid for
-        * RELAY_CONTROL connection type.
-        */
-       uint32_t major;
-       uint32_t minor;
-
-       struct urcu_ref ref;
-
-       bool version_check_done;
-
-       /*
-        * Node member of connection within global socket hash table.
-        */
-       struct lttng_ht_node_ulong sock_n;
-       bool in_socket_ht;
-       struct lttng_ht *socket_ht;     /* HACK: Contained within this hash table. */
-       struct rcu_head rcu_node;       /* For call_rcu teardown. */
-
-       union {
-               struct {
-                       enum data_connection_state state_id;
-                       union {
-                               struct data_connection_state_receive_header receive_header;
-                               struct data_connection_state_receive_payload receive_payload;
-                       } state;
-               } data;
-               struct {
-                       enum ctrl_connection_state state_id;
-                       union {
-                               struct ctrl_connection_state_receive_header receive_header;
-                               struct ctrl_connection_state_receive_payload receive_payload;
-                       } state;
-                       struct lttng_dynamic_buffer reception_buffer;
-               } ctrl;
-       } protocol;
-};
-
-struct relay_connection *connection_create(struct lttcomm_sock *sock,
-               enum connection_type type);
-struct relay_connection *connection_get_by_sock(struct lttng_ht *relay_connections_ht,
-               int sock);
-int connection_reset_protocol_state(struct relay_connection *connection);
-bool connection_get(struct relay_connection *connection);
-void connection_put(struct relay_connection *connection);
-void connection_ht_add(struct lttng_ht *relay_connections_ht,
-               struct relay_connection *conn);
-int connection_set_session(struct relay_connection *conn,
-               struct relay_session *session);
-
-#endif /* _CONNECTION_H */
diff --git a/src/bin/lttng-relayd/connection.hpp b/src/bin/lttng-relayd/connection.hpp
new file mode 100644 (file)
index 0000000..de25255
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef _CONNECTION_H
+#define _CONNECTION_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <limits.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <urcu.h>
+#include <urcu/wfcqueue.h>
+#include <urcu/list.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/dynamic-buffer.hpp>
+
+#include "session.hpp"
+
+enum connection_type {
+       RELAY_CONNECTION_UNKNOWN    = 0,
+       RELAY_DATA                  = 1,
+       RELAY_CONTROL               = 2,
+       RELAY_VIEWER_COMMAND        = 3,
+       RELAY_VIEWER_NOTIFICATION   = 4,
+};
+
+enum data_connection_state {
+       DATA_CONNECTION_STATE_RECEIVE_HEADER = 0,
+       DATA_CONNECTION_STATE_RECEIVE_PAYLOAD = 1,
+};
+
+enum ctrl_connection_state {
+       CTRL_CONNECTION_STATE_RECEIVE_HEADER = 0,
+       CTRL_CONNECTION_STATE_RECEIVE_PAYLOAD = 1,
+};
+
+struct data_connection_state_receive_header {
+       uint64_t received, left_to_receive;
+       char header_reception_buffer[sizeof(struct lttcomm_relayd_data_hdr)];
+};
+
+struct data_connection_state_receive_payload {
+       uint64_t received, left_to_receive;
+       struct lttcomm_relayd_data_hdr header;
+       bool rotate_index;
+};
+
+struct ctrl_connection_state_receive_header {
+       uint64_t received, left_to_receive;
+};
+
+struct ctrl_connection_state_receive_payload {
+       uint64_t received, left_to_receive;
+       struct lttcomm_relayd_hdr header;
+};
+
+/*
+ * Internal structure to map a socket with the corresponding session.
+ * A hashtable indexed on the socket FD is used for the lookups.
+ *
+ * Connections are assumed to be accessed from a single thread. Live
+ * connections between the relay and a live client are only accessed
+ * from the live worker thread.
+ *
+ * The connections between the consumerd/sessiond and the relayd are only
+ * handled by the "main" worker thread (as in, the worker thread in main.c).
+ *
+ * This is why there are no back references to connections from the
+ * sessions and session list.
+ */
+struct relay_connection {
+       struct lttcomm_sock *sock;
+       struct cds_wfcq_node qnode;
+
+       enum connection_type type;
+       /*
+        * session is only ever set for RELAY_CONTROL connection type.
+        */
+       struct relay_session *session;
+       /*
+        * viewer_session is only ever set for RELAY_VIEWER_COMMAND
+        * connection type.
+        */
+       struct relay_viewer_session *viewer_session;
+
+       /*
+        * Protocol version to use for this connection. Only valid for
+        * RELAY_CONTROL connection type.
+        */
+       uint32_t major;
+       uint32_t minor;
+
+       struct urcu_ref ref;
+
+       bool version_check_done;
+
+       /*
+        * Node member of connection within global socket hash table.
+        */
+       struct lttng_ht_node_ulong sock_n;
+       bool in_socket_ht;
+       struct lttng_ht *socket_ht;     /* HACK: Contained within this hash table. */
+       struct rcu_head rcu_node;       /* For call_rcu teardown. */
+
+       union {
+               struct {
+                       enum data_connection_state state_id;
+                       union {
+                               struct data_connection_state_receive_header receive_header;
+                               struct data_connection_state_receive_payload receive_payload;
+                       } state;
+               } data;
+               struct {
+                       enum ctrl_connection_state state_id;
+                       union {
+                               struct ctrl_connection_state_receive_header receive_header;
+                               struct ctrl_connection_state_receive_payload receive_payload;
+                       } state;
+                       struct lttng_dynamic_buffer reception_buffer;
+               } ctrl;
+       } protocol;
+};
+
+struct relay_connection *connection_create(struct lttcomm_sock *sock,
+               enum connection_type type);
+struct relay_connection *connection_get_by_sock(struct lttng_ht *relay_connections_ht,
+               int sock);
+int connection_reset_protocol_state(struct relay_connection *connection);
+bool connection_get(struct relay_connection *connection);
+void connection_put(struct relay_connection *connection);
+void connection_ht_add(struct lttng_ht *relay_connections_ht,
+               struct relay_connection *conn);
+int connection_set_session(struct relay_connection *conn,
+               struct relay_session *session);
+
+#endif /* _CONNECTION_H */
index 7a3cbdea0ebde00f0613ccff1cb42553d2d6d798..747bdcf0d19d910835409ffd5a726c2922cf58b7 100644 (file)
@@ -9,13 +9,13 @@
 
 #define _LGPL_SOURCE
 
-#include <common/common.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/utils.hpp>
 #include <urcu/rculist.h>
 
-#include "ctf-trace.h"
-#include "lttng-relayd.h"
-#include "stream.h"
+#include "ctf-trace.hpp"
+#include "lttng-relayd.hpp"
+#include "stream.hpp"
 
 static uint64_t last_relay_ctf_trace_id;
 static pthread_mutex_t last_relay_ctf_trace_id_lock = PTHREAD_MUTEX_INITIALIZER;
diff --git a/src/bin/lttng-relayd/ctf-trace.h b/src/bin/lttng-relayd/ctf-trace.h
deleted file mode 100644 (file)
index 3afc00f..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef _CTF_TRACE_H
-#define _CTF_TRACE_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <inttypes.h>
-#include <urcu/ref.h>
-
-#include <common/hashtable/hashtable.h>
-
-#include "session.h"
-#include "stream.h"
-#include "viewer-stream.h"
-
-struct ctf_trace {
-       struct urcu_ref ref;            /* Every stream has a ref on the trace. */
-       struct relay_session *session;  /* Back ref to trace session */
-
-       /* Trace sub-folder relative to the session output path. */
-       char *path;
-
-       /*
-        * The ctf_trace lock nests inside the session lock.
-        */
-       pthread_mutex_t lock;
-       uint64_t id;
-       struct relay_viewer_stream *viewer_metadata_stream;     /* RCU protected */
-
-       /*
-        * Relay streams associated with this ctf trace.
-        * Updates are protected by the stream_list lock.
-        * Traversals are protected by RCU.
-        */
-       struct cds_list_head stream_list;
-       pthread_mutex_t stream_list_lock;
-
-       /*
-        * Node within session trace hash table. Node is indexed by
-        * stream path name.
-        */
-       struct lttng_ht_node_str node;
-       struct rcu_head rcu_node;       /* For call_rcu teardown. */
-
-       /*
-        * True if the metadata stream of this trace was sent the viewer in the
-        * past.
-        */
-       bool metadata_stream_sent_to_viewer;
-};
-
-struct ctf_trace *ctf_trace_get_by_path_or_create(struct relay_session *session,
-               const char *subpath);
-bool ctf_trace_get(struct ctf_trace *trace);
-void ctf_trace_put(struct ctf_trace *trace);
-
-int ctf_trace_close(struct ctf_trace *trace);
-
-struct relay_viewer_stream *ctf_trace_get_viewer_metadata_stream(struct ctf_trace *trace);
-
-#endif /* _CTF_TRACE_H */
diff --git a/src/bin/lttng-relayd/ctf-trace.hpp b/src/bin/lttng-relayd/ctf-trace.hpp
new file mode 100644 (file)
index 0000000..dbf7d3f
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _CTF_TRACE_H
+#define _CTF_TRACE_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <inttypes.h>
+#include <urcu/ref.h>
+
+#include <common/hashtable/hashtable.hpp>
+
+#include "session.hpp"
+#include "stream.hpp"
+#include "viewer-stream.hpp"
+
+struct ctf_trace {
+       struct urcu_ref ref;            /* Every stream has a ref on the trace. */
+       struct relay_session *session;  /* Back ref to trace session */
+
+       /* Trace sub-folder relative to the session output path. */
+       char *path;
+
+       /*
+        * The ctf_trace lock nests inside the session lock.
+        */
+       pthread_mutex_t lock;
+       uint64_t id;
+       struct relay_viewer_stream *viewer_metadata_stream;     /* RCU protected */
+
+       /*
+        * Relay streams associated with this ctf trace.
+        * Updates are protected by the stream_list lock.
+        * Traversals are protected by RCU.
+        */
+       struct cds_list_head stream_list;
+       pthread_mutex_t stream_list_lock;
+
+       /*
+        * Node within session trace hash table. Node is indexed by
+        * stream path name.
+        */
+       struct lttng_ht_node_str node;
+       struct rcu_head rcu_node;       /* For call_rcu teardown. */
+
+       /*
+        * True if the metadata stream of this trace was sent the viewer in the
+        * past.
+        */
+       bool metadata_stream_sent_to_viewer;
+};
+
+struct ctf_trace *ctf_trace_get_by_path_or_create(struct relay_session *session,
+               const char *subpath);
+bool ctf_trace_get(struct ctf_trace *trace);
+void ctf_trace_put(struct ctf_trace *trace);
+
+int ctf_trace_close(struct ctf_trace *trace);
+
+struct relay_viewer_stream *ctf_trace_get_viewer_metadata_stream(struct ctf_trace *trace);
+
+#endif /* _CTF_TRACE_H */
index 2e532bde4eec832b13895372ddb2b314b7fae180..5fc644f7c9b5d59f7851aea06dc6f041efd0b667 100644 (file)
 #include <urcu/compiler.h>
 #include <inttypes.h>
 
-#include <common/defaults.h>
-#include <common/common.h>
-#include <common/consumer/consumer.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/compat/poll.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/utils.h>
-#include <common/compat/getenv.h>
-#include <common/fd-tracker/utils.h>
-
-#include "lttng-relayd.h"
-#include "health-relayd.h"
+#include <common/defaults.hpp>
+#include <common/common.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/compat/poll.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/utils.hpp>
+#include <common/compat/getenv.hpp>
+#include <common/fd-tracker/utils.hpp>
+
+#include "lttng-relayd.hpp"
+#include "health-relayd.hpp"
 
 /* Global health check unix path */
 static
diff --git a/src/bin/lttng-relayd/health-relayd.h b/src/bin/lttng-relayd/health-relayd.h
deleted file mode 100644 (file)
index 3384f49..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef HEALTH_RELAYD_H
-#define HEALTH_RELAYD_H
-
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <limits.h>
-#include <lttng/health-internal.h>
-
-#define LTTNG_RELAYD_HEALTH_ENV                "LTTNG_RELAYD_HEALTH"
-
-enum health_type_relayd {
-       HEALTH_RELAYD_TYPE_DISPATCHER           = 0,
-       HEALTH_RELAYD_TYPE_WORKER               = 1,
-       HEALTH_RELAYD_TYPE_LISTENER             = 2,
-       HEALTH_RELAYD_TYPE_LIVE_DISPATCHER      = 3,
-       HEALTH_RELAYD_TYPE_LIVE_WORKER          = 4,
-       HEALTH_RELAYD_TYPE_LIVE_LISTENER        = 5,
-
-       NR_HEALTH_RELAYD_TYPES,
-};
-
-extern struct health_app *health_relayd;
-
-extern int health_quit_pipe[2];
-
-void *thread_manage_health(void *data);
-
-#endif /* HEALTH_RELAYD_H */
diff --git a/src/bin/lttng-relayd/health-relayd.hpp b/src/bin/lttng-relayd/health-relayd.hpp
new file mode 100644 (file)
index 0000000..6339856
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef HEALTH_RELAYD_H
+#define HEALTH_RELAYD_H
+
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <limits.h>
+#include <lttng/health-internal.hpp>
+
+#define LTTNG_RELAYD_HEALTH_ENV                "LTTNG_RELAYD_HEALTH"
+
+enum health_type_relayd {
+       HEALTH_RELAYD_TYPE_DISPATCHER           = 0,
+       HEALTH_RELAYD_TYPE_WORKER               = 1,
+       HEALTH_RELAYD_TYPE_LISTENER             = 2,
+       HEALTH_RELAYD_TYPE_LIVE_DISPATCHER      = 3,
+       HEALTH_RELAYD_TYPE_LIVE_WORKER          = 4,
+       HEALTH_RELAYD_TYPE_LIVE_LISTENER        = 5,
+
+       NR_HEALTH_RELAYD_TYPES,
+};
+
+extern struct health_app *health_relayd;
+
+extern int health_quit_pipe[2];
+
+void *thread_manage_health(void *data);
+
+#endif /* HEALTH_RELAYD_H */
index f2f102e64d4714d945551435dc5f41e83cb394db..3074da3b6dda9e33c6c65e53c57899904eece18f 100644 (file)
@@ -9,14 +9,14 @@
 
 #define _LGPL_SOURCE
 
-#include <common/common.h>
-#include <common/utils.h>
-#include <common/compat/endian.h>
-
-#include "lttng-relayd.h"
-#include "stream.h"
-#include "index.h"
-#include "connection.h"
+#include <common/common.hpp>
+#include <common/utils.hpp>
+#include <common/compat/endian.hpp>
+
+#include "lttng-relayd.hpp"
+#include "stream.hpp"
+#include "index.hpp"
+#include "connection.hpp"
 
 /*
  * Allocate a new relay index object. Pass the stream in which it is
diff --git a/src/bin/lttng-relayd/index.h b/src/bin/lttng-relayd/index.h
deleted file mode 100644 (file)
index 4364f12..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef _RELAY_INDEX_H
-#define _RELAY_INDEX_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <inttypes.h>
-#include <pthread.h>
-
-#include <common/hashtable/hashtable.h>
-#include <common/index/index.h>
-
-struct relay_stream;
-struct relay_connection;
-struct lttcomm_relayd_index;
-
-struct relay_index {
-       /*
-        * index lock nests inside stream lock.
-        */
-       struct urcu_ref ref;            /* Reference from getters. */
-       struct relay_stream *stream;    /* Back ref to stream */
-
-       pthread_mutex_t lock;
-       /*
-        * index file on which to write the index data. May differ from
-        * stream->index_file due to tracefile rotation.
-        */
-       struct lttng_index_file *index_file;
-
-       /* Index packet data. This is the data that is written on disk. */
-       struct ctf_packet_index index_data;
-       /* Data + padding size of this packet, filled by the data thread. */
-       uint64_t total_size;
-
-       bool has_index_data;
-       bool flushed;
-       bool in_hash_table;
-
-       /*
-        * Node within indexes_ht that corresponds to this struct
-        * relay_index. Indexed by net_seq_num, which is unique for this
-        * index across the stream.
-        */
-       struct lttng_ht_node_u64 index_n;
-       struct rcu_head rcu_node;       /* For call_rcu teardown. */
-};
-
-struct relay_index *relay_index_get_by_id_or_create(struct relay_stream *stream,
-               uint64_t net_seq_num);
-void relay_index_put(struct relay_index *index);
-int relay_index_set_file(struct relay_index *index,
-               struct lttng_index_file *index_file,
-               uint64_t data_offset);
-int relay_index_set_data(struct relay_index *index,
-               const struct ctf_packet_index *data);
-int relay_index_try_flush(struct relay_index *index);
-
-void relay_index_close_all(struct relay_stream *stream);
-void relay_index_close_partial_fd(struct relay_stream *stream);
-uint64_t relay_index_find_last(struct relay_stream *stream);
-int relay_index_switch_all_files(struct relay_stream *stream);
-int relay_index_set_control_data(struct relay_index *index,
-               const struct lttcomm_relayd_index *data,
-               unsigned int minor_version);
-
-#endif /* _RELAY_INDEX_H */
diff --git a/src/bin/lttng-relayd/index.hpp b/src/bin/lttng-relayd/index.hpp
new file mode 100644 (file)
index 0000000..cb29485
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef _RELAY_INDEX_H
+#define _RELAY_INDEX_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <inttypes.h>
+#include <pthread.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <common/index/index.hpp>
+
+struct relay_stream;
+struct relay_connection;
+struct lttcomm_relayd_index;
+
+struct relay_index {
+       /*
+        * index lock nests inside stream lock.
+        */
+       struct urcu_ref ref;            /* Reference from getters. */
+       struct relay_stream *stream;    /* Back ref to stream */
+
+       pthread_mutex_t lock;
+       /*
+        * index file on which to write the index data. May differ from
+        * stream->index_file due to tracefile rotation.
+        */
+       struct lttng_index_file *index_file;
+
+       /* Index packet data. This is the data that is written on disk. */
+       struct ctf_packet_index index_data;
+       /* Data + padding size of this packet, filled by the data thread. */
+       uint64_t total_size;
+
+       bool has_index_data;
+       bool flushed;
+       bool in_hash_table;
+
+       /*
+        * Node within indexes_ht that corresponds to this struct
+        * relay_index. Indexed by net_seq_num, which is unique for this
+        * index across the stream.
+        */
+       struct lttng_ht_node_u64 index_n;
+       struct rcu_head rcu_node;       /* For call_rcu teardown. */
+};
+
+struct relay_index *relay_index_get_by_id_or_create(struct relay_stream *stream,
+               uint64_t net_seq_num);
+void relay_index_put(struct relay_index *index);
+int relay_index_set_file(struct relay_index *index,
+               struct lttng_index_file *index_file,
+               uint64_t data_offset);
+int relay_index_set_data(struct relay_index *index,
+               const struct ctf_packet_index *data);
+int relay_index_try_flush(struct relay_index *index);
+
+void relay_index_close_all(struct relay_stream *stream);
+void relay_index_close_partial_fd(struct relay_stream *stream);
+uint64_t relay_index_find_last(struct relay_stream *stream);
+int relay_index_switch_all_files(struct relay_stream *stream);
+int relay_index_set_control_data(struct relay_index *index,
+               const struct lttcomm_relayd_index *data,
+               unsigned int minor_version);
+
+#endif /* _RELAY_INDEX_H */
index e3d27b1ef8411a1a6efc837ffa10051d6108155f..cc6e21ca50190c4b7b0ca60e6bb14624a60aff21 100644 (file)
 #include <urcu/uatomic.h>
 #include <string>
 
-#include <common/common.h>
-#include <common/compat/endian.h>
-#include <common/compat/poll.h>
-#include <common/compat/socket.h>
-#include <common/defaults.h>
-#include <common/fd-tracker/utils.h>
-#include <common/fs-handle.h>
-#include <common/futex.h>
-#include <common/index/index.h>
-#include <common/sessiond-comm/inet.h>
-#include <common/sessiond-comm/relayd.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/uri.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/compat/endian.hpp>
+#include <common/compat/poll.hpp>
+#include <common/compat/socket.hpp>
+#include <common/defaults.hpp>
+#include <common/fd-tracker/utils.hpp>
+#include <common/fs-handle.hpp>
+#include <common/futex.hpp>
+#include <common/index/index.hpp>
+#include <common/sessiond-comm/inet.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/uri.hpp>
+#include <common/utils.hpp>
 #include <lttng/lttng.h>
 
-#include "cmd.h"
-#include "connection.h"
-#include "ctf-trace.h"
-#include "health-relayd.h"
-#include "live.h"
-#include "lttng-relayd.h"
-#include "session.h"
-#include "stream.h"
-#include "testpoint.h"
-#include "utils.h"
-#include "viewer-session.h"
-#include "viewer-stream.h"
+#include "cmd.hpp"
+#include "connection.hpp"
+#include "ctf-trace.hpp"
+#include "health-relayd.hpp"
+#include "live.hpp"
+#include "lttng-relayd.hpp"
+#include "session.hpp"
+#include "stream.hpp"
+#include "testpoint.hpp"
+#include "utils.hpp"
+#include "viewer-session.hpp"
+#include "viewer-stream.hpp"
 
 #define SESSION_BUF_DEFAULT_COUNT      16
 
diff --git a/src/bin/lttng-relayd/live.h b/src/bin/lttng-relayd/live.h
deleted file mode 100644 (file)
index d6ec89e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef LTTNG_RELAYD_LIVE_H
-#define LTTNG_RELAYD_LIVE_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <common/uri.h>
-
-#include "lttng-relayd.h"
-
-int relayd_live_create(struct lttng_uri *live_uri);
-int relayd_live_stop(void);
-int relayd_live_join(void);
-
-#endif /* LTTNG_RELAYD_LIVE_H */
diff --git a/src/bin/lttng-relayd/live.hpp b/src/bin/lttng-relayd/live.hpp
new file mode 100644 (file)
index 0000000..d1866d3
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef LTTNG_RELAYD_LIVE_H
+#define LTTNG_RELAYD_LIVE_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <common/uri.hpp>
+
+#include "lttng-relayd.hpp"
+
+int relayd_live_create(struct lttng_uri *live_uri);
+int relayd_live_stop(void);
+int relayd_live_join(void);
+
+#endif /* LTTNG_RELAYD_LIVE_H */
diff --git a/src/bin/lttng-relayd/lttng-relayd.h b/src/bin/lttng-relayd/lttng-relayd.h
deleted file mode 100644 (file)
index e64bb37..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef LTTNG_RELAYD_H
-#define LTTNG_RELAYD_H
-
-/*
- * Copyright (C) 2012 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <limits.h>
-#include <urcu.h>
-#include <urcu/wfcqueue.h>
-
-#include <common/hashtable/hashtable.h>
-#include <common/fd-tracker/fd-tracker.h>
-
-struct sessiond_trace_chunk_registry;
-
-/*
- * Queue used to enqueue relay requests
- */
-struct relay_conn_queue {
-       struct cds_wfcq_head head;
-       struct cds_wfcq_tail tail;
-       int32_t futex;
-};
-
-enum relay_group_output_by {
-       RELAYD_GROUP_OUTPUT_BY_UNKNOWN,
-       RELAYD_GROUP_OUTPUT_BY_HOST,
-       RELAYD_GROUP_OUTPUT_BY_SESSION,
-};
-
-/*
- * Contains stream indexed by ID. This is important since many commands lookup
- * streams only by ID thus also keeping them in this hash table makes the
- * search O(1).
- */
-extern struct lttng_ht *sessions_ht;
-extern struct lttng_ht *relay_streams_ht;
-extern struct lttng_ht *viewer_streams_ht;
-extern struct sessiond_trace_chunk_registry *sessiond_trace_chunk_registry;
-
-extern char *opt_output_path;
-extern const char *tracing_group_name;
-extern const char * const config_section_name;
-extern enum relay_group_output_by opt_group_output_by;
-
-extern int thread_quit_pipe[2];
-
-extern struct fd_tracker *the_fd_tracker;
-
-void lttng_relay_notify_ready(void);
-int lttng_relay_stop_threads(void);
-
-#endif /* LTTNG_RELAYD_H */
diff --git a/src/bin/lttng-relayd/lttng-relayd.hpp b/src/bin/lttng-relayd/lttng-relayd.hpp
new file mode 100644 (file)
index 0000000..a92ace7
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef LTTNG_RELAYD_H
+#define LTTNG_RELAYD_H
+
+/*
+ * Copyright (C) 2012 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <limits.h>
+#include <urcu.h>
+#include <urcu/wfcqueue.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <common/fd-tracker/fd-tracker.hpp>
+
+struct sessiond_trace_chunk_registry;
+
+/*
+ * Queue used to enqueue relay requests
+ */
+struct relay_conn_queue {
+       struct cds_wfcq_head head;
+       struct cds_wfcq_tail tail;
+       int32_t futex;
+};
+
+enum relay_group_output_by {
+       RELAYD_GROUP_OUTPUT_BY_UNKNOWN,
+       RELAYD_GROUP_OUTPUT_BY_HOST,
+       RELAYD_GROUP_OUTPUT_BY_SESSION,
+};
+
+/*
+ * Contains stream indexed by ID. This is important since many commands lookup
+ * streams only by ID thus also keeping them in this hash table makes the
+ * search O(1).
+ */
+extern struct lttng_ht *sessions_ht;
+extern struct lttng_ht *relay_streams_ht;
+extern struct lttng_ht *viewer_streams_ht;
+extern struct sessiond_trace_chunk_registry *sessiond_trace_chunk_registry;
+
+extern char *opt_output_path;
+extern const char *tracing_group_name;
+extern const char * const config_section_name;
+extern enum relay_group_output_by opt_group_output_by;
+
+extern int thread_quit_pipe[2];
+
+extern struct fd_tracker *the_fd_tracker;
+
+void lttng_relay_notify_ready(void);
+int lttng_relay_stop_threads(void);
+
+#endif /* LTTNG_RELAYD_H */
diff --git a/src/bin/lttng-relayd/lttng-viewer-abi.h b/src/bin/lttng-relayd/lttng-viewer-abi.h
deleted file mode 100644 (file)
index f5f61b4..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-#ifndef LTTNG_VIEWER_ABI_H
-#define LTTNG_VIEWER_ABI_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#include <limits.h>
-#include <common/macros.h>
-
-#define LTTNG_VIEWER_PATH_MAX          4096
-#define LTTNG_VIEWER_NAME_MAX          255
-#define LTTNG_VIEWER_HOST_NAME_MAX     64
-
-/* Flags in reply to get_next_index and get_packet. */
-enum {
-       /* New metadata is required to read this packet. */
-       LTTNG_VIEWER_FLAG_NEW_METADATA  = (1 << 0),
-       /* New stream got added to the trace. */
-       LTTNG_VIEWER_FLAG_NEW_STREAM    = (1 << 1),
-};
-
-enum lttng_viewer_command {
-       LTTNG_VIEWER_CONNECT            = 1,
-       LTTNG_VIEWER_LIST_SESSIONS      = 2,
-       LTTNG_VIEWER_ATTACH_SESSION     = 3,
-       LTTNG_VIEWER_GET_NEXT_INDEX     = 4,
-       LTTNG_VIEWER_GET_PACKET         = 5,
-       LTTNG_VIEWER_GET_METADATA       = 6,
-       LTTNG_VIEWER_GET_NEW_STREAMS    = 7,
-       LTTNG_VIEWER_CREATE_SESSION     = 8,
-       LTTNG_VIEWER_DETACH_SESSION     = 9,
-};
-
-enum lttng_viewer_attach_return_code {
-       LTTNG_VIEWER_ATTACH_OK          = 1, /* The attach command succeeded. */
-       LTTNG_VIEWER_ATTACH_ALREADY     = 2, /* A viewer is already attached. */
-       LTTNG_VIEWER_ATTACH_UNK         = 3, /* The session ID is unknown. */
-       LTTNG_VIEWER_ATTACH_NOT_LIVE    = 4, /* The session is not live. */
-       LTTNG_VIEWER_ATTACH_SEEK_ERR    = 5, /* Seek error. */
-       LTTNG_VIEWER_ATTACH_NO_SESSION  = 6, /* No viewer session created. */
-};
-
-enum lttng_viewer_next_index_return_code {
-       LTTNG_VIEWER_INDEX_OK           = 1, /* Index is available. */
-       LTTNG_VIEWER_INDEX_RETRY        = 2, /* Index not yet available. */
-       LTTNG_VIEWER_INDEX_HUP          = 3, /* Index closed (trace destroyed). */
-       LTTNG_VIEWER_INDEX_ERR          = 4, /* Unknow error. */
-       LTTNG_VIEWER_INDEX_INACTIVE     = 5, /* Inactive stream beacon. */
-       LTTNG_VIEWER_INDEX_EOF          = 6, /* End of index file. */
-};
-
-enum lttng_viewer_get_packet_return_code {
-       LTTNG_VIEWER_GET_PACKET_OK      = 1,
-       LTTNG_VIEWER_GET_PACKET_RETRY   = 2,
-       LTTNG_VIEWER_GET_PACKET_ERR     = 3,
-       LTTNG_VIEWER_GET_PACKET_EOF     = 4,
-};
-
-enum lttng_viewer_get_metadata_return_code {
-       LTTNG_VIEWER_METADATA_OK        = 1,
-       LTTNG_VIEWER_NO_NEW_METADATA    = 2,
-       LTTNG_VIEWER_METADATA_ERR       = 3,
-};
-
-enum lttng_viewer_connection_type {
-       LTTNG_VIEWER_CLIENT_COMMAND             = 1,
-       LTTNG_VIEWER_CLIENT_NOTIFICATION        = 2,
-};
-
-enum lttng_viewer_seek {
-       /* Receive the trace packets from the beginning. */
-       LTTNG_VIEWER_SEEK_BEGINNING     = 1,
-       /* Receive the trace packets from now. */
-       LTTNG_VIEWER_SEEK_LAST          = 2,
-};
-
-enum lttng_viewer_new_streams_return_code {
-       LTTNG_VIEWER_NEW_STREAMS_OK           = 1, /* If new streams are being sent. */
-       LTTNG_VIEWER_NEW_STREAMS_NO_NEW       = 2, /* If no new streams are available. */
-       LTTNG_VIEWER_NEW_STREAMS_ERR          = 3, /* Error. */
-       LTTNG_VIEWER_NEW_STREAMS_HUP          = 4, /* Session closed. */
-};
-
-enum lttng_viewer_create_session_return_code {
-       LTTNG_VIEWER_CREATE_SESSION_OK          = 1,
-       LTTNG_VIEWER_CREATE_SESSION_ERR         = 2,
-};
-
-enum lttng_viewer_detach_session_return_code {
-       LTTNG_VIEWER_DETACH_SESSION_OK          = 1,
-       LTTNG_VIEWER_DETACH_SESSION_UNK         = 2,
-       LTTNG_VIEWER_DETACH_SESSION_ERR         = 3,
-};
-
-struct lttng_viewer_session {
-       uint64_t id;
-       uint32_t live_timer;
-       uint32_t clients;
-       uint32_t streams;
-       char hostname[LTTNG_VIEWER_HOST_NAME_MAX];
-       char session_name[LTTNG_VIEWER_NAME_MAX];
-} LTTNG_PACKED;
-
-struct lttng_viewer_stream {
-       uint64_t id;
-       uint64_t ctf_trace_id;
-       uint32_t metadata_flag;
-       char path_name[LTTNG_VIEWER_PATH_MAX];
-       char channel_name[LTTNG_VIEWER_NAME_MAX];
-} LTTNG_PACKED;
-
-struct lttng_viewer_cmd {
-       uint64_t data_size;     /* data size following this header */
-       uint32_t cmd;           /* enum lttcomm_relayd_command */
-       uint32_t cmd_version;   /* command version */
-} LTTNG_PACKED;
-
-/*
- * LTTNG_VIEWER_CONNECT payload.
- */
-struct lttng_viewer_connect {
-       /* session ID assigned by the relay for command connections */
-       uint64_t viewer_session_id;
-       uint32_t major;
-       uint32_t minor;
-       uint32_t type;          /* enum lttng_viewer_connection_type */
-} LTTNG_PACKED;
-
-/*
- * LTTNG_VIEWER_LIST_SESSIONS payload.
- */
-struct lttng_viewer_list_sessions {
-       uint32_t sessions_count;
-       char session_list[];    /* struct lttng_viewer_session */
-} LTTNG_PACKED;
-
-/*
- * LTTNG_VIEWER_ATTACH_SESSION payload.
- */
-struct lttng_viewer_attach_session_request {
-       uint64_t session_id;
-       uint64_t offset;        /* unused for now */
-       uint32_t seek;          /* enum lttng_viewer_seek */
-} LTTNG_PACKED;
-
-struct lttng_viewer_attach_session_response {
-       /* enum lttng_viewer_attach_return_code */
-       uint32_t status;
-       uint32_t streams_count;
-       /* struct lttng_viewer_stream */
-       char stream_list[];
-} LTTNG_PACKED;
-
-/*
- * LTTNG_VIEWER_GET_NEXT_INDEX payload.
- */
-struct lttng_viewer_get_next_index {
-       uint64_t stream_id;
-} __attribute__ ((__packed__));
-
-struct lttng_viewer_index {
-       uint64_t offset;
-       uint64_t packet_size;
-       uint64_t content_size;
-       uint64_t timestamp_begin;
-       uint64_t timestamp_end;
-       uint64_t events_discarded;
-       uint64_t stream_id;
-       uint32_t status;        /* enum lttng_viewer_next_index_return_code */
-       uint32_t flags;         /* LTTNG_VIEWER_FLAG_* */
-} __attribute__ ((__packed__));
-
-/*
- * LTTNG_VIEWER_GET_PACKET payload.
- */
-struct lttng_viewer_get_packet {
-       uint64_t stream_id;
-       uint64_t offset;
-       uint32_t len;
-} LTTNG_PACKED;
-
-struct lttng_viewer_trace_packet {
-       uint32_t status;        /* enum lttng_viewer_get_packet_return_code */
-       uint32_t len;
-       uint32_t flags;         /* LTTNG_VIEWER_FLAG_* */
-       char data[];
-} LTTNG_PACKED;
-
-/*
- * LTTNG_VIEWER_GET_METADATA payload.
- */
-struct lttng_viewer_get_metadata {
-       uint64_t stream_id;
-} LTTNG_PACKED;
-
-struct lttng_viewer_metadata_packet {
-       uint64_t len;
-       uint32_t status;        /* enum lttng_viewer_get_metadata_return_code */
-       char data[];
-} LTTNG_PACKED;
-
-/*
- * LTTNG_VIEWER_GET_NEW_STREAMS payload.
- */
-struct lttng_viewer_new_streams_request {
-       uint64_t session_id;
-} LTTNG_PACKED;
-
-struct lttng_viewer_new_streams_response {
-       /* enum lttng_viewer_new_streams_return_code */
-       uint32_t status;
-       uint32_t streams_count;
-       /* struct lttng_viewer_stream */
-       char stream_list[];
-} LTTNG_PACKED;
-
-struct lttng_viewer_create_session_response {
-       /* enum lttng_viewer_create_session_return_code */
-       uint32_t status;
-} LTTNG_PACKED;
-
-/*
- * LTTNG_VIEWER_DETACH_SESSION payload.
- */
-struct lttng_viewer_detach_session_request {
-       uint64_t session_id;
-} LTTNG_PACKED;
-
-struct lttng_viewer_detach_session_response {
-       /* enum lttng_viewer_detach_session_return_code */
-       uint32_t status;
-} LTTNG_PACKED;
-
-#endif /* LTTNG_VIEWER_ABI_H */
diff --git a/src/bin/lttng-relayd/lttng-viewer-abi.hpp b/src/bin/lttng-relayd/lttng-viewer-abi.hpp
new file mode 100644 (file)
index 0000000..6fdb7fa
--- /dev/null
@@ -0,0 +1,240 @@
+#ifndef LTTNG_VIEWER_ABI_H
+#define LTTNG_VIEWER_ABI_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#include <limits.h>
+#include <common/macros.hpp>
+
+#define LTTNG_VIEWER_PATH_MAX          4096
+#define LTTNG_VIEWER_NAME_MAX          255
+#define LTTNG_VIEWER_HOST_NAME_MAX     64
+
+/* Flags in reply to get_next_index and get_packet. */
+enum {
+       /* New metadata is required to read this packet. */
+       LTTNG_VIEWER_FLAG_NEW_METADATA  = (1 << 0),
+       /* New stream got added to the trace. */
+       LTTNG_VIEWER_FLAG_NEW_STREAM    = (1 << 1),
+};
+
+enum lttng_viewer_command {
+       LTTNG_VIEWER_CONNECT            = 1,
+       LTTNG_VIEWER_LIST_SESSIONS      = 2,
+       LTTNG_VIEWER_ATTACH_SESSION     = 3,
+       LTTNG_VIEWER_GET_NEXT_INDEX     = 4,
+       LTTNG_VIEWER_GET_PACKET         = 5,
+       LTTNG_VIEWER_GET_METADATA       = 6,
+       LTTNG_VIEWER_GET_NEW_STREAMS    = 7,
+       LTTNG_VIEWER_CREATE_SESSION     = 8,
+       LTTNG_VIEWER_DETACH_SESSION     = 9,
+};
+
+enum lttng_viewer_attach_return_code {
+       LTTNG_VIEWER_ATTACH_OK          = 1, /* The attach command succeeded. */
+       LTTNG_VIEWER_ATTACH_ALREADY     = 2, /* A viewer is already attached. */
+       LTTNG_VIEWER_ATTACH_UNK         = 3, /* The session ID is unknown. */
+       LTTNG_VIEWER_ATTACH_NOT_LIVE    = 4, /* The session is not live. */
+       LTTNG_VIEWER_ATTACH_SEEK_ERR    = 5, /* Seek error. */
+       LTTNG_VIEWER_ATTACH_NO_SESSION  = 6, /* No viewer session created. */
+};
+
+enum lttng_viewer_next_index_return_code {
+       LTTNG_VIEWER_INDEX_OK           = 1, /* Index is available. */
+       LTTNG_VIEWER_INDEX_RETRY        = 2, /* Index not yet available. */
+       LTTNG_VIEWER_INDEX_HUP          = 3, /* Index closed (trace destroyed). */
+       LTTNG_VIEWER_INDEX_ERR          = 4, /* Unknow error. */
+       LTTNG_VIEWER_INDEX_INACTIVE     = 5, /* Inactive stream beacon. */
+       LTTNG_VIEWER_INDEX_EOF          = 6, /* End of index file. */
+};
+
+enum lttng_viewer_get_packet_return_code {
+       LTTNG_VIEWER_GET_PACKET_OK      = 1,
+       LTTNG_VIEWER_GET_PACKET_RETRY   = 2,
+       LTTNG_VIEWER_GET_PACKET_ERR     = 3,
+       LTTNG_VIEWER_GET_PACKET_EOF     = 4,
+};
+
+enum lttng_viewer_get_metadata_return_code {
+       LTTNG_VIEWER_METADATA_OK        = 1,
+       LTTNG_VIEWER_NO_NEW_METADATA    = 2,
+       LTTNG_VIEWER_METADATA_ERR       = 3,
+};
+
+enum lttng_viewer_connection_type {
+       LTTNG_VIEWER_CLIENT_COMMAND             = 1,
+       LTTNG_VIEWER_CLIENT_NOTIFICATION        = 2,
+};
+
+enum lttng_viewer_seek {
+       /* Receive the trace packets from the beginning. */
+       LTTNG_VIEWER_SEEK_BEGINNING     = 1,
+       /* Receive the trace packets from now. */
+       LTTNG_VIEWER_SEEK_LAST          = 2,
+};
+
+enum lttng_viewer_new_streams_return_code {
+       LTTNG_VIEWER_NEW_STREAMS_OK           = 1, /* If new streams are being sent. */
+       LTTNG_VIEWER_NEW_STREAMS_NO_NEW       = 2, /* If no new streams are available. */
+       LTTNG_VIEWER_NEW_STREAMS_ERR          = 3, /* Error. */
+       LTTNG_VIEWER_NEW_STREAMS_HUP          = 4, /* Session closed. */
+};
+
+enum lttng_viewer_create_session_return_code {
+       LTTNG_VIEWER_CREATE_SESSION_OK          = 1,
+       LTTNG_VIEWER_CREATE_SESSION_ERR         = 2,
+};
+
+enum lttng_viewer_detach_session_return_code {
+       LTTNG_VIEWER_DETACH_SESSION_OK          = 1,
+       LTTNG_VIEWER_DETACH_SESSION_UNK         = 2,
+       LTTNG_VIEWER_DETACH_SESSION_ERR         = 3,
+};
+
+struct lttng_viewer_session {
+       uint64_t id;
+       uint32_t live_timer;
+       uint32_t clients;
+       uint32_t streams;
+       char hostname[LTTNG_VIEWER_HOST_NAME_MAX];
+       char session_name[LTTNG_VIEWER_NAME_MAX];
+} LTTNG_PACKED;
+
+struct lttng_viewer_stream {
+       uint64_t id;
+       uint64_t ctf_trace_id;
+       uint32_t metadata_flag;
+       char path_name[LTTNG_VIEWER_PATH_MAX];
+       char channel_name[LTTNG_VIEWER_NAME_MAX];
+} LTTNG_PACKED;
+
+struct lttng_viewer_cmd {
+       uint64_t data_size;     /* data size following this header */
+       uint32_t cmd;           /* enum lttcomm_relayd_command */
+       uint32_t cmd_version;   /* command version */
+} LTTNG_PACKED;
+
+/*
+ * LTTNG_VIEWER_CONNECT payload.
+ */
+struct lttng_viewer_connect {
+       /* session ID assigned by the relay for command connections */
+       uint64_t viewer_session_id;
+       uint32_t major;
+       uint32_t minor;
+       uint32_t type;          /* enum lttng_viewer_connection_type */
+} LTTNG_PACKED;
+
+/*
+ * LTTNG_VIEWER_LIST_SESSIONS payload.
+ */
+struct lttng_viewer_list_sessions {
+       uint32_t sessions_count;
+       char session_list[];    /* struct lttng_viewer_session */
+} LTTNG_PACKED;
+
+/*
+ * LTTNG_VIEWER_ATTACH_SESSION payload.
+ */
+struct lttng_viewer_attach_session_request {
+       uint64_t session_id;
+       uint64_t offset;        /* unused for now */
+       uint32_t seek;          /* enum lttng_viewer_seek */
+} LTTNG_PACKED;
+
+struct lttng_viewer_attach_session_response {
+       /* enum lttng_viewer_attach_return_code */
+       uint32_t status;
+       uint32_t streams_count;
+       /* struct lttng_viewer_stream */
+       char stream_list[];
+} LTTNG_PACKED;
+
+/*
+ * LTTNG_VIEWER_GET_NEXT_INDEX payload.
+ */
+struct lttng_viewer_get_next_index {
+       uint64_t stream_id;
+} __attribute__ ((__packed__));
+
+struct lttng_viewer_index {
+       uint64_t offset;
+       uint64_t packet_size;
+       uint64_t content_size;
+       uint64_t timestamp_begin;
+       uint64_t timestamp_end;
+       uint64_t events_discarded;
+       uint64_t stream_id;
+       uint32_t status;        /* enum lttng_viewer_next_index_return_code */
+       uint32_t flags;         /* LTTNG_VIEWER_FLAG_* */
+} __attribute__ ((__packed__));
+
+/*
+ * LTTNG_VIEWER_GET_PACKET payload.
+ */
+struct lttng_viewer_get_packet {
+       uint64_t stream_id;
+       uint64_t offset;
+       uint32_t len;
+} LTTNG_PACKED;
+
+struct lttng_viewer_trace_packet {
+       uint32_t status;        /* enum lttng_viewer_get_packet_return_code */
+       uint32_t len;
+       uint32_t flags;         /* LTTNG_VIEWER_FLAG_* */
+       char data[];
+} LTTNG_PACKED;
+
+/*
+ * LTTNG_VIEWER_GET_METADATA payload.
+ */
+struct lttng_viewer_get_metadata {
+       uint64_t stream_id;
+} LTTNG_PACKED;
+
+struct lttng_viewer_metadata_packet {
+       uint64_t len;
+       uint32_t status;        /* enum lttng_viewer_get_metadata_return_code */
+       char data[];
+} LTTNG_PACKED;
+
+/*
+ * LTTNG_VIEWER_GET_NEW_STREAMS payload.
+ */
+struct lttng_viewer_new_streams_request {
+       uint64_t session_id;
+} LTTNG_PACKED;
+
+struct lttng_viewer_new_streams_response {
+       /* enum lttng_viewer_new_streams_return_code */
+       uint32_t status;
+       uint32_t streams_count;
+       /* struct lttng_viewer_stream */
+       char stream_list[];
+} LTTNG_PACKED;
+
+struct lttng_viewer_create_session_response {
+       /* enum lttng_viewer_create_session_return_code */
+       uint32_t status;
+} LTTNG_PACKED;
+
+/*
+ * LTTNG_VIEWER_DETACH_SESSION payload.
+ */
+struct lttng_viewer_detach_session_request {
+       uint64_t session_id;
+} LTTNG_PACKED;
+
+struct lttng_viewer_detach_session_response {
+       /* enum lttng_viewer_detach_session_return_code */
+       uint32_t status;
+} LTTNG_PACKED;
+
+#endif /* LTTNG_VIEWER_ABI_H */
index d3f8b3c9e30234a98eed30f49831028a3f9a99bf..126e7574ac06c9e4ef79ddc64cc5194db0056629 100644 (file)
 #include <algorithm>
 
 #include <lttng/lttng.h>
-#include <common/common.h>
-#include <common/compat/poll.h>
-#include <common/compat/socket.h>
-#include <common/compat/endian.h>
-#include <common/compat/getenv.h>
-#include <common/defaults.h>
-#include <common/daemonize.h>
-#include <common/futex.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/sessiond-comm/inet.h>
-#include <common/sessiond-comm/relayd.h>
-#include <common/uri.h>
-#include <common/utils.h>
-#include <common/align.h>
-#include <common/ini-config/ini-config.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <common/string-utils/format.h>
-#include <common/fd-tracker/fd-tracker.h>
-#include <common/fd-tracker/utils.h>
-
-#include "backward-compatibility-group-by.h"
-#include "cmd.h"
-#include "connection.h"
-#include "ctf-trace.h"
-#include "health-relayd.h"
-#include "index.h"
-#include "live.h"
-#include "lttng-relayd.h"
-#include "session.h"
-#include "sessiond-trace-chunks.h"
-#include "stream.h"
-#include "tcp_keep_alive.h"
-#include "testpoint.h"
-#include "tracefile-array.h"
-#include "utils.h"
-#include "version.h"
-#include "viewer-stream.h"
+#include <common/common.hpp>
+#include <common/compat/poll.hpp>
+#include <common/compat/socket.hpp>
+#include <common/compat/endian.hpp>
+#include <common/compat/getenv.hpp>
+#include <common/defaults.hpp>
+#include <common/daemonize.hpp>
+#include <common/futex.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/sessiond-comm/inet.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/uri.hpp>
+#include <common/utils.hpp>
+#include <common/align.hpp>
+#include <common/ini-config/ini-config.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/buffer-view.hpp>
+#include <common/string-utils/format.hpp>
+#include <common/fd-tracker/fd-tracker.hpp>
+#include <common/fd-tracker/utils.hpp>
+
+#include "backward-compatibility-group-by.hpp"
+#include "cmd.hpp"
+#include "connection.hpp"
+#include "ctf-trace.hpp"
+#include "health-relayd.hpp"
+#include "index.hpp"
+#include "live.hpp"
+#include "lttng-relayd.hpp"
+#include "session.hpp"
+#include "sessiond-trace-chunks.hpp"
+#include "stream.hpp"
+#include "tcp_keep_alive.hpp"
+#include "testpoint.hpp"
+#include "tracefile-array.hpp"
+#include "utils.hpp"
+#include "version.hpp"
+#include "viewer-stream.hpp"
 
 static const char *help_msg =
 #ifdef LTTNG_EMBED_HELP
index 5fa39663a5a63fc80fbc024509278d88aea988f0..3de1fad446e2629ffc53289dddae444bed215d32 100644 (file)
@@ -8,23 +8,23 @@
  */
 
 #define _LGPL_SOURCE
-#include <common/common.h>
-#include <common/compat/path.h>
-#include <common/fd-tracker/utils.h>
-#include <common/time.h>
-#include <common/utils.h>
-#include <common/uuid.h>
+#include <common/common.hpp>
+#include <common/compat/path.hpp>
+#include <common/fd-tracker/utils.hpp>
+#include <common/time.hpp>
+#include <common/utils.hpp>
+#include <common/uuid.hpp>
 #include <urcu/rculist.h>
 
 #include <sys/stat.h>
 
-#include "ctf-trace.h"
-#include "lttng-relayd.h"
-#include "session.h"
-#include "sessiond-trace-chunks.h"
-#include "stream.h"
-#include <common/defaults.h>
-#include "utils.h"
+#include "ctf-trace.hpp"
+#include "lttng-relayd.hpp"
+#include "session.hpp"
+#include "sessiond-trace-chunks.hpp"
+#include "stream.hpp"
+#include <common/defaults.hpp>
+#include "utils.hpp"
 
 /* Global session id used in the session creation. */
 static uint64_t last_relay_session_id;
diff --git a/src/bin/lttng-relayd/session.h b/src/bin/lttng-relayd/session.h
deleted file mode 100644 (file)
index 3a9b924..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-#ifndef _SESSION_H
-#define _SESSION_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <limits.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <urcu/list.h>
-#include <urcu/ref.h>
-
-#include <lttng/constant.h>
-#include <common/hashtable/hashtable.h>
-#include <common/uuid.h>
-#include <common/trace-chunk.h>
-#include <common/optional.h>
-
-/*
- * Represents a session for the relay point of view
- */
-struct relay_session {
-       /*
-        * This session id is generated by the relay daemon to guarantee
-        * its uniqueness even when serving multiple session daemons.
-        * It is used to match a set of streams to their session.
-        */
-       uint64_t id;
-       /*
-        * ID of the session in the session daemon's domain.
-        * This information is only provided by 2.11+ peers.
-        */
-       LTTNG_OPTIONAL(uint64_t) id_sessiond;
-       /*
-        * Only provided by 2.11+ peers. However, the UUID is set to 'nil' in
-        * the other cases.
-        */
-       lttng_uuid sessiond_uuid;
-       /*
-        * Contains the creation time on the session daemon's end for 2.11+
-        * peers. Otherwise, this contains the session creation time on the
-        * relay daemon's end.
-        */
-       LTTNG_OPTIONAL(time_t) creation_time;
-       /* Must _not_ be empty for 2.4+ peers. */
-       char session_name[LTTNG_NAME_MAX];
-       char hostname[LTTNG_HOST_NAME_MAX];
-       char base_path[LTTNG_PATH_MAX];
-       /*
-        * Session output path relative to relayd's output path.
-        * Will be empty when interacting with peers < 2.11 since their
-        * streams' path are expressed relative to the relay daemon's
-        * output path.
-        */
-       char output_path[LTTNG_PATH_MAX];
-       uint32_t live_timer;
-
-       /* Session in snapshot mode. */
-       bool snapshot;
-
-       /*
-        * Session has no back reference to its connection because it
-        * has a life-time that can be longer than the consumer connection's
-        * life-time; a reference can still be held by the viewer
-        * connection through the viewer streams.
-        */
-
-       struct urcu_ref ref;
-
-       pthread_mutex_t lock;
-
-       /* major/minor version used for this session. */
-       uint32_t major;
-       uint32_t minor;
-
-       bool viewer_attached;
-       /* Tell if the session connection has been closed on the streaming side. */
-       bool connection_closed;
-
-       /*
-        * Tell if the session is currently living in a exiting relayd and
-        * should be cleaned forcefully without waiting for pending data or
-        * pending ctrl data.
-        */
-       bool aborted;
-
-       bool session_name_contains_creation_time;
-       /* Whether session has performed an explicit rotation. */
-       bool has_rotated;
-
-       /* Contains ctf_trace object of that session indexed by path name. */
-       struct lttng_ht *ctf_traces_ht;
-
-       /*
-        * This contains streams that are received on that connection.
-        * It's used to store them until we get the streams sent
-        * command. When this is received, we remove those streams from
-        * the list and publish them.
-        *
-        * Updates are protected by the recv_list_lock.
-        * Traversals are protected by RCU.
-        * recv_list_lock also protects stream_count.
-        */
-       struct cds_list_head recv_list; /* RCU list. */
-       uint32_t stream_count;
-       pthread_mutex_t recv_list_lock;
-
-       /*
-        * Flag checked and exchanged with uatomic_cmpxchg to tell the
-        * viewer-side if new streams got added since the last check.
-        */
-       unsigned long new_streams;
-
-       /*
-        * Node in the global session hash table.
-        */
-       struct lttng_ht_node_u64 session_n;
-       /*
-        * Member of the session list in struct relay_viewer_session.
-        * Updates are protected by the relay_viewer_session
-        * session_list_lock. Traversals are protected by RCU.
-        */
-       struct cds_list_head viewer_session_node;
-       struct lttng_trace_chunk *current_trace_chunk;
-       struct lttng_trace_chunk *pending_closure_trace_chunk;
-       /*
-        * Prevent live viewers from taking of copy of the chunk
-        * while new chunk has a temporary directory name.
-        */
-       bool ongoing_rotation;
-       struct lttng_directory_handle *output_directory;
-       struct rcu_head rcu_node;       /* For call_rcu teardown. */
-};
-
-struct relay_session *session_create(const char *session_name,
-               const char *hostname, const char *base_path,
-               uint32_t live_timer,
-               bool snapshot,
-               const lttng_uuid sessiond_uuid,
-               const uint64_t *id_sessiond,
-               const uint64_t *current_chunk_id,
-               const time_t *creation_time,
-               uint32_t major,
-               uint32_t minor,
-               bool session_name_contains_creation_timestamp);
-struct relay_session *session_get_by_id(uint64_t id);
-bool session_get(struct relay_session *session);
-void session_put(struct relay_session *session);
-
-int session_close(struct relay_session *session);
-int session_abort(struct relay_session *session);
-
-void print_sessions(void);
-
-#endif /* _SESSION_H */
diff --git a/src/bin/lttng-relayd/session.hpp b/src/bin/lttng-relayd/session.hpp
new file mode 100644 (file)
index 0000000..56518b2
--- /dev/null
@@ -0,0 +1,161 @@
+#ifndef _SESSION_H
+#define _SESSION_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <limits.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <urcu/list.h>
+#include <urcu/ref.h>
+
+#include <lttng/constant.h>
+#include <common/hashtable/hashtable.hpp>
+#include <common/uuid.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/optional.hpp>
+
+/*
+ * Represents a session for the relay point of view
+ */
+struct relay_session {
+       /*
+        * This session id is generated by the relay daemon to guarantee
+        * its uniqueness even when serving multiple session daemons.
+        * It is used to match a set of streams to their session.
+        */
+       uint64_t id;
+       /*
+        * ID of the session in the session daemon's domain.
+        * This information is only provided by 2.11+ peers.
+        */
+       LTTNG_OPTIONAL(uint64_t) id_sessiond;
+       /*
+        * Only provided by 2.11+ peers. However, the UUID is set to 'nil' in
+        * the other cases.
+        */
+       lttng_uuid sessiond_uuid;
+       /*
+        * Contains the creation time on the session daemon's end for 2.11+
+        * peers. Otherwise, this contains the session creation time on the
+        * relay daemon's end.
+        */
+       LTTNG_OPTIONAL(time_t) creation_time;
+       /* Must _not_ be empty for 2.4+ peers. */
+       char session_name[LTTNG_NAME_MAX];
+       char hostname[LTTNG_HOST_NAME_MAX];
+       char base_path[LTTNG_PATH_MAX];
+       /*
+        * Session output path relative to relayd's output path.
+        * Will be empty when interacting with peers < 2.11 since their
+        * streams' path are expressed relative to the relay daemon's
+        * output path.
+        */
+       char output_path[LTTNG_PATH_MAX];
+       uint32_t live_timer;
+
+       /* Session in snapshot mode. */
+       bool snapshot;
+
+       /*
+        * Session has no back reference to its connection because it
+        * has a life-time that can be longer than the consumer connection's
+        * life-time; a reference can still be held by the viewer
+        * connection through the viewer streams.
+        */
+
+       struct urcu_ref ref;
+
+       pthread_mutex_t lock;
+
+       /* major/minor version used for this session. */
+       uint32_t major;
+       uint32_t minor;
+
+       bool viewer_attached;
+       /* Tell if the session connection has been closed on the streaming side. */
+       bool connection_closed;
+
+       /*
+        * Tell if the session is currently living in a exiting relayd and
+        * should be cleaned forcefully without waiting for pending data or
+        * pending ctrl data.
+        */
+       bool aborted;
+
+       bool session_name_contains_creation_time;
+       /* Whether session has performed an explicit rotation. */
+       bool has_rotated;
+
+       /* Contains ctf_trace object of that session indexed by path name. */
+       struct lttng_ht *ctf_traces_ht;
+
+       /*
+        * This contains streams that are received on that connection.
+        * It's used to store them until we get the streams sent
+        * command. When this is received, we remove those streams from
+        * the list and publish them.
+        *
+        * Updates are protected by the recv_list_lock.
+        * Traversals are protected by RCU.
+        * recv_list_lock also protects stream_count.
+        */
+       struct cds_list_head recv_list; /* RCU list. */
+       uint32_t stream_count;
+       pthread_mutex_t recv_list_lock;
+
+       /*
+        * Flag checked and exchanged with uatomic_cmpxchg to tell the
+        * viewer-side if new streams got added since the last check.
+        */
+       unsigned long new_streams;
+
+       /*
+        * Node in the global session hash table.
+        */
+       struct lttng_ht_node_u64 session_n;
+       /*
+        * Member of the session list in struct relay_viewer_session.
+        * Updates are protected by the relay_viewer_session
+        * session_list_lock. Traversals are protected by RCU.
+        */
+       struct cds_list_head viewer_session_node;
+       struct lttng_trace_chunk *current_trace_chunk;
+       struct lttng_trace_chunk *pending_closure_trace_chunk;
+       /*
+        * Prevent live viewers from taking of copy of the chunk
+        * while new chunk has a temporary directory name.
+        */
+       bool ongoing_rotation;
+       struct lttng_directory_handle *output_directory;
+       struct rcu_head rcu_node;       /* For call_rcu teardown. */
+};
+
+struct relay_session *session_create(const char *session_name,
+               const char *hostname, const char *base_path,
+               uint32_t live_timer,
+               bool snapshot,
+               const lttng_uuid sessiond_uuid,
+               const uint64_t *id_sessiond,
+               const uint64_t *current_chunk_id,
+               const time_t *creation_time,
+               uint32_t major,
+               uint32_t minor,
+               bool session_name_contains_creation_timestamp);
+struct relay_session *session_get_by_id(uint64_t id);
+bool session_get(struct relay_session *session);
+void session_put(struct relay_session *session);
+
+int session_close(struct relay_session *session);
+int session_abort(struct relay_session *session);
+
+void print_sessions(void);
+
+#endif /* _SESSION_H */
index e0c46e34ad4a7436e344b178a1302bd9fd06c64b..c638302600979154950ef0687a6ad65df26d136c 100644 (file)
@@ -5,17 +5,17 @@
  *
  */
 
-#include "sessiond-trace-chunks.h"
+#include "sessiond-trace-chunks.hpp"
 #include <urcu.h>
 #include <urcu/rculfhash.h>
 #include <urcu/ref.h>
-#include <common/macros.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/trace-chunk-registry.h>
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/string-utils/format.h>
+#include <common/macros.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/trace-chunk-registry.hpp>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/string-utils/format.hpp>
 #include <stdio.h>
 #include <inttypes.h>
 
diff --git a/src/bin/lttng-relayd/sessiond-trace-chunks.h b/src/bin/lttng-relayd/sessiond-trace-chunks.h
deleted file mode 100644 (file)
index f2bc5a3..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SESSIOND_TRACE_CHUNK_REGISTRY_H
-#define SESSIOND_TRACE_CHUNK_REGISTRY_H
-
-#include <common/uuid.h>
-#include <common/trace-chunk.h>
-#include <stdint.h>
-
-struct sessiond_trace_chunk_registry;
-
-struct sessiond_trace_chunk_registry *
-sessiond_trace_chunk_registry_create(void);
-
-void sessiond_trace_chunk_registry_destroy(
-               struct sessiond_trace_chunk_registry *sessiond_registry);
-
-int sessiond_trace_chunk_registry_session_created(
-               struct sessiond_trace_chunk_registry *sessiond_registry,
-               const lttng_uuid sessiond_uuid);
-
-int sessiond_trace_chunk_registry_session_destroyed(
-               struct sessiond_trace_chunk_registry *sessiond_registry,
-               const lttng_uuid sessiond_uuid);
-
-struct lttng_trace_chunk *sessiond_trace_chunk_registry_publish_chunk(
-               struct sessiond_trace_chunk_registry *sessiond_registry,
-               const lttng_uuid sessiond_uuid, uint64_t session_id,
-               struct lttng_trace_chunk *chunk);
-
-struct lttng_trace_chunk *
-sessiond_trace_chunk_registry_get_anonymous_chunk(
-               struct sessiond_trace_chunk_registry *sessiond_registry,
-               const lttng_uuid sessiond_uuid,
-               uint64_t session_id);
-
-struct lttng_trace_chunk *
-sessiond_trace_chunk_registry_get_chunk(
-               struct sessiond_trace_chunk_registry *sessiond_registry,
-               const lttng_uuid sessiond_uuid,
-               uint64_t session_id, uint64_t chunk_id);
-
-int sessiond_trace_chunk_registry_chunk_exists(
-               struct sessiond_trace_chunk_registry *sessiond_registry,
-               const lttng_uuid sessiond_uuid,
-               uint64_t session_id, uint64_t chunk_id, bool *chunk_exists);
-
-#endif /* SESSIOND_TRACE_CHUNK_REGISTRY_H */
diff --git a/src/bin/lttng-relayd/sessiond-trace-chunks.hpp b/src/bin/lttng-relayd/sessiond-trace-chunks.hpp
new file mode 100644 (file)
index 0000000..e3200e1
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SESSIOND_TRACE_CHUNK_REGISTRY_H
+#define SESSIOND_TRACE_CHUNK_REGISTRY_H
+
+#include <common/uuid.hpp>
+#include <common/trace-chunk.hpp>
+#include <stdint.h>
+
+struct sessiond_trace_chunk_registry;
+
+struct sessiond_trace_chunk_registry *
+sessiond_trace_chunk_registry_create(void);
+
+void sessiond_trace_chunk_registry_destroy(
+               struct sessiond_trace_chunk_registry *sessiond_registry);
+
+int sessiond_trace_chunk_registry_session_created(
+               struct sessiond_trace_chunk_registry *sessiond_registry,
+               const lttng_uuid sessiond_uuid);
+
+int sessiond_trace_chunk_registry_session_destroyed(
+               struct sessiond_trace_chunk_registry *sessiond_registry,
+               const lttng_uuid sessiond_uuid);
+
+struct lttng_trace_chunk *sessiond_trace_chunk_registry_publish_chunk(
+               struct sessiond_trace_chunk_registry *sessiond_registry,
+               const lttng_uuid sessiond_uuid, uint64_t session_id,
+               struct lttng_trace_chunk *chunk);
+
+struct lttng_trace_chunk *
+sessiond_trace_chunk_registry_get_anonymous_chunk(
+               struct sessiond_trace_chunk_registry *sessiond_registry,
+               const lttng_uuid sessiond_uuid,
+               uint64_t session_id);
+
+struct lttng_trace_chunk *
+sessiond_trace_chunk_registry_get_chunk(
+               struct sessiond_trace_chunk_registry *sessiond_registry,
+               const lttng_uuid sessiond_uuid,
+               uint64_t session_id, uint64_t chunk_id);
+
+int sessiond_trace_chunk_registry_chunk_exists(
+               struct sessiond_trace_chunk_registry *sessiond_registry,
+               const lttng_uuid sessiond_uuid,
+               uint64_t session_id, uint64_t chunk_id, bool *chunk_exists);
+
+#endif /* SESSIOND_TRACE_CHUNK_REGISTRY_H */
index b57c061c571b41fea32997d5c778eabee233764c..b05d7eb3a3590181de9afac196f40b58c54d4be9 100644 (file)
 
 #define _LGPL_SOURCE
 #include <algorithm>
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/fs-handle.h>
-#include <common/sessiond-comm/relayd.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/fs-handle.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/utils.hpp>
 #include <sys/stat.h>
 #include <urcu/rculist.h>
 
-#include "lttng-relayd.h"
-#include "index.h"
-#include "stream.h"
-#include "viewer-stream.h"
+#include "lttng-relayd.hpp"
+#include "index.hpp"
+#include "stream.hpp"
+#include "viewer-stream.hpp"
 
 #include <sys/types.h>
 #include <fcntl.h>
diff --git a/src/bin/lttng-relayd/stream.h b/src/bin/lttng-relayd/stream.h
deleted file mode 100644 (file)
index c64b180..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-#ifndef _STREAM_H
-#define _STREAM_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <limits.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <urcu/list.h>
-
-#include <common/hashtable/hashtable.h>
-#include <common/trace-chunk.h>
-#include <common/optional.h>
-#include <common/buffer-view.h>
-
-#include "session.h"
-#include "tracefile-array.h"
-
-struct lttcomm_relayd_index;
-
-struct relay_stream_rotation {
-       /*
-        * Indicates if the stream's data and index have been rotated. A
-        * rotation is considered completed when both rotations have occurred.
-        */
-       bool data_rotated;
-       bool index_rotated;
-       /*
-        * Packet sequence number of the first packet of the new trace chunk to
-        * which the stream is rotating.
-        */
-       uint64_t packet_seq_num;
-       /*
-        * Monotonically increasing previous network sequence number of first
-        * data packet of the new trace chunk to which the stream is rotating.
-        */
-       uint64_t prev_data_net_seq;
-       struct lttng_trace_chunk *next_trace_chunk;
-};
-
-/*
- * Represents a stream in the relay
- */
-struct relay_stream {
-       uint64_t stream_handle;
-
-       struct urcu_ref ref;
-       /* Back reference to trace. Protected by refcount on trace object. */
-       struct ctf_trace *trace;
-
-       /*
-        * To protect from concurrent read/update. The viewer stream
-        * lock nests inside the stream lock. The stream lock nests
-        * inside the ctf_trace lock.
-        */
-       pthread_mutex_t lock;
-       /* previous data sequence number written to disk. */
-       uint64_t prev_data_seq;
-       /* previous index sequence number written to disk. */
-       uint64_t prev_index_seq;
-       /* seq num to encounter before closing. */
-       uint64_t last_net_seq_num;
-
-       struct fs_handle *file;
-       /* index file on which to write the index data. */
-       struct lttng_index_file *index_file;
-
-       char *path_name;
-       char *channel_name;
-
-       /* On-disk circular buffer of tracefiles. */
-       uint64_t tracefile_size;
-       uint64_t tracefile_size_current;
-       /* Max number of trace files for this stream. */
-       uint64_t tracefile_count;
-       /*
-        * Index of the currently active file for this stream's on-disk
-        * ring buffer.
-        */
-       uint64_t tracefile_current_index;
-       /*
-        * Indicates that the on-disk buffer has wrapped around. Stream
-        * files shall be unlinked before being opened after this has occurred.
-        */
-       bool tracefile_wrapped_around;
-
-       /*
-        * Position in the tracefile where we have the full index also on disk.
-        */
-       uint64_t pos_after_last_complete_data_index;
-
-       /*
-        * Counts the number of received indexes. The "tag" associated
-        * with an index is taken before incrementing this seqcount.
-        * Therefore, the sequence tag associated with the last index
-        * received is always index_received_seqcount - 1.
-        */
-       uint64_t index_received_seqcount;
-
-       /*
-        * Packet sequence number of the last received packet index.
-        * Only populated when interacting with CTF_INDEX 1.1+.
-        */
-       LTTNG_OPTIONAL(uint64_t) received_packet_seq_num;
-
-       /*
-        * Tracefile array is an index of the stream trace files,
-        * indexed by position. It allows keeping track of the oldest
-        * available indexes when overwriting trace files in tracefile
-        * rotation.
-        */
-       struct tracefile_array *tfa;
-
-       bool closed;            /* Stream is closed. */
-       bool close_requested;   /* Close command has been received. */
-
-       /*
-        * Counts number of indexes in indexes_ht. Redundant info.
-        * Protected by stream lock.
-        */
-       int indexes_in_flight;
-       struct lttng_ht *indexes_ht;
-
-       /*
-        * If the stream is inactive, this field is updated with the
-        * live beacon timestamp end, when it is active, this
-        * field == -1ULL.
-        */
-       uint64_t beacon_ts_end;
-
-       /* CTF stream ID, -1ULL when unset (first packet not received yet). */
-       uint64_t ctf_stream_id;
-
-       /* Indicate if the stream was initialized for a data pending command. */
-       bool data_pending_check_done;
-
-       /* Is this stream a metadata stream ? */
-       bool is_metadata;
-       /* Amount of metadata received (bytes). */
-       uint64_t metadata_received;
-
-       /*
-        * Member of the stream list in struct ctf_trace.
-        * Updates are protected by the stream_list_lock.
-        * Traversals are protected by RCU.
-        */
-       struct cds_list_head stream_node;
-       /*
-        * Temporary list belonging to the connection until all streams
-        * are received for that connection.
-        * Member of the stream recv list in the connection.
-        * Updates are protected by the stream_recv_list_lock.
-        * Traversals are protected by RCU.
-        */
-       bool in_recv_list;
-       struct cds_list_head recv_node;
-       /* Protected by session lock. */
-       bool published;
-       /* Notified viewer that no new metadata is available. */
-       bool no_new_metadata_notified;
-       /*
-        * Node of stream within global stream hash table.
-        */
-       struct lttng_ht_node_u64 node;
-       bool in_stream_ht;              /* is stream in stream hash table. */
-       struct rcu_head rcu_node;       /* For call_rcu teardown. */
-       /*
-        * The trace chunk to which the file currently being produced (if any)
-        * belongs.
-        *
-        * Note that a relay stream can have no output trace chunk. For
-        * instance, after a session stop followed by a session clear,
-        * streams will not have an output trace chunk until the session
-        * is resumed.
-        */
-       struct lttng_trace_chunk *trace_chunk;
-       LTTNG_OPTIONAL(struct relay_stream_rotation) ongoing_rotation;
-       uint64_t completed_rotation_count;
-};
-
-struct relay_stream *stream_create(struct ctf_trace *trace,
-       uint64_t stream_handle, char *path_name,
-       char *channel_name, uint64_t tracefile_size,
-       uint64_t tracefile_count);
-
-struct relay_stream *stream_get_by_id(uint64_t stream_id);
-bool stream_get(struct relay_stream *stream);
-void stream_put(struct relay_stream *stream);
-int stream_rotate_output_files(struct relay_session *session,
-               struct relay_stream *stream);
-int stream_set_pending_rotation(struct relay_stream *stream,
-               struct lttng_trace_chunk *next_trace_chunk,
-               uint64_t rotation_sequence_number);
-void try_stream_close(struct relay_stream *stream);
-void stream_publish(struct relay_stream *stream);
-int stream_init_packet(struct relay_stream *stream, size_t packet_size,
-               bool *file_rotated);
-int stream_write(struct relay_stream *stream,
-               const struct lttng_buffer_view *packet, size_t padding_len);
-/* Called after the reception of a complete data packet. */
-int stream_update_index(struct relay_stream *stream, uint64_t net_seq_num,
-               bool rotate_index, bool *flushed, uint64_t total_size);
-int stream_complete_packet(struct relay_stream *stream,
-               size_t packet_total_size, uint64_t sequence_number,
-               bool index_flushed);
-/* Index info is in host endianness. */
-int stream_add_index(struct relay_stream *stream,
-               const struct lttcomm_relayd_index *index_info);
-int stream_reset_file(struct relay_stream *stream);
-
-void print_relay_streams(void);
-
-#endif /* _STREAM_H */
diff --git a/src/bin/lttng-relayd/stream.hpp b/src/bin/lttng-relayd/stream.hpp
new file mode 100644 (file)
index 0000000..6e09c55
--- /dev/null
@@ -0,0 +1,220 @@
+#ifndef _STREAM_H
+#define _STREAM_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <limits.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <urcu/list.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/optional.hpp>
+#include <common/buffer-view.hpp>
+
+#include "session.hpp"
+#include "tracefile-array.hpp"
+
+struct lttcomm_relayd_index;
+
+struct relay_stream_rotation {
+       /*
+        * Indicates if the stream's data and index have been rotated. A
+        * rotation is considered completed when both rotations have occurred.
+        */
+       bool data_rotated;
+       bool index_rotated;
+       /*
+        * Packet sequence number of the first packet of the new trace chunk to
+        * which the stream is rotating.
+        */
+       uint64_t packet_seq_num;
+       /*
+        * Monotonically increasing previous network sequence number of first
+        * data packet of the new trace chunk to which the stream is rotating.
+        */
+       uint64_t prev_data_net_seq;
+       struct lttng_trace_chunk *next_trace_chunk;
+};
+
+/*
+ * Represents a stream in the relay
+ */
+struct relay_stream {
+       uint64_t stream_handle;
+
+       struct urcu_ref ref;
+       /* Back reference to trace. Protected by refcount on trace object. */
+       struct ctf_trace *trace;
+
+       /*
+        * To protect from concurrent read/update. The viewer stream
+        * lock nests inside the stream lock. The stream lock nests
+        * inside the ctf_trace lock.
+        */
+       pthread_mutex_t lock;
+       /* previous data sequence number written to disk. */
+       uint64_t prev_data_seq;
+       /* previous index sequence number written to disk. */
+       uint64_t prev_index_seq;
+       /* seq num to encounter before closing. */
+       uint64_t last_net_seq_num;
+
+       struct fs_handle *file;
+       /* index file on which to write the index data. */
+       struct lttng_index_file *index_file;
+
+       char *path_name;
+       char *channel_name;
+
+       /* On-disk circular buffer of tracefiles. */
+       uint64_t tracefile_size;
+       uint64_t tracefile_size_current;
+       /* Max number of trace files for this stream. */
+       uint64_t tracefile_count;
+       /*
+        * Index of the currently active file for this stream's on-disk
+        * ring buffer.
+        */
+       uint64_t tracefile_current_index;
+       /*
+        * Indicates that the on-disk buffer has wrapped around. Stream
+        * files shall be unlinked before being opened after this has occurred.
+        */
+       bool tracefile_wrapped_around;
+
+       /*
+        * Position in the tracefile where we have the full index also on disk.
+        */
+       uint64_t pos_after_last_complete_data_index;
+
+       /*
+        * Counts the number of received indexes. The "tag" associated
+        * with an index is taken before incrementing this seqcount.
+        * Therefore, the sequence tag associated with the last index
+        * received is always index_received_seqcount - 1.
+        */
+       uint64_t index_received_seqcount;
+
+       /*
+        * Packet sequence number of the last received packet index.
+        * Only populated when interacting with CTF_INDEX 1.1+.
+        */
+       LTTNG_OPTIONAL(uint64_t) received_packet_seq_num;
+
+       /*
+        * Tracefile array is an index of the stream trace files,
+        * indexed by position. It allows keeping track of the oldest
+        * available indexes when overwriting trace files in tracefile
+        * rotation.
+        */
+       struct tracefile_array *tfa;
+
+       bool closed;            /* Stream is closed. */
+       bool close_requested;   /* Close command has been received. */
+
+       /*
+        * Counts number of indexes in indexes_ht. Redundant info.
+        * Protected by stream lock.
+        */
+       int indexes_in_flight;
+       struct lttng_ht *indexes_ht;
+
+       /*
+        * If the stream is inactive, this field is updated with the
+        * live beacon timestamp end, when it is active, this
+        * field == -1ULL.
+        */
+       uint64_t beacon_ts_end;
+
+       /* CTF stream ID, -1ULL when unset (first packet not received yet). */
+       uint64_t ctf_stream_id;
+
+       /* Indicate if the stream was initialized for a data pending command. */
+       bool data_pending_check_done;
+
+       /* Is this stream a metadata stream ? */
+       bool is_metadata;
+       /* Amount of metadata received (bytes). */
+       uint64_t metadata_received;
+
+       /*
+        * Member of the stream list in struct ctf_trace.
+        * Updates are protected by the stream_list_lock.
+        * Traversals are protected by RCU.
+        */
+       struct cds_list_head stream_node;
+       /*
+        * Temporary list belonging to the connection until all streams
+        * are received for that connection.
+        * Member of the stream recv list in the connection.
+        * Updates are protected by the stream_recv_list_lock.
+        * Traversals are protected by RCU.
+        */
+       bool in_recv_list;
+       struct cds_list_head recv_node;
+       /* Protected by session lock. */
+       bool published;
+       /* Notified viewer that no new metadata is available. */
+       bool no_new_metadata_notified;
+       /*
+        * Node of stream within global stream hash table.
+        */
+       struct lttng_ht_node_u64 node;
+       bool in_stream_ht;              /* is stream in stream hash table. */
+       struct rcu_head rcu_node;       /* For call_rcu teardown. */
+       /*
+        * The trace chunk to which the file currently being produced (if any)
+        * belongs.
+        *
+        * Note that a relay stream can have no output trace chunk. For
+        * instance, after a session stop followed by a session clear,
+        * streams will not have an output trace chunk until the session
+        * is resumed.
+        */
+       struct lttng_trace_chunk *trace_chunk;
+       LTTNG_OPTIONAL(struct relay_stream_rotation) ongoing_rotation;
+       uint64_t completed_rotation_count;
+};
+
+struct relay_stream *stream_create(struct ctf_trace *trace,
+       uint64_t stream_handle, char *path_name,
+       char *channel_name, uint64_t tracefile_size,
+       uint64_t tracefile_count);
+
+struct relay_stream *stream_get_by_id(uint64_t stream_id);
+bool stream_get(struct relay_stream *stream);
+void stream_put(struct relay_stream *stream);
+int stream_rotate_output_files(struct relay_session *session,
+               struct relay_stream *stream);
+int stream_set_pending_rotation(struct relay_stream *stream,
+               struct lttng_trace_chunk *next_trace_chunk,
+               uint64_t rotation_sequence_number);
+void try_stream_close(struct relay_stream *stream);
+void stream_publish(struct relay_stream *stream);
+int stream_init_packet(struct relay_stream *stream, size_t packet_size,
+               bool *file_rotated);
+int stream_write(struct relay_stream *stream,
+               const struct lttng_buffer_view *packet, size_t padding_len);
+/* Called after the reception of a complete data packet. */
+int stream_update_index(struct relay_stream *stream, uint64_t net_seq_num,
+               bool rotate_index, bool *flushed, uint64_t total_size);
+int stream_complete_packet(struct relay_stream *stream,
+               size_t packet_total_size, uint64_t sequence_number,
+               bool index_flushed);
+/* Index info is in host endianness. */
+int stream_add_index(struct relay_stream *stream,
+               const struct lttcomm_relayd_index *index_info);
+int stream_reset_file(struct relay_stream *stream);
+
+void print_relay_streams(void);
+
+#endif /* _STREAM_H */
index c52a55ffba4cb1493d1b9ce60d743ed6ee62b552..885b2a6a5617391e4a430674e37f4c4459cfca34 100644 (file)
 #include <sys/socket.h>
 #include <limits.h>
 
-#include <common/compat/getenv.h>
-#include <common/time.h>
-#include <common/defaults.h>
-#include <common/ini-config/ini-config.h>
+#include <common/compat/getenv.hpp>
+#include <common/time.hpp>
+#include <common/defaults.hpp>
+#include <common/ini-config/ini-config.hpp>
 
-#include "tcp_keep_alive.h"
+#include "tcp_keep_alive.hpp"
 
 #define SOLARIS_IDLE_TIME_MIN_S 10
 #define SOLARIS_IDLE_TIME_MAX_S 864000 /* 10 days */
diff --git a/src/bin/lttng-relayd/tcp_keep_alive.h b/src/bin/lttng-relayd/tcp_keep_alive.h
deleted file mode 100644 (file)
index 2236028..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef RELAYD_TCP_KEEP_ALIVE_H
-#define RELAYD_TCP_KEEP_ALIVE_H
-
-#include <common/macros.h>
-
-int socket_apply_keep_alive_config(int socket_fd);
-
-#endif /* RELAYD_TCP_KEEP_ALIVE_H */
diff --git a/src/bin/lttng-relayd/tcp_keep_alive.hpp b/src/bin/lttng-relayd/tcp_keep_alive.hpp
new file mode 100644 (file)
index 0000000..840730f
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef RELAYD_TCP_KEEP_ALIVE_H
+#define RELAYD_TCP_KEEP_ALIVE_H
+
+#include <common/macros.hpp>
+
+int socket_apply_keep_alive_config(int socket_fd);
+
+#endif /* RELAYD_TCP_KEEP_ALIVE_H */
diff --git a/src/bin/lttng-relayd/testpoint.h b/src/bin/lttng-relayd/testpoint.h
deleted file mode 100644 (file)
index f58836a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef RELAYD_TESTPOINT_H
-#define RELAYD_TESTPOINT_H
-
-/*
- * Copyright (C) 2012 Christian Babeux <christian.babeux@efficios.com>
- * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <common/testpoint/testpoint.h>
-
-/* Testpoints, internal use only */
-TESTPOINT_DECL(relayd_thread_dispatcher);
-TESTPOINT_DECL(relayd_thread_worker);
-TESTPOINT_DECL(relayd_thread_listener);
-TESTPOINT_DECL(relayd_thread_live_dispatcher);
-TESTPOINT_DECL(relayd_thread_live_worker);
-TESTPOINT_DECL(relayd_thread_live_listener);
-
-#endif /* SESSIOND_TESTPOINT_H */
diff --git a/src/bin/lttng-relayd/testpoint.hpp b/src/bin/lttng-relayd/testpoint.hpp
new file mode 100644 (file)
index 0000000..84fb4a8
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef RELAYD_TESTPOINT_H
+#define RELAYD_TESTPOINT_H
+
+/*
+ * Copyright (C) 2012 Christian Babeux <christian.babeux@efficios.com>
+ * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <common/testpoint/testpoint.hpp>
+
+/* Testpoints, internal use only */
+TESTPOINT_DECL(relayd_thread_dispatcher);
+TESTPOINT_DECL(relayd_thread_worker);
+TESTPOINT_DECL(relayd_thread_listener);
+TESTPOINT_DECL(relayd_thread_live_dispatcher);
+TESTPOINT_DECL(relayd_thread_live_worker);
+TESTPOINT_DECL(relayd_thread_live_listener);
+
+#endif /* SESSIOND_TESTPOINT_H */
index 05012b642cc40f6f6c913806e808b56d488e45d5..8b1b533d5d60e8520344531ff3f3813d36030591 100644 (file)
@@ -6,11 +6,11 @@
  */
 
 #define _LGPL_SOURCE
-#include <common/common.h>
-#include <common/utils.h>
-#include <common/defaults.h>
+#include <common/common.hpp>
+#include <common/utils.hpp>
+#include <common/defaults.hpp>
 
-#include "tracefile-array.h"
+#include "tracefile-array.hpp"
 
 struct tracefile_array *tracefile_array_create(size_t count)
 {
diff --git a/src/bin/lttng-relayd/tracefile-array.h b/src/bin/lttng-relayd/tracefile-array.h
deleted file mode 100644 (file)
index 09c425f..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _TRACEFILE_ARRAY_H
-#define _TRACEFILE_ARRAY_H
-
-/*
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <limits.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <stdbool.h>
-
-struct tracefile {
-       /* Per-tracefile head/tail seq. */
-       uint64_t seq_head;      /* Newest seqcount. Inclusive. */
-       uint64_t seq_tail;      /* Oldest seqcount. Inclusive. */
-};
-
-enum tracefile_rotate_type {
-       TRACEFILE_ROTATE_READ,
-       TRACEFILE_ROTATE_WRITE,
-};
-
-/*
- * Represents an array of trace files in a stream.
- * head is the most recent file/trace packet.
- * tail is the oldest file/trace packet.
- *
- * There are two heads: a "read" head and a "write" head. The "write" head is
- * the position of the newest data file. The "read" head position is only moved
- * forward when the index is received.
- *
- * The viewer uses the "read" head position as upper bound, which
- * ensures it never attempts to open a non-existing index file.
- */
-struct tracefile_array {
-       struct tracefile *tf;
-       size_t count;
-
-       /* Current head/tail files. */
-       uint64_t file_head_read;
-       uint64_t file_head_write;
-       uint64_t file_tail;
-
-       /* Overall head/tail seq for the entire array. Inclusive. */
-       uint64_t seq_head;
-       uint64_t seq_tail;
-};
-
-struct tracefile_array *tracefile_array_create(size_t count);
-void tracefile_array_destroy(struct tracefile_array *tfa);
-
-void tracefile_array_file_rotate(struct tracefile_array *tfa, enum tracefile_rotate_type type);
-void tracefile_array_commit_seq(struct tracefile_array *tfa,
-               uint64_t new_seq_head);
-void tracefile_array_reset(struct tracefile_array *tfa);
-
-uint64_t tracefile_array_get_read_file_index_head(struct tracefile_array *tfa);
-/* May return -1ULL in the case where we have not received any indexes yet. */
-uint64_t tracefile_array_get_seq_head(struct tracefile_array *tfa);
-
-uint64_t tracefile_array_get_file_index_tail(struct tracefile_array *tfa);
-/* May return -1ULL in the case where we have not received any indexes yet. */
-uint64_t tracefile_array_get_seq_tail(struct tracefile_array *tfa);
-
-bool tracefile_array_seq_in_file(struct tracefile_array *tfa,
-               uint64_t file_index, uint64_t seq);
-
-#endif /* _STREAM_H */
diff --git a/src/bin/lttng-relayd/tracefile-array.hpp b/src/bin/lttng-relayd/tracefile-array.hpp
new file mode 100644 (file)
index 0000000..09c425f
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _TRACEFILE_ARRAY_H
+#define _TRACEFILE_ARRAY_H
+
+/*
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <limits.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdbool.h>
+
+struct tracefile {
+       /* Per-tracefile head/tail seq. */
+       uint64_t seq_head;      /* Newest seqcount. Inclusive. */
+       uint64_t seq_tail;      /* Oldest seqcount. Inclusive. */
+};
+
+enum tracefile_rotate_type {
+       TRACEFILE_ROTATE_READ,
+       TRACEFILE_ROTATE_WRITE,
+};
+
+/*
+ * Represents an array of trace files in a stream.
+ * head is the most recent file/trace packet.
+ * tail is the oldest file/trace packet.
+ *
+ * There are two heads: a "read" head and a "write" head. The "write" head is
+ * the position of the newest data file. The "read" head position is only moved
+ * forward when the index is received.
+ *
+ * The viewer uses the "read" head position as upper bound, which
+ * ensures it never attempts to open a non-existing index file.
+ */
+struct tracefile_array {
+       struct tracefile *tf;
+       size_t count;
+
+       /* Current head/tail files. */
+       uint64_t file_head_read;
+       uint64_t file_head_write;
+       uint64_t file_tail;
+
+       /* Overall head/tail seq for the entire array. Inclusive. */
+       uint64_t seq_head;
+       uint64_t seq_tail;
+};
+
+struct tracefile_array *tracefile_array_create(size_t count);
+void tracefile_array_destroy(struct tracefile_array *tfa);
+
+void tracefile_array_file_rotate(struct tracefile_array *tfa, enum tracefile_rotate_type type);
+void tracefile_array_commit_seq(struct tracefile_array *tfa,
+               uint64_t new_seq_head);
+void tracefile_array_reset(struct tracefile_array *tfa);
+
+uint64_t tracefile_array_get_read_file_index_head(struct tracefile_array *tfa);
+/* May return -1ULL in the case where we have not received any indexes yet. */
+uint64_t tracefile_array_get_seq_head(struct tracefile_array *tfa);
+
+uint64_t tracefile_array_get_file_index_tail(struct tracefile_array *tfa);
+/* May return -1ULL in the case where we have not received any indexes yet. */
+uint64_t tracefile_array_get_seq_tail(struct tracefile_array *tfa);
+
+bool tracefile_array_seq_in_file(struct tracefile_array *tfa,
+               uint64_t file_index, uint64_t seq);
+
+#endif /* _STREAM_H */
index 599f7ff819f3cf4855ca9f7b47ae27d6343c0493..a708afe33b682d4c5f6dade0389ef3303f0442ad 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/utils.hpp>
 
-#include "lttng-relayd.h"
-#include "utils.h"
+#include "lttng-relayd.hpp"
+#include "utils.hpp"
 
 static char *create_output_path_auto(const char *path_name)
 {
diff --git a/src/bin/lttng-relayd/utils.h b/src/bin/lttng-relayd/utils.h
deleted file mode 100644 (file)
index b02a791..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef RELAYD_UTILS_H
-#define RELAYD_UTILS_H
-
-/*
- * Copyright (C) 2012 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-char *create_output_path(const char *path_name);
-
-#endif /* RELAYD_UTILS_H */
diff --git a/src/bin/lttng-relayd/utils.hpp b/src/bin/lttng-relayd/utils.hpp
new file mode 100644 (file)
index 0000000..b02a791
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef RELAYD_UTILS_H
+#define RELAYD_UTILS_H
+
+/*
+ * Copyright (C) 2012 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+char *create_output_path(const char *path_name);
+
+#endif /* RELAYD_UTILS_H */
index ac14dbff0cf8fcf3d042775f0d0335febdfb4db5..4529a21fa7c9342f9aa30749dce2dcfd226dcdc0 100644 (file)
@@ -8,15 +8,15 @@
  */
 
 #define _LGPL_SOURCE
-#include <common/common.h>
+#include <common/common.hpp>
 #include <urcu/rculist.h>
 
-#include "lttng-relayd.h"
-#include "ctf-trace.h"
-#include "session.h"
-#include "viewer-session.h"
-#include "viewer-stream.h"
-#include "stream.h"
+#include "lttng-relayd.hpp"
+#include "ctf-trace.hpp"
+#include "session.hpp"
+#include "viewer-session.hpp"
+#include "viewer-stream.hpp"
+#include "stream.hpp"
 
 struct relay_viewer_session *viewer_session_create(void)
 {
diff --git a/src/bin/lttng-relayd/viewer-session.h b/src/bin/lttng-relayd/viewer-session.h
deleted file mode 100644 (file)
index f70daed..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _VIEWER_SESSION_H
-#define _VIEWER_SESSION_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <limits.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <urcu/list.h>
-#include <urcu/ref.h>
-
-#include <common/hashtable/hashtable.h>
-#include <common/trace-chunk.h>
-
-#include "session.h"
-#include "lttng-viewer-abi.h"
-
-struct relay_viewer_session {
-       /*
-        * Session list. Updates are protected by the session_list_lock.
-        * Traversals are protected by RCU.
-        * This list limits the design to having the sessions in at most
-        * one viewer session.
-        */
-       struct cds_list_head session_list;      /* RCU list. */
-       pthread_mutex_t session_list_lock;      /* Protects list updates. */
-       /*
-        * The viewer session's current trace chunk is initially set, when
-        * a viewer attaches to the viewer session, to a copy the corresponding
-        * relay_session's current trace chunk.
-        *
-        * A live session always attempts to "catch-up" to the newest available
-        * trace chunk. This means that when a viewer reaches the end of a
-        * trace chunk, the viewer session may not transition to the "next" one:
-        * it jumps to the most recent trace chunk available (the one being
-        * produced by the relay_session). Hence, if the producer performs
-        * multiple rotations before a viewer completes the consumption of a
-        * trace chunk, it will skip over those "intermediary" trace chunks.
-        *
-        * A viewer session updates its current trace chunk when:
-        *   1) new viewer streams are created,
-        *   2) a new index is requested,
-        *   3) metadata is requested.
-        *
-        * Hence, as a general principle, the viewer session will reference the
-        * most recent trace chunk available _even if its streams do not point to
-        * it_. It indicates which trace chunk viewer streams should transition
-        * to when the end of their current trace chunk is reached.
-        *
-        * Note that a viewer session's trace chunk points to the session's
-        * output directory. The sub-directories in which the various stream files
-        * are created are considered as being a part of their name.
-        */
-       struct lttng_trace_chunk *current_trace_chunk;
-};
-
-struct relay_viewer_session *viewer_session_create(void);
-void viewer_session_destroy(struct relay_viewer_session *vsession);
-void viewer_session_close(struct relay_viewer_session *vsession);
-
-enum lttng_viewer_attach_return_code viewer_session_attach(
-               struct relay_viewer_session *vsession,
-               struct relay_session *session);
-int viewer_session_is_attached(struct relay_viewer_session *vsession,
-               struct relay_session *session);
-void viewer_session_close_one_session(struct relay_viewer_session *vsession,
-               struct relay_session *session);
-int viewer_session_set_trace_chunk_copy(struct relay_viewer_session *vsession,
-               struct lttng_trace_chunk *relay_session_trace_chunk);
-
-#endif /* _VIEWER_SESSION_H */
diff --git a/src/bin/lttng-relayd/viewer-session.hpp b/src/bin/lttng-relayd/viewer-session.hpp
new file mode 100644 (file)
index 0000000..65ad3e1
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _VIEWER_SESSION_H
+#define _VIEWER_SESSION_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <limits.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <urcu/list.h>
+#include <urcu/ref.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <common/trace-chunk.hpp>
+
+#include "session.hpp"
+#include "lttng-viewer-abi.hpp"
+
+struct relay_viewer_session {
+       /*
+        * Session list. Updates are protected by the session_list_lock.
+        * Traversals are protected by RCU.
+        * This list limits the design to having the sessions in at most
+        * one viewer session.
+        */
+       struct cds_list_head session_list;      /* RCU list. */
+       pthread_mutex_t session_list_lock;      /* Protects list updates. */
+       /*
+        * The viewer session's current trace chunk is initially set, when
+        * a viewer attaches to the viewer session, to a copy the corresponding
+        * relay_session's current trace chunk.
+        *
+        * A live session always attempts to "catch-up" to the newest available
+        * trace chunk. This means that when a viewer reaches the end of a
+        * trace chunk, the viewer session may not transition to the "next" one:
+        * it jumps to the most recent trace chunk available (the one being
+        * produced by the relay_session). Hence, if the producer performs
+        * multiple rotations before a viewer completes the consumption of a
+        * trace chunk, it will skip over those "intermediary" trace chunks.
+        *
+        * A viewer session updates its current trace chunk when:
+        *   1) new viewer streams are created,
+        *   2) a new index is requested,
+        *   3) metadata is requested.
+        *
+        * Hence, as a general principle, the viewer session will reference the
+        * most recent trace chunk available _even if its streams do not point to
+        * it_. It indicates which trace chunk viewer streams should transition
+        * to when the end of their current trace chunk is reached.
+        *
+        * Note that a viewer session's trace chunk points to the session's
+        * output directory. The sub-directories in which the various stream files
+        * are created are considered as being a part of their name.
+        */
+       struct lttng_trace_chunk *current_trace_chunk;
+};
+
+struct relay_viewer_session *viewer_session_create(void);
+void viewer_session_destroy(struct relay_viewer_session *vsession);
+void viewer_session_close(struct relay_viewer_session *vsession);
+
+enum lttng_viewer_attach_return_code viewer_session_attach(
+               struct relay_viewer_session *vsession,
+               struct relay_session *session);
+int viewer_session_is_attached(struct relay_viewer_session *vsession,
+               struct relay_session *session);
+void viewer_session_close_one_session(struct relay_viewer_session *vsession,
+               struct relay_session *session);
+int viewer_session_set_trace_chunk_copy(struct relay_viewer_session *vsession,
+               struct lttng_trace_chunk *relay_session_trace_chunk);
+
+#endif /* _VIEWER_SESSION_H */
index 69671bd7af4552ae6eb1803654692265a1c30cd3..fa447d45bb20584a75236d9969e0ade9a534d03a 100644 (file)
@@ -8,17 +8,17 @@
  */
 
 #define _LGPL_SOURCE
-#include <common/common.h>
-#include <common/index/index.h>
-#include <common/compat/string.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/index/index.hpp>
+#include <common/compat/string.hpp>
+#include <common/utils.hpp>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <algorithm>
 
-#include "lttng-relayd.h"
-#include "viewer-stream.h"
+#include "lttng-relayd.hpp"
+#include "viewer-stream.hpp"
 
 static void viewer_stream_release_composite_objects(struct relay_viewer_stream *vstream)
 {
diff --git a/src/bin/lttng-relayd/viewer-stream.h b/src/bin/lttng-relayd/viewer-stream.h
deleted file mode 100644 (file)
index e7d733b..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef _VIEWER_STREAM_H
-#define _VIEWER_STREAM_H
-
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <limits.h>
-#include <inttypes.h>
-#include <pthread.h>
-
-#include <common/hashtable/hashtable.h>
-
-#include "ctf-trace.h"
-#include "lttng-viewer-abi.h"
-#include "stream.h"
-
-struct relay_stream;
-
-/*
- * The viewer stream's lifetime is the intersection of their viewer connection's
- * lifetime and the duration during which at least:
- * a) their input source is still active
- * b) they still have data left to send to the client.
- *
- * This means that both the sessiond/consumerd connection or the viewer
- * connection may tear down (and unpublish) a relay_viewer_stream.
- *
- * Viewer stream updates are protected by their associated stream's lock.
- */
-struct relay_viewer_stream {
-       struct urcu_ref ref;
-
-       /* Back ref to stream. */
-       struct relay_stream *stream;
-
-       struct {
-               struct fs_handle *handle;
-               struct lttng_trace_chunk *trace_chunk;
-       } stream_file;
-       /* index file from which to read the index data. */
-       struct lttng_index_file *index_file;
-       /*
-        * Last seen rotation count in stream.
-        *
-        * Sampled on every change to the viewer stream trace chunk,
-        * this allows the live server to determine if it saw the latest
-        * rotation that occurred on the receiving end.
-        */
-       uint64_t last_seen_rotation_count;
-
-       char *path_name;
-       char *channel_name;
-
-       uint64_t current_tracefile_id;
-
-       /*
-        * Counts the number of sent indexes. The "tag" associated
-        * with an index to send is the current index_received_seqcount,
-        * because we increment index_received_seqcount after sending
-        * each index. This index_received_seqcount counter can also be
-        * updated when catching up with the producer.
-        */
-       uint64_t index_sent_seqcount;
-
-       /* Indicates if this stream has been sent to a viewer client. */
-       bool sent_flag;
-       /* For metadata stream, how much metadata has been sent. */
-       uint64_t metadata_sent;
-
-       struct lttng_ht_node_u64 stream_n;
-       struct rcu_head rcu_node;
-};
-
-struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream,
-               struct lttng_trace_chunk *viewer_trace_chunk,
-               enum lttng_viewer_seek seek_t);
-
-struct relay_viewer_stream *viewer_stream_get_by_id(uint64_t id);
-bool viewer_stream_get(struct relay_viewer_stream *vstream);
-void viewer_stream_put(struct relay_viewer_stream *vstream);
-int viewer_stream_rotate(struct relay_viewer_stream *vstream);
-bool viewer_stream_is_tracefile_seq_readable(struct relay_viewer_stream *vstream,
-               uint64_t seq);
-void print_viewer_streams(void);
-void viewer_stream_close_files(struct relay_viewer_stream *vstream);
-void viewer_stream_sync_tracefile_array_tail(struct relay_viewer_stream *vstream);
-
-#endif /* _VIEWER_STREAM_H */
diff --git a/src/bin/lttng-relayd/viewer-stream.hpp b/src/bin/lttng-relayd/viewer-stream.hpp
new file mode 100644 (file)
index 0000000..42bdc1e
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef _VIEWER_STREAM_H
+#define _VIEWER_STREAM_H
+
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <limits.h>
+#include <inttypes.h>
+#include <pthread.h>
+
+#include <common/hashtable/hashtable.hpp>
+
+#include "ctf-trace.hpp"
+#include "lttng-viewer-abi.hpp"
+#include "stream.hpp"
+
+struct relay_stream;
+
+/*
+ * The viewer stream's lifetime is the intersection of their viewer connection's
+ * lifetime and the duration during which at least:
+ * a) their input source is still active
+ * b) they still have data left to send to the client.
+ *
+ * This means that both the sessiond/consumerd connection or the viewer
+ * connection may tear down (and unpublish) a relay_viewer_stream.
+ *
+ * Viewer stream updates are protected by their associated stream's lock.
+ */
+struct relay_viewer_stream {
+       struct urcu_ref ref;
+
+       /* Back ref to stream. */
+       struct relay_stream *stream;
+
+       struct {
+               struct fs_handle *handle;
+               struct lttng_trace_chunk *trace_chunk;
+       } stream_file;
+       /* index file from which to read the index data. */
+       struct lttng_index_file *index_file;
+       /*
+        * Last seen rotation count in stream.
+        *
+        * Sampled on every change to the viewer stream trace chunk,
+        * this allows the live server to determine if it saw the latest
+        * rotation that occurred on the receiving end.
+        */
+       uint64_t last_seen_rotation_count;
+
+       char *path_name;
+       char *channel_name;
+
+       uint64_t current_tracefile_id;
+
+       /*
+        * Counts the number of sent indexes. The "tag" associated
+        * with an index to send is the current index_received_seqcount,
+        * because we increment index_received_seqcount after sending
+        * each index. This index_received_seqcount counter can also be
+        * updated when catching up with the producer.
+        */
+       uint64_t index_sent_seqcount;
+
+       /* Indicates if this stream has been sent to a viewer client. */
+       bool sent_flag;
+       /* For metadata stream, how much metadata has been sent. */
+       uint64_t metadata_sent;
+
+       struct lttng_ht_node_u64 stream_n;
+       struct rcu_head rcu_node;
+};
+
+struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream,
+               struct lttng_trace_chunk *viewer_trace_chunk,
+               enum lttng_viewer_seek seek_t);
+
+struct relay_viewer_stream *viewer_stream_get_by_id(uint64_t id);
+bool viewer_stream_get(struct relay_viewer_stream *vstream);
+void viewer_stream_put(struct relay_viewer_stream *vstream);
+int viewer_stream_rotate(struct relay_viewer_stream *vstream);
+bool viewer_stream_is_tracefile_seq_readable(struct relay_viewer_stream *vstream,
+               uint64_t seq);
+void print_viewer_streams(void);
+void viewer_stream_close_files(struct relay_viewer_stream *vstream);
+void viewer_stream_sync_tracefile_array_tail(struct relay_viewer_stream *vstream);
+
+#endif /* _VIEWER_STREAM_H */
index 2de44a492d427564650fd0d5c4ec8cf181e88519..154230718823b80e891e5f3626211ad77774c061 100644 (file)
@@ -9,77 +9,77 @@ endif
 
 noinst_LTLIBRARIES = liblttng-sessiond-common.la
 
-liblttng_sessiond_common_la_SOURCES = utils.cpp utils.h \
-                       trace-kernel.cpp trace-kernel.h \
-                       kernel.cpp kernel.h \
-                       ust-app.h ust-sigbus.h trace-ust.h notify-apps.h \
-                       lttng-ust-ctl.h lttng-ust-abi.h lttng-ust-error.h \
-                       ust-ctl-internal.h ust-abi-internal.h ust-error-internal.h \
-                       ust-registry.h \
-                       condition-internal.cpp condition-internal.h \
-                       context.cpp context.h \
-                       channel.cpp channel.h \
-                       event.cpp event.h \
-                       consumer.cpp consumer.h \
-                       session.cpp session.h \
-                       modprobe.cpp modprobe.h kern-modules.h \
-                       fd-limit.cpp fd-limit.h \
-                       kernel-consumer.cpp kernel-consumer.h \
-                       consumer.h \
-                       health-sessiond.h \
-                       cmd.cpp cmd.h \
-                       buffer-registry.cpp buffer-registry.h \
-                       testpoint.h ht-cleanup.cpp ht-cleanup.h \
-                       snapshot.cpp snapshot.h \
-                       agent.cpp agent.h \
-                       save.h save.cpp \
-                       lttng-syscall.h lttng-syscall.cpp \
-                       notification-thread.h notification-thread.cpp \
-                       notification-thread-internal.h \
-                       notification-thread-commands.h notification-thread-commands.cpp \
-                       notification-thread-events.h notification-thread-events.cpp \
-                       sessiond-config.h sessiond-config.cpp \
-                       rotate.h rotate.cpp \
-                       rotation-thread.h rotation-thread.cpp \
-                       timer.cpp timer.h \
+liblttng_sessiond_common_la_SOURCES = utils.cpp utils.hpp \
+                       trace-kernel.cpp trace-kernel.hpp \
+                       kernel.cpp kernel.hpp \
+                       ust-app.hpp ust-sigbus.hpp trace-ust.hpp notify-apps.hpp \
+                       lttng-ust-ctl.hpp lttng-ust-abi.hpp lttng-ust-error.hpp \
+                       ust-ctl-internal.hpp ust-abi-internal.hpp ust-error-internal.hpp \
+                       ust-registry.hpp \
+                       condition-internal.cpp condition-internal.hpp \
+                       context.cpp context.hpp \
+                       channel.cpp channel.hpp \
+                       event.cpp event.hpp \
+                       consumer.cpp consumer.hpp \
+                       session.cpp session.hpp \
+                       modprobe.cpp modprobe.hpp kern-modules.hpp \
+                       fd-limit.cpp fd-limit.hpp \
+                       kernel-consumer.cpp kernel-consumer.hpp \
+                       consumer.hpp \
+                       health-sessiond.hpp \
+                       cmd.cpp cmd.hpp \
+                       buffer-registry.cpp buffer-registry.hpp \
+                       testpoint.hpp ht-cleanup.cpp ht-cleanup.hpp \
+                       snapshot.cpp snapshot.hpp \
+                       agent.cpp agent.hpp \
+                       save.hpp save.cpp \
+                       lttng-syscall.hpp lttng-syscall.cpp \
+                       notification-thread.hpp notification-thread.cpp \
+                       notification-thread-internal.hpp \
+                       notification-thread-commands.hpp notification-thread-commands.cpp \
+                       notification-thread-events.hpp notification-thread-events.cpp \
+                       sessiond-config.hpp sessiond-config.cpp \
+                       rotate.hpp rotate.cpp \
+                       rotation-thread.hpp rotation-thread.cpp \
+                       timer.cpp timer.hpp \
                        globals.cpp \
                        thread-utils.cpp \
                        process-utils.cpp \
-                       thread.cpp thread.h \
+                       thread.cpp thread.hpp \
                        health.cpp \
-                       client.cpp client.h \
-                       dispatch.cpp dispatch.h \
-                       register.cpp register.h \
-                       manage-apps.cpp manage-apps.h \
-                       manage-kernel.cpp manage-kernel.h \
-                       manage-consumer.cpp manage-consumer.h \
-                       clear.cpp clear.h \
-                       tracker.cpp tracker.h \
-                       event-notifier-error-accounting.cpp event-notifier-error-accounting.h \
-                       action-executor.cpp action-executor.h\
+                       client.cpp client.hpp \
+                       dispatch.cpp dispatch.hpp \
+                       register.cpp register.hpp \
+                       manage-apps.cpp manage-apps.hpp \
+                       manage-kernel.cpp manage-kernel.hpp \
+                       manage-consumer.cpp manage-consumer.hpp \
+                       clear.cpp clear.hpp \
+                       tracker.cpp tracker.hpp \
+                       event-notifier-error-accounting.cpp event-notifier-error-accounting.hpp \
+                       action-executor.cpp action-executor.hpp \
                        trigger-error-query.cpp
 
 if HAVE_LIBLTTNG_UST_CTL
 liblttng_sessiond_common_la_SOURCES += trace-ust.cpp ust-registry.cpp ust-app.cpp \
-                       ust-consumer.cpp ust-consumer.h notify-apps.cpp \
-                       ust-metadata.cpp ust-clock.h agent-thread.cpp agent-thread.h \
-                       ust-field-utils.h ust-field-utils.cpp \
+                       ust-consumer.cpp ust-consumer.hpp notify-apps.cpp \
+                       ust-metadata.cpp ust-clock.hpp agent-thread.cpp agent-thread.hpp \
+                       ust-field-utils.hpp ust-field-utils.cpp \
                        ust-sigbus.cpp
 endif
 
 # link on liblttngctl for check if sessiond is already alive.
 liblttng_sessiond_common_la_LIBADD = $(URCU_LIBS) $(KMOD_LIBS) \
                $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la \
-               $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \
-               $(top_builddir)/src/common/kernel-ctl/libkernel-ctl.la \
-               $(top_builddir)/src/common/hashtable/libhashtable.la \
+               $(top_builddir)/src/common/libsessiond-comm.la \
+               $(top_builddir)/src/common/libkernel-ctl.la \
+               $(top_builddir)/src/common/libhashtable.la \
                $(top_builddir)/src/common/libcommon.la \
-               $(top_builddir)/src/common/compat/libcompat.la \
-               $(top_builddir)/src/common/relayd/librelayd.la \
-               $(top_builddir)/src/common/testpoint/libtestpoint.la \
-               $(top_builddir)/src/common/health/libhealth.la \
-               $(top_builddir)/src/common/config/libconfig.la \
-               $(top_builddir)/src/common/string-utils/libstring-utils.la
+               $(top_builddir)/src/common/libcompat.la \
+               $(top_builddir)/src/common/librelayd.la \
+               $(top_builddir)/src/common/libtestpoint.la \
+               $(top_builddir)/src/common/libhealth.la \
+               $(top_builddir)/src/common/libconfig.la \
+               $(top_builddir)/src/common/libstring-utils.la
 
 
 if HAVE_LIBLTTNG_UST_CTL
@@ -88,7 +88,7 @@ endif
 
 bin_PROGRAMS = lttng-sessiond
 
-lttng_sessiond_SOURCES = lttng-sessiond.h main.cpp
+lttng_sessiond_SOURCES = lttng-sessiond.hpp main.cpp
 
 lttng_sessiond_LDFLAGS = -rdynamic
 
index 032ac11a08de74d0f0657b67086e2bfc7afc99c4..4a81b3f3e8ebc86a4f48a4cea1ecf736ac5ef0c9 100644 (file)
@@ -5,29 +5,29 @@
  *
  */
 
-#include "action-executor.h"
-#include "cmd.h"
-#include "health-sessiond.h"
-#include "lttng-sessiond.h"
-#include "notification-thread-internal.h"
-#include "session.h"
-#include "thread.h"
-#include <common/dynamic-array.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/list-internal.h>
+#include "action-executor.hpp"
+#include "cmd.hpp"
+#include "health-sessiond.hpp"
+#include "lttng-sessiond.hpp"
+#include "notification-thread-internal.hpp"
+#include "session.hpp"
+#include "thread.hpp"
+#include <common/dynamic-array.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/list-internal.hpp>
 #include <lttng/action/list.h>
-#include <lttng/action/notify-internal.h>
+#include <lttng/action/notify-internal.hpp>
 #include <lttng/action/notify.h>
 #include <lttng/action/rotate-session.h>
 #include <lttng/action/snapshot-session.h>
 #include <lttng/action/start-session.h>
 #include <lttng/action/stop-session.h>
 #include <lttng/condition/evaluation.h>
-#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/condition/event-rule-matches-internal.hpp>
 #include <lttng/lttng-error.h>
-#include <lttng/trigger/trigger-internal.h>
+#include <lttng/trigger/trigger-internal.hpp>
 #include <pthread.h>
 #include <stdbool.h>
 #include <stddef.h>
diff --git a/src/bin/lttng-sessiond/action-executor.h b/src/bin/lttng-sessiond/action-executor.h
deleted file mode 100644 (file)
index 85d5931..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef ACTION_EXECUTOR_H
-#define ACTION_EXECUTOR_H
-
-struct action_executor;
-struct notification_thread_handle;
-struct lttng_evaluation;
-struct lttng_trigger;
-struct notification_client_list;
-struct lttng_credentials;
-
-enum action_executor_status {
-       ACTION_EXECUTOR_STATUS_OK,
-       ACTION_EXECUTOR_STATUS_OVERFLOW,
-       ACTION_EXECUTOR_STATUS_ERROR,
-       ACTION_EXECUTOR_STATUS_INVALID,
-};
-
-struct action_executor *action_executor_create(
-               struct notification_thread_handle *handle);
-
-void action_executor_destroy(struct action_executor *executor);
-
-/*
- * Enqueue a job on an action executor's work queue to perform the actions
- * associated with a trigger.
- *
- * A reference to `trigger` is acquired.
- * A reference to `list` is acquired.
- *
- * This function assumes the ownership of the `evaluation` both on success and
- * failure: the caller should no longer access it once the function returns.
- */
-enum action_executor_status action_executor_enqueue_trigger(
-               struct action_executor *executor,
-               struct lttng_trigger *trigger,
-               struct lttng_evaluation *evaluation,
-               const struct lttng_credentials *object_creds,
-               struct notification_client_list *list);
-
-#endif /* ACTION_EXECUTOR_H */
diff --git a/src/bin/lttng-sessiond/action-executor.hpp b/src/bin/lttng-sessiond/action-executor.hpp
new file mode 100644 (file)
index 0000000..85d5931
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef ACTION_EXECUTOR_H
+#define ACTION_EXECUTOR_H
+
+struct action_executor;
+struct notification_thread_handle;
+struct lttng_evaluation;
+struct lttng_trigger;
+struct notification_client_list;
+struct lttng_credentials;
+
+enum action_executor_status {
+       ACTION_EXECUTOR_STATUS_OK,
+       ACTION_EXECUTOR_STATUS_OVERFLOW,
+       ACTION_EXECUTOR_STATUS_ERROR,
+       ACTION_EXECUTOR_STATUS_INVALID,
+};
+
+struct action_executor *action_executor_create(
+               struct notification_thread_handle *handle);
+
+void action_executor_destroy(struct action_executor *executor);
+
+/*
+ * Enqueue a job on an action executor's work queue to perform the actions
+ * associated with a trigger.
+ *
+ * A reference to `trigger` is acquired.
+ * A reference to `list` is acquired.
+ *
+ * This function assumes the ownership of the `evaluation` both on success and
+ * failure: the caller should no longer access it once the function returns.
+ */
+enum action_executor_status action_executor_enqueue_trigger(
+               struct action_executor *executor,
+               struct lttng_trigger *trigger,
+               struct lttng_evaluation *evaluation,
+               const struct lttng_credentials *object_creds,
+               struct notification_client_list *list);
+
+#endif /* ACTION_EXECUTOR_H */
index 5e158b49bea408d2c161121f90eed7fbe4294359..77470b3ee1a25446a9a8f23e2be3c9f4f4a7e134 100644 (file)
@@ -7,20 +7,20 @@
 
 #define _LGPL_SOURCE
 
-#include <common/common.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/uri.h>
-#include <common/utils.h>
-
-#include <common/compat/endian.h>
-
-#include "fd-limit.h"
-#include "agent-thread.h"
-#include "agent.h"
-#include "lttng-sessiond.h"
-#include "session.h"
-#include "utils.h"
-#include "thread.h"
+#include <common/common.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/uri.hpp>
+#include <common/utils.hpp>
+
+#include <common/compat/endian.hpp>
+
+#include "fd-limit.hpp"
+#include "agent-thread.hpp"
+#include "agent.hpp"
+#include "lttng-sessiond.hpp"
+#include "session.hpp"
+#include "utils.hpp"
+#include "thread.hpp"
 
 struct thread_notifiers {
        struct lttng_pipe *quit_pipe;
diff --git a/src/bin/lttng-sessiond/agent-thread.h b/src/bin/lttng-sessiond/agent-thread.h
deleted file mode 100644 (file)
index d84ea61..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <stdbool.h>
-
-#ifndef LTTNG_SESSIOND_AGENT_THREAD_H
-#define LTTNG_SESSIOND_AGENT_THREAD_H
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-bool launch_agent_management_thread(void);
-bool agent_tracing_is_enabled(void);
-
-#else /* HAVE_LIBLTTNG_UST_CTL */
-
-static inline
-bool launch_agent_management_thread(void)
-{
-       return true;
-}
-
-static inline
-bool agent_tracing_is_enabled(void)
-{
-       return false;
-}
-
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* LTTNG_SESSIOND_AGENT_THREAD_H */
diff --git a/src/bin/lttng-sessiond/agent-thread.hpp b/src/bin/lttng-sessiond/agent-thread.hpp
new file mode 100644 (file)
index 0000000..d84ea61
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <stdbool.h>
+
+#ifndef LTTNG_SESSIOND_AGENT_THREAD_H
+#define LTTNG_SESSIOND_AGENT_THREAD_H
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+bool launch_agent_management_thread(void);
+bool agent_tracing_is_enabled(void);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+static inline
+bool launch_agent_management_thread(void)
+{
+       return true;
+}
+
+static inline
+bool agent_tracing_is_enabled(void)
+{
+       return false;
+}
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* LTTNG_SESSIOND_AGENT_THREAD_H */
index 5be61dc366fdb66b8ea41e6c3fc74cb4a00a8445..c42cabd2105bde8137f6efdfb9a78f6bc633e549 100644 (file)
 #include <urcu/rculist.h>
 
 #include <lttng/event-rule/event-rule.h>
-#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/event-rule-internal.hpp>
 #include <lttng/event-rule/jul-logging.h>
 #include <lttng/event-rule/log4j-logging.h>
 #include <lttng/event-rule/python-logging.h>
 #include <lttng/condition/condition.h>
 #include <lttng/condition/event-rule-matches.h>
-#include <lttng/domain-internal.h>
-#include <lttng/log-level-rule-internal.h>
+#include <lttng/domain-internal.hpp>
+#include <lttng/log-level-rule-internal.hpp>
 
-#include <common/common.h>
-#include <common/sessiond-comm/agent.h>
+#include <common/common.hpp>
+#include <common/sessiond-comm/agent.hpp>
 
-#include <common/compat/endian.h>
+#include <common/compat/endian.hpp>
 
-#include "agent.h"
-#include "ust-app.h"
-#include "utils.h"
-#include "common/error.h"
+#include "agent.hpp"
+#include "ust-app.hpp"
+#include "utils.hpp"
+#include "common/error.hpp"
 
 typedef enum lttng_event_rule_status (*event_rule_logging_get_name_pattern)(
                const struct lttng_event_rule *rule, const char **pattern);
diff --git a/src/bin/lttng-sessiond/agent.h b/src/bin/lttng-sessiond/agent.h
deleted file mode 100644 (file)
index b0a4fa8..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_SESSIOND_AGENT_H
-#define LTTNG_SESSIOND_AGENT_H
-
-#include <inttypes.h>
-
-#include <common/hashtable/hashtable.h>
-#include <lttng/lttng.h>
-
-/* Agent protocol version that is verified during the agent registration. */
-#define AGENT_MAJOR_VERSION            2
-#define AGENT_MINOR_VERSION            0
-
-/*
- * Hash table that contains the agent app created upon registration indexed by
- * socket. Global to the session daemon.
- */
-extern struct lttng_ht *the_agent_apps_ht_by_sock;
-
-/*
- * Hash table that contains the trigger agents by domain */
-extern struct lttng_ht *the_trigger_agents_ht_by_domain;
-
-struct agent_ht_key {
-       const char *name;
-       int loglevel_value;
-       enum lttng_loglevel_type loglevel_type;
-       const char *filter_expression;
-};
-
-/*
- * Registration message payload from an agent application. The PID is used to
- * find back the corresponding UST app object so both socket can be linked.
- */
-struct agent_register_msg {
-       /* This maps to a lttng_domain_type. */
-       uint32_t domain;
-       uint32_t pid;
-       uint32_t major_version;
-       uint32_t minor_version;
-};
-
-/*
- * Agent application object created after a successful registration. This
- * object is linked to its associated UST app by their PID through hash table
- * lookups.
- */
-struct agent_app {
-       /*
-        * PID sent during registration of an agent application.
-        */
-       pid_t pid;
-
-       /* Domain of the application. */
-       enum lttng_domain_type domain;
-
-       /*
-        * AGENT TCP socket that was created upon registration.
-        */
-       struct lttcomm_sock *sock;
-
-       /* Initialized with the AGENT sock value. */
-       struct lttng_ht_node_ulong node;
-};
-
-/*
- * Agent event representation.
- * Accesses to this structure are protected by the session list lock.
- */
-struct agent_event {
-       /* Name of the event. */
-       char name[LTTNG_SYMBOL_NAME_LEN];
-       int loglevel_value;
-       enum lttng_loglevel_type loglevel_type;
-
-       /*
-        * Tells if the event is enabled or not on the agent. While this can be
-        * implicitly tested as a boolean, it is in fact a reference count and
-        * the AGENT_EVENT_IS_ENABLED macro should be used to prevent accidental
-        * comparisons to non-zero literals (e.g. '1').
-        *
-        * Multiple triggers and events can map to the same agent event as it
-        * is merely a "filter" in front of a user space tracer enabler.
-        *
-        * This count is updated to ensure an event is only disabled when all
-        * matching enablers are disabled.
-        */
-       unsigned int enabled_count;
-
-       /* Hash table node of the agent domain object. */
-       struct lttng_ht_node_str node;
-
-       /* Filter associated with the event. NULL if none. */
-       struct lttng_bytecode *filter;
-       char *filter_expression;
-       struct lttng_event_exclusion *exclusion;
-};
-
-#define AGENT_EVENT_IS_ENABLED(agent_event) (!!agent_event->enabled_count)
-
-/*
- * Agent object containing events enabled/disabled for a given domain in a
- * scope. The scope is typically a session, but can also be "global" in the
- * context of event notifiers: see event_notifiers_find_agent().
- */
-struct agent {
-       /*
-        * This indicates if that domain is being used meaning if at least one
-        * event has been at some point in time added to it. This is used so when
-        * listing domains for a session, we can tell or not if the agent is
-        * actually enabled.
-        */
-       unsigned int being_used:1;
-
-       /* What domain this agent is. */
-       enum lttng_domain_type domain;
-
-       /* Contains event indexed by name. */
-       struct lttng_ht *events;
-
-       /* Application context list (struct agent_app_ctx). */
-       struct cds_list_head app_ctx_list;
-
-       /* Node used for the hash table indexed by domain type. */
-       struct lttng_ht_node_u64 node;
-};
-
-/* Allocate agent apps hash table */
-int agent_app_ht_alloc(void);
-/* Clean-up agent apps hash table */
-void agent_app_ht_clean(void);
-
-/* Initialize an already allocated agent domain. */
-int agent_init(struct agent *agt);
-struct agent *agent_create(enum lttng_domain_type domain);
-void agent_destroy(struct agent *agt);
-void agent_add(struct agent *agt, struct lttng_ht *ht);
-
-/* Agent event API. */
-struct agent_event *agent_create_event(const char *name,
-               enum lttng_loglevel_type loglevel_type, int loglevel_value,
-               struct lttng_bytecode *filter,
-               char *filter_expression);
-void agent_add_event(struct agent_event *event, struct agent *agt);
-
-struct agent_event *agent_find_event(const char *name,
-               enum lttng_loglevel_type loglevel_type,
-               int loglevel_value,
-               const char *filter_expression,
-               struct agent *agt);
-void agent_find_events_by_name(const char *name, struct agent *agt,
-               struct lttng_ht_iter* iter);
-void agent_event_next_duplicate(const char *name,
-               struct agent *agt, struct lttng_ht_iter* iter);
-void agent_delete_event(struct agent_event *event, struct agent *agt);
-void agent_destroy_event(struct agent_event *event);
-
-/* Agent context API.*/
-int agent_enable_context(const struct lttng_event_context *ctx,
-               enum lttng_domain_type domain);
-int agent_add_context(const struct lttng_event_context *ctx,
-               struct agent *agt);
-
-/* Agent app API. */
-struct agent_app *agent_create_app(pid_t pid, enum lttng_domain_type domain,
-               struct lttcomm_sock *sock);
-void agent_add_app(struct agent_app *app);
-void agent_delete_app(struct agent_app *app);
-struct agent_app *agent_find_app_by_sock(int sock);
-void agent_destroy_app(struct agent_app *app);
-void agent_destroy_app_by_sock(int sock);
-int agent_send_registration_done(struct agent_app *app);
-
-/* Agent action API */
-int agent_enable_event(struct agent_event *event,
-               enum lttng_domain_type domain);
-int agent_disable_event(struct agent_event *event,
-               enum lttng_domain_type domain);
-void agent_update(const struct agent *agt, const struct agent_app *app);
-int agent_list_events(struct lttng_event **events,
-               enum lttng_domain_type domain);
-
-struct agent_event *agent_find_event_by_trigger(
-               const struct lttng_trigger *trigger, struct agent *agt);
-
-/* Global event notifier per-domain agents. */
-struct agent *agent_find_by_event_notifier_domain(
-               enum lttng_domain_type domain_type);
-void agent_by_event_notifier_domain_ht_destroy(void);
-int agent_by_event_notifier_domain_ht_create(void);
-
-#endif /* LTTNG_SESSIOND_AGENT_H */
diff --git a/src/bin/lttng-sessiond/agent.hpp b/src/bin/lttng-sessiond/agent.hpp
new file mode 100644 (file)
index 0000000..2ad42c3
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_SESSIOND_AGENT_H
+#define LTTNG_SESSIOND_AGENT_H
+
+#include <inttypes.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <lttng/lttng.h>
+
+/* Agent protocol version that is verified during the agent registration. */
+#define AGENT_MAJOR_VERSION            2
+#define AGENT_MINOR_VERSION            0
+
+/*
+ * Hash table that contains the agent app created upon registration indexed by
+ * socket. Global to the session daemon.
+ */
+extern struct lttng_ht *the_agent_apps_ht_by_sock;
+
+/*
+ * Hash table that contains the trigger agents by domain */
+extern struct lttng_ht *the_trigger_agents_ht_by_domain;
+
+struct agent_ht_key {
+       const char *name;
+       int loglevel_value;
+       enum lttng_loglevel_type loglevel_type;
+       const char *filter_expression;
+};
+
+/*
+ * Registration message payload from an agent application. The PID is used to
+ * find back the corresponding UST app object so both socket can be linked.
+ */
+struct agent_register_msg {
+       /* This maps to a lttng_domain_type. */
+       uint32_t domain;
+       uint32_t pid;
+       uint32_t major_version;
+       uint32_t minor_version;
+};
+
+/*
+ * Agent application object created after a successful registration. This
+ * object is linked to its associated UST app by their PID through hash table
+ * lookups.
+ */
+struct agent_app {
+       /*
+        * PID sent during registration of an agent application.
+        */
+       pid_t pid;
+
+       /* Domain of the application. */
+       enum lttng_domain_type domain;
+
+       /*
+        * AGENT TCP socket that was created upon registration.
+        */
+       struct lttcomm_sock *sock;
+
+       /* Initialized with the AGENT sock value. */
+       struct lttng_ht_node_ulong node;
+};
+
+/*
+ * Agent event representation.
+ * Accesses to this structure are protected by the session list lock.
+ */
+struct agent_event {
+       /* Name of the event. */
+       char name[LTTNG_SYMBOL_NAME_LEN];
+       int loglevel_value;
+       enum lttng_loglevel_type loglevel_type;
+
+       /*
+        * Tells if the event is enabled or not on the agent. While this can be
+        * implicitly tested as a boolean, it is in fact a reference count and
+        * the AGENT_EVENT_IS_ENABLED macro should be used to prevent accidental
+        * comparisons to non-zero literals (e.g. '1').
+        *
+        * Multiple triggers and events can map to the same agent event as it
+        * is merely a "filter" in front of a user space tracer enabler.
+        *
+        * This count is updated to ensure an event is only disabled when all
+        * matching enablers are disabled.
+        */
+       unsigned int enabled_count;
+
+       /* Hash table node of the agent domain object. */
+       struct lttng_ht_node_str node;
+
+       /* Filter associated with the event. NULL if none. */
+       struct lttng_bytecode *filter;
+       char *filter_expression;
+       struct lttng_event_exclusion *exclusion;
+};
+
+#define AGENT_EVENT_IS_ENABLED(agent_event) (!!agent_event->enabled_count)
+
+/*
+ * Agent object containing events enabled/disabled for a given domain in a
+ * scope. The scope is typically a session, but can also be "global" in the
+ * context of event notifiers: see event_notifiers_find_agent().
+ */
+struct agent {
+       /*
+        * This indicates if that domain is being used meaning if at least one
+        * event has been at some point in time added to it. This is used so when
+        * listing domains for a session, we can tell or not if the agent is
+        * actually enabled.
+        */
+       unsigned int being_used:1;
+
+       /* What domain this agent is. */
+       enum lttng_domain_type domain;
+
+       /* Contains event indexed by name. */
+       struct lttng_ht *events;
+
+       /* Application context list (struct agent_app_ctx). */
+       struct cds_list_head app_ctx_list;
+
+       /* Node used for the hash table indexed by domain type. */
+       struct lttng_ht_node_u64 node;
+};
+
+/* Allocate agent apps hash table */
+int agent_app_ht_alloc(void);
+/* Clean-up agent apps hash table */
+void agent_app_ht_clean(void);
+
+/* Initialize an already allocated agent domain. */
+int agent_init(struct agent *agt);
+struct agent *agent_create(enum lttng_domain_type domain);
+void agent_destroy(struct agent *agt);
+void agent_add(struct agent *agt, struct lttng_ht *ht);
+
+/* Agent event API. */
+struct agent_event *agent_create_event(const char *name,
+               enum lttng_loglevel_type loglevel_type, int loglevel_value,
+               struct lttng_bytecode *filter,
+               char *filter_expression);
+void agent_add_event(struct agent_event *event, struct agent *agt);
+
+struct agent_event *agent_find_event(const char *name,
+               enum lttng_loglevel_type loglevel_type,
+               int loglevel_value,
+               const char *filter_expression,
+               struct agent *agt);
+void agent_find_events_by_name(const char *name, struct agent *agt,
+               struct lttng_ht_iter* iter);
+void agent_event_next_duplicate(const char *name,
+               struct agent *agt, struct lttng_ht_iter* iter);
+void agent_delete_event(struct agent_event *event, struct agent *agt);
+void agent_destroy_event(struct agent_event *event);
+
+/* Agent context API.*/
+int agent_enable_context(const struct lttng_event_context *ctx,
+               enum lttng_domain_type domain);
+int agent_add_context(const struct lttng_event_context *ctx,
+               struct agent *agt);
+
+/* Agent app API. */
+struct agent_app *agent_create_app(pid_t pid, enum lttng_domain_type domain,
+               struct lttcomm_sock *sock);
+void agent_add_app(struct agent_app *app);
+void agent_delete_app(struct agent_app *app);
+struct agent_app *agent_find_app_by_sock(int sock);
+void agent_destroy_app(struct agent_app *app);
+void agent_destroy_app_by_sock(int sock);
+int agent_send_registration_done(struct agent_app *app);
+
+/* Agent action API */
+int agent_enable_event(struct agent_event *event,
+               enum lttng_domain_type domain);
+int agent_disable_event(struct agent_event *event,
+               enum lttng_domain_type domain);
+void agent_update(const struct agent *agt, const struct agent_app *app);
+int agent_list_events(struct lttng_event **events,
+               enum lttng_domain_type domain);
+
+struct agent_event *agent_find_event_by_trigger(
+               const struct lttng_trigger *trigger, struct agent *agt);
+
+/* Global event notifier per-domain agents. */
+struct agent *agent_find_by_event_notifier_domain(
+               enum lttng_domain_type domain_type);
+void agent_by_event_notifier_domain_ht_destroy(void);
+int agent_by_event_notifier_domain_ht_create(void);
+
+#endif /* LTTNG_SESSIOND_AGENT_H */
index aca8ec1f227f54cc9f8fded46d8924c4b53841be..b0f6f4f846a7f69664652c0cc7c3a51805ddbe3f 100644 (file)
@@ -8,15 +8,15 @@
 #define _LGPL_SOURCE
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/hashtable/utils.h>
-
-#include "buffer-registry.h"
-#include "fd-limit.h"
-#include "ust-consumer.h"
-#include "lttng-ust-ctl.h"
-#include "lttng-ust-error.h"
-#include "utils.h"
+#include <common/common.hpp>
+#include <common/hashtable/utils.hpp>
+
+#include "buffer-registry.hpp"
+#include "fd-limit.hpp"
+#include "ust-consumer.hpp"
+#include "lttng-ust-ctl.hpp"
+#include "lttng-ust-error.hpp"
+#include "utils.hpp"
 
 /*
  * Set in main.c during initialization process of the daemon. This contains
diff --git a/src/bin/lttng-sessiond/buffer-registry.h b/src/bin/lttng-sessiond/buffer-registry.h
deleted file mode 100644 (file)
index 440493d..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_BUFFER_REGISTRY_H
-#define LTTNG_BUFFER_REGISTRY_H
-
-#include <stdint.h>
-#include <urcu/list.h>
-
-#include <lttng/lttng.h>
-#include <common/hashtable/hashtable.h>
-
-#include "consumer.h"
-#include "lttng-ust-ctl.h"
-#include "ust-registry.h"
-
-struct buffer_reg_stream {
-       struct cds_list_head lnode;
-       union {
-               /* Original object data that MUST be copied over. */
-               struct lttng_ust_abi_object_data *ust;
-       } obj;
-};
-
-struct buffer_reg_channel {
-       /* This key is the same as a tracing channel key. */
-       uint32_t key;
-       /* Key of the channel on the consumer side. */
-       uint64_t consumer_key;
-       /* Stream registry object of this channel registry. */
-       struct cds_list_head streams;
-       /* Total number of stream in the list. */
-       uint64_t stream_count;
-       /* Used to ensure mutual exclusion to the stream's list. */
-       pthread_mutex_t stream_list_lock;
-       /* Node for hash table usage. */
-       struct lttng_ht_node_u64 node;
-       /* Size of subbuffers in this channel. */
-       size_t subbuf_size;
-       /* Number of subbuffers per stream. */
-       size_t num_subbuf;
-       union {
-               /* Original object data that MUST be copied over. */
-               struct lttng_ust_abi_object_data *ust;
-       } obj;
-};
-
-struct buffer_reg_session {
-       /* Registry per domain. */
-       union {
-               struct ust_registry_session *ust;
-       } reg;
-
-       /* Contains buffer registry channel indexed by tracing channel key. */
-       struct lttng_ht *channels;
-};
-
-/*
- * Registry object for per UID buffers.
- */
-struct buffer_reg_uid {
-       /*
-        * Keys to match this object in a hash table. The following three variables
-        * identify a unique per UID buffer registry.
-        */
-       uint64_t session_id;    /* Unique tracing session id. */
-       int bits_per_long;      /* ABI */
-       uid_t uid;                      /* Owner. */
-
-       enum lttng_domain_type domain;
-       struct buffer_reg_session *registry;
-
-       /* Indexed by session id. */
-       struct lttng_ht_node_u64 node;
-       /* Node of a linked list used to teardown object at a destroy session. */
-       struct cds_list_head lnode;
-
-       char root_shm_path[PATH_MAX];
-       char shm_path[PATH_MAX];
-};
-
-/*
- * Registry object for per PID buffers.
- */
-struct buffer_reg_pid {
-       uint64_t session_id;
-
-       struct buffer_reg_session *registry;
-
-       /* Indexed by session id. */
-       struct lttng_ht_node_u64 node;
-
-       char root_shm_path[PATH_MAX];
-       char shm_path[PATH_MAX];
-};
-
-/* Buffer registry per UID. */
-void buffer_reg_init_uid_registry(void);
-int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid,
-               enum lttng_domain_type domain, struct buffer_reg_uid **regp,
-               const char *root_shm_path, const char *shm_path);
-void buffer_reg_uid_add(struct buffer_reg_uid *reg);
-struct buffer_reg_uid *buffer_reg_uid_find(uint64_t session_id,
-               uint32_t bits_per_long, uid_t uid);
-void buffer_reg_uid_remove(struct buffer_reg_uid *regp);
-void buffer_reg_uid_destroy(struct buffer_reg_uid *regp,
-               struct consumer_output *consumer);
-
-/* Buffer registry per PID. */
-void buffer_reg_init_pid_registry(void);
-int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp,
-               const char *root_shm_path, const char *shm_path);
-void buffer_reg_pid_add(struct buffer_reg_pid *reg);
-struct buffer_reg_pid *buffer_reg_pid_find(uint64_t session_id);
-void buffer_reg_pid_remove(struct buffer_reg_pid *regp);
-void buffer_reg_pid_destroy(struct buffer_reg_pid *regp);
-
-/* Channel */
-int buffer_reg_channel_create(uint64_t key, struct buffer_reg_channel **regp);
-void buffer_reg_channel_add(struct buffer_reg_session *session,
-               struct buffer_reg_channel *channel);
-struct buffer_reg_channel *buffer_reg_channel_find(uint64_t key,
-               struct buffer_reg_uid *reg);
-void buffer_reg_channel_remove(struct buffer_reg_session *session,
-               struct buffer_reg_channel *regp);
-void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
-               enum lttng_domain_type domain);
-
-/* Stream */
-int buffer_reg_stream_create(struct buffer_reg_stream **regp);
-void buffer_reg_stream_add(struct buffer_reg_stream *stream,
-               struct buffer_reg_channel *channel);
-void buffer_reg_stream_destroy(struct buffer_reg_stream *regp,
-               enum lttng_domain_type domain);
-
-/* Global registry. */
-void buffer_reg_destroy_registries(void);
-
-int buffer_reg_uid_consumer_channel_key(
-               struct cds_list_head *buffer_reg_uid_list,
-               uint64_t chan_key, uint64_t *consumer_chan_key);
-
-#endif /* LTTNG_BUFFER_REGISTRY_H */
diff --git a/src/bin/lttng-sessiond/buffer-registry.hpp b/src/bin/lttng-sessiond/buffer-registry.hpp
new file mode 100644 (file)
index 0000000..a06be60
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_BUFFER_REGISTRY_H
+#define LTTNG_BUFFER_REGISTRY_H
+
+#include <stdint.h>
+#include <urcu/list.h>
+
+#include <lttng/lttng.h>
+#include <common/hashtable/hashtable.hpp>
+
+#include "consumer.hpp"
+#include "lttng-ust-ctl.hpp"
+#include "ust-registry.hpp"
+
+struct buffer_reg_stream {
+       struct cds_list_head lnode;
+       union {
+               /* Original object data that MUST be copied over. */
+               struct lttng_ust_abi_object_data *ust;
+       } obj;
+};
+
+struct buffer_reg_channel {
+       /* This key is the same as a tracing channel key. */
+       uint32_t key;
+       /* Key of the channel on the consumer side. */
+       uint64_t consumer_key;
+       /* Stream registry object of this channel registry. */
+       struct cds_list_head streams;
+       /* Total number of stream in the list. */
+       uint64_t stream_count;
+       /* Used to ensure mutual exclusion to the stream's list. */
+       pthread_mutex_t stream_list_lock;
+       /* Node for hash table usage. */
+       struct lttng_ht_node_u64 node;
+       /* Size of subbuffers in this channel. */
+       size_t subbuf_size;
+       /* Number of subbuffers per stream. */
+       size_t num_subbuf;
+       union {
+               /* Original object data that MUST be copied over. */
+               struct lttng_ust_abi_object_data *ust;
+       } obj;
+};
+
+struct buffer_reg_session {
+       /* Registry per domain. */
+       union {
+               struct ust_registry_session *ust;
+       } reg;
+
+       /* Contains buffer registry channel indexed by tracing channel key. */
+       struct lttng_ht *channels;
+};
+
+/*
+ * Registry object for per UID buffers.
+ */
+struct buffer_reg_uid {
+       /*
+        * Keys to match this object in a hash table. The following three variables
+        * identify a unique per UID buffer registry.
+        */
+       uint64_t session_id;    /* Unique tracing session id. */
+       int bits_per_long;      /* ABI */
+       uid_t uid;                      /* Owner. */
+
+       enum lttng_domain_type domain;
+       struct buffer_reg_session *registry;
+
+       /* Indexed by session id. */
+       struct lttng_ht_node_u64 node;
+       /* Node of a linked list used to teardown object at a destroy session. */
+       struct cds_list_head lnode;
+
+       char root_shm_path[PATH_MAX];
+       char shm_path[PATH_MAX];
+};
+
+/*
+ * Registry object for per PID buffers.
+ */
+struct buffer_reg_pid {
+       uint64_t session_id;
+
+       struct buffer_reg_session *registry;
+
+       /* Indexed by session id. */
+       struct lttng_ht_node_u64 node;
+
+       char root_shm_path[PATH_MAX];
+       char shm_path[PATH_MAX];
+};
+
+/* Buffer registry per UID. */
+void buffer_reg_init_uid_registry(void);
+int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid,
+               enum lttng_domain_type domain, struct buffer_reg_uid **regp,
+               const char *root_shm_path, const char *shm_path);
+void buffer_reg_uid_add(struct buffer_reg_uid *reg);
+struct buffer_reg_uid *buffer_reg_uid_find(uint64_t session_id,
+               uint32_t bits_per_long, uid_t uid);
+void buffer_reg_uid_remove(struct buffer_reg_uid *regp);
+void buffer_reg_uid_destroy(struct buffer_reg_uid *regp,
+               struct consumer_output *consumer);
+
+/* Buffer registry per PID. */
+void buffer_reg_init_pid_registry(void);
+int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp,
+               const char *root_shm_path, const char *shm_path);
+void buffer_reg_pid_add(struct buffer_reg_pid *reg);
+struct buffer_reg_pid *buffer_reg_pid_find(uint64_t session_id);
+void buffer_reg_pid_remove(struct buffer_reg_pid *regp);
+void buffer_reg_pid_destroy(struct buffer_reg_pid *regp);
+
+/* Channel */
+int buffer_reg_channel_create(uint64_t key, struct buffer_reg_channel **regp);
+void buffer_reg_channel_add(struct buffer_reg_session *session,
+               struct buffer_reg_channel *channel);
+struct buffer_reg_channel *buffer_reg_channel_find(uint64_t key,
+               struct buffer_reg_uid *reg);
+void buffer_reg_channel_remove(struct buffer_reg_session *session,
+               struct buffer_reg_channel *regp);
+void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
+               enum lttng_domain_type domain);
+
+/* Stream */
+int buffer_reg_stream_create(struct buffer_reg_stream **regp);
+void buffer_reg_stream_add(struct buffer_reg_stream *stream,
+               struct buffer_reg_channel *channel);
+void buffer_reg_stream_destroy(struct buffer_reg_stream *regp,
+               enum lttng_domain_type domain);
+
+/* Global registry. */
+void buffer_reg_destroy_registries(void);
+
+int buffer_reg_uid_consumer_channel_key(
+               struct cds_list_head *buffer_reg_uid_list,
+               uint64_t chan_key, uint64_t *consumer_chan_key);
+
+#endif /* LTTNG_BUFFER_REGISTRY_H */
index 0f150972c74f79d74bf01e0dc06b3dee601f2b15..3f1525f8a2165f0381d7e76e9a2c942191da7b3a 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-
-#include "channel.h"
-#include "lttng-sessiond.h"
-#include "kernel.h"
-#include "lttng-ust-ctl.h"
-#include "lttng-ust-error.h"
-#include "utils.h"
-#include "ust-app.h"
-#include "agent.h"
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+
+#include "channel.hpp"
+#include "lttng-sessiond.hpp"
+#include "kernel.hpp"
+#include "lttng-ust-ctl.hpp"
+#include "lttng-ust-error.hpp"
+#include "utils.hpp"
+#include "ust-app.hpp"
+#include "agent.hpp"
 
 /*
  * Return allocated channel attributes.
diff --git a/src/bin/lttng-sessiond/channel.h b/src/bin/lttng-sessiond/channel.h
deleted file mode 100644 (file)
index ef3100e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_CHANNEL_H
-#define _LTT_CHANNEL_H
-
-#include <lttng/lttng.h>
-
-#include "trace-kernel.h"
-#include "trace-ust.h"
-
-int channel_kernel_disable(struct ltt_kernel_session *ksession,
-               char *channel_name);
-int channel_kernel_enable(struct ltt_kernel_session *ksession,
-               struct ltt_kernel_channel *kchan);
-int channel_kernel_create(struct ltt_kernel_session *ksession,
-               struct lttng_channel *chan, int kernel_pipe);
-
-struct lttng_channel *channel_new_default_attr(int domain,
-               enum lttng_buffer_type type);
-void channel_attr_destroy(struct lttng_channel *channel);
-
-int channel_ust_create(struct ltt_ust_session *usess,
-               struct lttng_channel *attr, enum lttng_buffer_type type);
-int channel_ust_enable(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan);
-int channel_ust_disable(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan);
-
-#endif /* _LTT_CHANNEL_H */
diff --git a/src/bin/lttng-sessiond/channel.hpp b/src/bin/lttng-sessiond/channel.hpp
new file mode 100644 (file)
index 0000000..3a9bc09
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_CHANNEL_H
+#define _LTT_CHANNEL_H
+
+#include <lttng/lttng.h>
+
+#include "trace-kernel.hpp"
+#include "trace-ust.hpp"
+
+int channel_kernel_disable(struct ltt_kernel_session *ksession,
+               char *channel_name);
+int channel_kernel_enable(struct ltt_kernel_session *ksession,
+               struct ltt_kernel_channel *kchan);
+int channel_kernel_create(struct ltt_kernel_session *ksession,
+               struct lttng_channel *chan, int kernel_pipe);
+
+struct lttng_channel *channel_new_default_attr(int domain,
+               enum lttng_buffer_type type);
+void channel_attr_destroy(struct lttng_channel *channel);
+
+int channel_ust_create(struct ltt_ust_session *usess,
+               struct lttng_channel *attr, enum lttng_buffer_type type);
+int channel_ust_enable(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan);
+int channel_ust_disable(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan);
+
+#endif /* _LTT_CHANNEL_H */
index 1239c5f2467a7db22537de7eb1f4fd751baefe0f..d22abfec10a73cd12cde6573c182c063c144efef 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/utils.h>
-
-#include "clear.h"
-#include "session.h"
-#include "ust-app.h"
-#include "kernel.h"
-#include "cmd.h"
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/utils.hpp>
+
+#include "clear.hpp"
+#include "session.hpp"
+#include "ust-app.hpp"
+#include "kernel.hpp"
+#include "cmd.hpp"
 
 struct cmd_clear_session_reply_context {
        int reply_sock_fd;
diff --git a/src/bin/lttng-sessiond/clear.h b/src/bin/lttng-sessiond/clear.h
deleted file mode 100644 (file)
index e788ec7..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef CLEAR_H
-#define CLEAR_H
-
-#include "session.h"
-
-int cmd_clear_session(struct ltt_session *session, int *sock_fd);
-
-#endif /* CLEAT_H */
diff --git a/src/bin/lttng-sessiond/clear.hpp b/src/bin/lttng-sessiond/clear.hpp
new file mode 100644 (file)
index 0000000..aca20d3
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef CLEAR_H
+#define CLEAR_H
+
+#include "session.hpp"
+
+int cmd_clear_session(struct ltt_session *session, int *sock_fd);
+
+#endif /* CLEAT_H */
index 154fa4a3633f585af655a7697edbb68e128f787d..bc5f31afc26318a6b061bf7e5f4f4d64f3bedc97 100644 (file)
@@ -7,42 +7,42 @@
  *
  */
 
-#include "common/buffer-view.h"
-#include "common/compat/socket.h"
-#include "common/dynamic-array.h"
-#include "common/dynamic-buffer.h"
-#include "common/fd-handle.h"
-#include "common/payload-view.h"
-#include "common/payload.h"
-#include "common/sessiond-comm/sessiond-comm.h"
+#include "common/buffer-view.hpp"
+#include "common/compat/socket.hpp"
+#include "common/dynamic-array.hpp"
+#include "common/dynamic-buffer.hpp"
+#include "common/fd-handle.hpp"
+#include "common/payload-view.hpp"
+#include "common/payload.hpp"
+#include "common/sessiond-comm/sessiond-comm.hpp"
 #include "lttng/lttng-error.h"
 #include "lttng/tracker.h"
-#include <common/compat/getenv.h>
-#include <common/tracker.h>
-#include <common/unix.h>
-#include <common/utils.h>
-#include <lttng/error-query-internal.h>
-#include <lttng/event-internal.h>
-#include <lttng/session-descriptor-internal.h>
-#include <lttng/session-internal.h>
-#include <lttng/userspace-probe-internal.h>
+#include <common/compat/getenv.hpp>
+#include <common/tracker.hpp>
+#include <common/unix.hpp>
+#include <common/utils.hpp>
+#include <lttng/error-query-internal.hpp>
+#include <lttng/event-internal.hpp>
+#include <lttng/session-descriptor-internal.hpp>
+#include <lttng/session-internal.hpp>
+#include <lttng/userspace-probe-internal.hpp>
 #include <pthread.h>
 #include <signal.h>
 #include <stddef.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "agent-thread.h"
-#include "clear.h"
-#include "client.h"
-#include "cmd.h"
-#include "health-sessiond.h"
-#include "kernel.h"
-#include "lttng-sessiond.h"
-#include "manage-consumer.h"
-#include "save.h"
-#include "testpoint.h"
-#include "utils.h"
+#include "agent-thread.hpp"
+#include "clear.hpp"
+#include "client.hpp"
+#include "cmd.hpp"
+#include "health-sessiond.hpp"
+#include "kernel.hpp"
+#include "lttng-sessiond.hpp"
+#include "manage-consumer.hpp"
+#include "save.hpp"
+#include "testpoint.hpp"
+#include "utils.hpp"
 
 static bool is_root;
 
diff --git a/src/bin/lttng-sessiond/client.h b/src/bin/lttng-sessiond/client.h
deleted file mode 100644 (file)
index b80d56c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef CLIENT_SESSIOND_H
-#define CLIENT_SESSIOND_H
-
-#include "thread.h"
-
-struct lttng_thread *launch_client_thread(void);
-
-#endif /* CLIENT_SESSIOND_H */
diff --git a/src/bin/lttng-sessiond/client.hpp b/src/bin/lttng-sessiond/client.hpp
new file mode 100644 (file)
index 0000000..f49bfc6
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef CLIENT_SESSIOND_H
+#define CLIENT_SESSIOND_H
+
+#include "thread.hpp"
+
+struct lttng_thread *launch_client_thread(void);
+
+#endif /* CLIENT_SESSIOND_H */
index b4bd6b43fca8826850a83d4f0fd6b0ec4579b735..9cab0141f71bce53179ddc923f658fd2576d1334 100644 (file)
 #include <urcu/list.h>
 #include <urcu/uatomic.h>
 
-#include <common/buffer-view.h>
-#include <common/common.h>
-#include <common/compat/string.h>
-#include <common/defaults.h>
-#include <common/dynamic-buffer.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/relayd/relayd.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/string-utils/string-utils.h>
-#include <common/trace-chunk.h>
-#include <common/utils.h>
-#include <lttng/action/action-internal.h>
+#include <common/buffer-view.hpp>
+#include <common/common.hpp>
+#include <common/compat/string.hpp>
+#include <common/defaults.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/relayd/relayd.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/utils.hpp>
+#include <lttng/action/action-internal.hpp>
 #include <lttng/action/action.h>
-#include <lttng/channel-internal.h>
+#include <lttng/channel-internal.hpp>
 #include <lttng/channel.h>
-#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/condition-internal.hpp>
 #include <lttng/condition/condition.h>
-#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/condition/event-rule-matches-internal.hpp>
 #include <lttng/condition/event-rule-matches.h>
-#include <lttng/error-query-internal.h>
-#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/error-query-internal.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
 #include <lttng/event-rule/event-rule.h>
-#include <lttng/location-internal.h>
+#include <lttng/location-internal.hpp>
 #include <lttng/lttng-error.h>
-#include <lttng/rotate-internal.h>
-#include <lttng/session-descriptor-internal.h>
-#include <lttng/session-internal.h>
+#include <lttng/rotate-internal.hpp>
+#include <lttng/session-descriptor-internal.hpp>
+#include <lttng/session-internal.hpp>
 #include <lttng/tracker.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/userspace-probe-internal.h>
-
-#include "agent-thread.h"
-#include "agent.h"
-#include "buffer-registry.h"
-#include "channel.h"
-#include "cmd.h"
-#include "consumer.h"
-#include "event-notifier-error-accounting.h"
-#include "event.h"
-#include "health-sessiond.h"
-#include "kernel-consumer.h"
-#include "kernel.h"
-#include "lttng-sessiond.h"
-#include "lttng-syscall.h"
-#include "notification-thread-commands.h"
-#include "notification-thread.h"
-#include "rotate.h"
-#include "rotation-thread.h"
-#include "session.h"
-#include "timer.h"
-#include "tracker.h"
-#include "utils.h"
+#include <lttng/trigger/trigger-internal.hpp>
+#include <lttng/userspace-probe-internal.hpp>
+
+#include "agent-thread.hpp"
+#include "agent.hpp"
+#include "buffer-registry.hpp"
+#include "channel.hpp"
+#include "cmd.hpp"
+#include "consumer.hpp"
+#include "event-notifier-error-accounting.hpp"
+#include "event.hpp"
+#include "health-sessiond.hpp"
+#include "kernel-consumer.hpp"
+#include "kernel.hpp"
+#include "lttng-sessiond.hpp"
+#include "lttng-syscall.hpp"
+#include "notification-thread-commands.hpp"
+#include "notification-thread.hpp"
+#include "rotate.hpp"
+#include "rotation-thread.hpp"
+#include "session.hpp"
+#include "timer.hpp"
+#include "tracker.hpp"
+#include "utils.hpp"
 
 /* Sleep for 100ms between each check for the shm path's deletion. */
 #define SESSION_DESTROY_SHM_PATH_CHECK_DELAY_US 100000
@@ -4189,7 +4189,7 @@ int ust_regenerate_metadata(struct ltt_ust_session *usess)
                                                "(err = %d)", ret);
                                goto end;
                        }
-                       cds_lfht_for_each_entry(chan->ht->ht, &iter_event.iter,
+                       cds_lfht_for_each_entry(chan->events->ht, &iter_event.iter,
                                        event, node.node) {
                                ret = ust_metadata_event_statedump(registry,
                                                chan, event);
diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h
deleted file mode 100644 (file)
index 03f7cc1..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef CMD_H
-#define CMD_H
-
-#include "context.h"
-#include "lttng-sessiond.h"
-#include "lttng/tracker.h"
-#include "session.h"
-#include <common/tracker.h>
-
-struct notification_thread_handle;
-
-/*
- * A callback (and associated user data) that should be run after a command
- * has been executed. No locks should be taken while executing this handler.
- *
- * The command's reply should not be sent until the handler has run and
- * completed successfully. On failure, the handler's return code should
- * be the only reply sent to the client.
- */
-typedef enum lttng_error_code (*completion_handler_function)(void *);
-struct cmd_completion_handler {
-       completion_handler_function run;
-       void *data;
-};
-
-/*
- * Init the command subsystem. Must be called before using any of the functions
- * above. This is called in the main() of the session daemon.
- */
-void cmd_init(void);
-
-/* Session commands */
-enum lttng_error_code cmd_create_session(struct command_ctx *cmd_ctx, int sock,
-               struct lttng_session_descriptor **return_descriptor);
-int cmd_destroy_session(struct ltt_session *session,
-               struct notification_thread_handle *notification_thread_handle,
-               int *sock_fd);
-
-/* Channel commands */
-int cmd_disable_channel(struct ltt_session *session,
-               enum lttng_domain_type domain, char *channel_name);
-int cmd_enable_channel(struct ltt_session *session,
-               const struct lttng_domain *domain, const struct lttng_channel *attr,
-               int wpipe);
-
-/* Process attribute tracker commands */
-enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy(
-               struct ltt_session *session,
-               enum lttng_domain_type domain,
-               enum lttng_process_attr process_attr,
-               enum lttng_tracking_policy *policy);
-enum lttng_error_code cmd_process_attr_tracker_set_tracking_policy(
-               struct ltt_session *session,
-               enum lttng_domain_type domain,
-               enum lttng_process_attr process_attr,
-               enum lttng_tracking_policy policy);
-enum lttng_error_code cmd_process_attr_tracker_inclusion_set_add_value(
-               struct ltt_session *session,
-               enum lttng_domain_type domain,
-               enum lttng_process_attr process_attr,
-               const struct process_attr_value *value);
-enum lttng_error_code cmd_process_attr_tracker_inclusion_set_remove_value(
-               struct ltt_session *session,
-               enum lttng_domain_type domain,
-               enum lttng_process_attr process_attr,
-               const struct process_attr_value *value);
-enum lttng_error_code cmd_process_attr_tracker_get_inclusion_set(
-               struct ltt_session *session,
-               enum lttng_domain_type domain,
-               enum lttng_process_attr process_attr,
-               struct lttng_process_attr_values **values);
-
-/* Event commands */
-int cmd_disable_event(struct ltt_session *session,
-               enum lttng_domain_type domain,
-               const char *channel_name,
-               const struct lttng_event *event);
-int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain,
-               char *channel_name, const struct lttng_event_context *ctx, int kwpipe);
-int cmd_set_filter(struct ltt_session *session, enum lttng_domain_type domain,
-               char *channel_name, struct lttng_event *event,
-               struct lttng_bytecode *bytecode);
-int cmd_enable_event(struct ltt_session *session, const struct lttng_domain *domain,
-               char *channel_name, struct lttng_event *event,
-               char *filter_expression,
-               struct lttng_bytecode *filter,
-               struct lttng_event_exclusion *exclusion,
-               int wpipe);
-
-/* Trace session action commands */
-int cmd_start_trace(struct ltt_session *session);
-int cmd_stop_trace(struct ltt_session *session);
-
-/* Consumer commands */
-int cmd_register_consumer(struct ltt_session *session,
-               enum lttng_domain_type domain,
-               const char *sock_path, struct consumer_data *cdata);
-int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri,
-               struct lttng_uri *uris);
-int cmd_setup_relayd(struct ltt_session *session);
-
-/* Listing commands */
-ssize_t cmd_list_domains(struct ltt_session *session,
-               struct lttng_domain **domains);
-ssize_t cmd_list_events(enum lttng_domain_type domain,
-               struct ltt_session *session, char *channel_name,
-               struct lttng_payload *payload);
-ssize_t cmd_list_channels(enum lttng_domain_type domain,
-               struct ltt_session *session, struct lttng_channel **channels);
-ssize_t cmd_list_domains(struct ltt_session *session,
-               struct lttng_domain **domains);
-void cmd_list_lttng_sessions(struct lttng_session *sessions,
-               size_t session_count, uid_t uid, gid_t gid);
-ssize_t cmd_list_tracepoint_fields(enum lttng_domain_type domain,
-               struct lttng_event_field **fields);
-ssize_t cmd_list_tracepoints(enum lttng_domain_type domain,
-               struct lttng_event **events);
-ssize_t cmd_snapshot_list_outputs(struct ltt_session *session,
-               struct lttng_snapshot_output **outputs);
-ssize_t cmd_list_syscalls(struct lttng_event **events);
-
-int cmd_data_pending(struct ltt_session *session);
-
-/* Snapshot */
-int cmd_snapshot_add_output(struct ltt_session *session,
-               const struct lttng_snapshot_output *output, uint32_t *id);
-int cmd_snapshot_del_output(struct ltt_session *session,
-               const struct lttng_snapshot_output *output);
-int cmd_snapshot_record(struct ltt_session *session,
-               const struct lttng_snapshot_output *output, int wait);
-
-int cmd_set_session_shm_path(struct ltt_session *session,
-               const char *shm_path);
-int cmd_regenerate_metadata(struct ltt_session *session);
-int cmd_regenerate_statedump(struct ltt_session *session);
-
-enum lttng_error_code cmd_register_trigger(
-               const struct lttng_credentials *cmd_creds,
-               struct lttng_trigger *trigger,
-               bool is_anonymous_trigger,
-               struct notification_thread_handle *notification_thread_handle,
-               struct lttng_trigger **return_trigger);
-enum lttng_error_code cmd_unregister_trigger(
-               const struct lttng_credentials *cmd_creds,
-               const struct lttng_trigger *trigger,
-               struct notification_thread_handle *notification_thread_handle);
-
-enum lttng_error_code cmd_list_triggers(struct command_ctx *cmd_ctx,
-               struct notification_thread_handle *notification_thread_handle,
-               struct lttng_triggers **return_triggers);
-enum lttng_error_code cmd_execute_error_query(const struct lttng_credentials *cmd_creds,
-               const struct lttng_error_query *query,
-               struct lttng_error_query_results **_results,
-               struct notification_thread_handle *notification_thread);
-
-int cmd_rotate_session(struct ltt_session *session,
-               struct lttng_rotate_session_return *rotate_return,
-               bool quiet_rotation,
-               enum lttng_trace_chunk_command_type command);
-int cmd_rotate_get_info(struct ltt_session *session,
-               struct lttng_rotation_get_info_return *info_return,
-               uint64_t rotate_id);
-int cmd_rotation_set_schedule(struct ltt_session *session,
-               bool activate, enum lttng_rotation_schedule_type schedule_type,
-               uint64_t value,
-               struct notification_thread_handle *notification_thread_handle);
-
-const struct cmd_completion_handler *cmd_pop_completion_handler(void);
-int start_kernel_session(struct ltt_kernel_session *ksess);
-int stop_kernel_session(struct ltt_kernel_session *ksess);
-
-#endif /* CMD_H */
diff --git a/src/bin/lttng-sessiond/cmd.hpp b/src/bin/lttng-sessiond/cmd.hpp
new file mode 100644 (file)
index 0000000..59e7902
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef CMD_H
+#define CMD_H
+
+#include "context.hpp"
+#include "lttng-sessiond.hpp"
+#include "lttng/tracker.h"
+#include "session.hpp"
+#include <common/tracker.hpp>
+
+struct notification_thread_handle;
+
+/*
+ * A callback (and associated user data) that should be run after a command
+ * has been executed. No locks should be taken while executing this handler.
+ *
+ * The command's reply should not be sent until the handler has run and
+ * completed successfully. On failure, the handler's return code should
+ * be the only reply sent to the client.
+ */
+typedef enum lttng_error_code (*completion_handler_function)(void *);
+struct cmd_completion_handler {
+       completion_handler_function run;
+       void *data;
+};
+
+/*
+ * Init the command subsystem. Must be called before using any of the functions
+ * above. This is called in the main() of the session daemon.
+ */
+void cmd_init(void);
+
+/* Session commands */
+enum lttng_error_code cmd_create_session(struct command_ctx *cmd_ctx, int sock,
+               struct lttng_session_descriptor **return_descriptor);
+int cmd_destroy_session(struct ltt_session *session,
+               struct notification_thread_handle *notification_thread_handle,
+               int *sock_fd);
+
+/* Channel commands */
+int cmd_disable_channel(struct ltt_session *session,
+               enum lttng_domain_type domain, char *channel_name);
+int cmd_enable_channel(struct ltt_session *session,
+               const struct lttng_domain *domain, const struct lttng_channel *attr,
+               int wpipe);
+
+/* Process attribute tracker commands */
+enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy(
+               struct ltt_session *session,
+               enum lttng_domain_type domain,
+               enum lttng_process_attr process_attr,
+               enum lttng_tracking_policy *policy);
+enum lttng_error_code cmd_process_attr_tracker_set_tracking_policy(
+               struct ltt_session *session,
+               enum lttng_domain_type domain,
+               enum lttng_process_attr process_attr,
+               enum lttng_tracking_policy policy);
+enum lttng_error_code cmd_process_attr_tracker_inclusion_set_add_value(
+               struct ltt_session *session,
+               enum lttng_domain_type domain,
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value);
+enum lttng_error_code cmd_process_attr_tracker_inclusion_set_remove_value(
+               struct ltt_session *session,
+               enum lttng_domain_type domain,
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value);
+enum lttng_error_code cmd_process_attr_tracker_get_inclusion_set(
+               struct ltt_session *session,
+               enum lttng_domain_type domain,
+               enum lttng_process_attr process_attr,
+               struct lttng_process_attr_values **values);
+
+/* Event commands */
+int cmd_disable_event(struct ltt_session *session,
+               enum lttng_domain_type domain,
+               const char *channel_name,
+               const struct lttng_event *event);
+int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain,
+               char *channel_name, const struct lttng_event_context *ctx, int kwpipe);
+int cmd_set_filter(struct ltt_session *session, enum lttng_domain_type domain,
+               char *channel_name, struct lttng_event *event,
+               struct lttng_bytecode *bytecode);
+int cmd_enable_event(struct ltt_session *session, const struct lttng_domain *domain,
+               char *channel_name, struct lttng_event *event,
+               char *filter_expression,
+               struct lttng_bytecode *filter,
+               struct lttng_event_exclusion *exclusion,
+               int wpipe);
+
+/* Trace session action commands */
+int cmd_start_trace(struct ltt_session *session);
+int cmd_stop_trace(struct ltt_session *session);
+
+/* Consumer commands */
+int cmd_register_consumer(struct ltt_session *session,
+               enum lttng_domain_type domain,
+               const char *sock_path, struct consumer_data *cdata);
+int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri,
+               struct lttng_uri *uris);
+int cmd_setup_relayd(struct ltt_session *session);
+
+/* Listing commands */
+ssize_t cmd_list_domains(struct ltt_session *session,
+               struct lttng_domain **domains);
+ssize_t cmd_list_events(enum lttng_domain_type domain,
+               struct ltt_session *session, char *channel_name,
+               struct lttng_payload *payload);
+ssize_t cmd_list_channels(enum lttng_domain_type domain,
+               struct ltt_session *session, struct lttng_channel **channels);
+ssize_t cmd_list_domains(struct ltt_session *session,
+               struct lttng_domain **domains);
+void cmd_list_lttng_sessions(struct lttng_session *sessions,
+               size_t session_count, uid_t uid, gid_t gid);
+ssize_t cmd_list_tracepoint_fields(enum lttng_domain_type domain,
+               struct lttng_event_field **fields);
+ssize_t cmd_list_tracepoints(enum lttng_domain_type domain,
+               struct lttng_event **events);
+ssize_t cmd_snapshot_list_outputs(struct ltt_session *session,
+               struct lttng_snapshot_output **outputs);
+ssize_t cmd_list_syscalls(struct lttng_event **events);
+
+int cmd_data_pending(struct ltt_session *session);
+
+/* Snapshot */
+int cmd_snapshot_add_output(struct ltt_session *session,
+               const struct lttng_snapshot_output *output, uint32_t *id);
+int cmd_snapshot_del_output(struct ltt_session *session,
+               const struct lttng_snapshot_output *output);
+int cmd_snapshot_record(struct ltt_session *session,
+               const struct lttng_snapshot_output *output, int wait);
+
+int cmd_set_session_shm_path(struct ltt_session *session,
+               const char *shm_path);
+int cmd_regenerate_metadata(struct ltt_session *session);
+int cmd_regenerate_statedump(struct ltt_session *session);
+
+enum lttng_error_code cmd_register_trigger(
+               const struct lttng_credentials *cmd_creds,
+               struct lttng_trigger *trigger,
+               bool is_anonymous_trigger,
+               struct notification_thread_handle *notification_thread_handle,
+               struct lttng_trigger **return_trigger);
+enum lttng_error_code cmd_unregister_trigger(
+               const struct lttng_credentials *cmd_creds,
+               const struct lttng_trigger *trigger,
+               struct notification_thread_handle *notification_thread_handle);
+
+enum lttng_error_code cmd_list_triggers(struct command_ctx *cmd_ctx,
+               struct notification_thread_handle *notification_thread_handle,
+               struct lttng_triggers **return_triggers);
+enum lttng_error_code cmd_execute_error_query(const struct lttng_credentials *cmd_creds,
+               const struct lttng_error_query *query,
+               struct lttng_error_query_results **_results,
+               struct notification_thread_handle *notification_thread);
+
+int cmd_rotate_session(struct ltt_session *session,
+               struct lttng_rotate_session_return *rotate_return,
+               bool quiet_rotation,
+               enum lttng_trace_chunk_command_type command);
+int cmd_rotate_get_info(struct ltt_session *session,
+               struct lttng_rotation_get_info_return *info_return,
+               uint64_t rotate_id);
+int cmd_rotation_set_schedule(struct ltt_session *session,
+               bool activate, enum lttng_rotation_schedule_type schedule_type,
+               uint64_t value,
+               struct notification_thread_handle *notification_thread_handle);
+
+const struct cmd_completion_handler *cmd_pop_completion_handler(void);
+int start_kernel_session(struct ltt_kernel_session *ksess);
+int stop_kernel_session(struct ltt_kernel_session *ksess);
+
+#endif /* CMD_H */
index dd9c244b3253ac68694799348066bc048daa1274..7daa53625190769284ecb0586387cba9d7bc5044 100644 (file)
@@ -5,19 +5,19 @@
  *
  */
 
-#include <common/hashtable/utils.h>
-#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.hpp>
+#include <common/hashtable/hashtable.hpp>
 
 #include <lttng/condition/condition.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/buffer-usage-internal.h>
-#include <lttng/condition/session-consumed-size-internal.h>
-#include <lttng/condition/session-rotation-internal.h>
-#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/buffer-usage-internal.hpp>
+#include <lttng/condition/session-consumed-size-internal.hpp>
+#include <lttng/condition/session-rotation-internal.hpp>
+#include <lttng/condition/event-rule-matches-internal.hpp>
 #include <lttng/condition/event-rule-matches.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/condition/event-rule-matches-internal.h>
-#include "condition-internal.h"
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/condition/event-rule-matches-internal.hpp>
+#include "condition-internal.hpp"
 
 static
 unsigned long lttng_condition_buffer_usage_hash(
diff --git a/src/bin/lttng-sessiond/condition-internal.h b/src/bin/lttng-sessiond/condition-internal.h
deleted file mode 100644 (file)
index 49a0749..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_SESSIOND_CONDITION_INTERNAL_H
-#define LTTNG_SESSIOND_CONDITION_INTERNAL_H
-
-#include <lttng/condition/condition.h>
-
-/*
- * The lttng_condition hashing code is kept in this file (rather than
- * condition.c) since it makes use of GPLv2 code (hashtable utils), which we
- * don't want to link in liblttng-ctl.
- */
-unsigned long lttng_condition_hash(const struct lttng_condition *condition);
-
-struct lttng_condition *lttng_condition_copy(
-               const struct lttng_condition *condition);
-
-#endif /* LTTNG_SESSIOND_CONDITION_INTERNAL_H */
diff --git a/src/bin/lttng-sessiond/condition-internal.hpp b/src/bin/lttng-sessiond/condition-internal.hpp
new file mode 100644 (file)
index 0000000..49a0749
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_SESSIOND_CONDITION_INTERNAL_H
+#define LTTNG_SESSIOND_CONDITION_INTERNAL_H
+
+#include <lttng/condition/condition.h>
+
+/*
+ * The lttng_condition hashing code is kept in this file (rather than
+ * condition.c) since it makes use of GPLv2 code (hashtable utils), which we
+ * don't want to link in liblttng-ctl.
+ */
+unsigned long lttng_condition_hash(const struct lttng_condition *condition);
+
+struct lttng_condition *lttng_condition_copy(
+               const struct lttng_condition *condition);
+
+#endif /* LTTNG_SESSIOND_CONDITION_INTERNAL_H */
index f7a92cb3d9b282683da3d9ec3060af976b3cada0..32d3ef48aab16754d74a2fc408d78d749494c906 100644 (file)
 #include <unistd.h>
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/uri.h>
-#include <common/relayd/relayd.h>
-#include <common/string-utils/format.h>
-
-#include "consumer.h"
-#include "health-sessiond.h"
-#include "ust-app.h"
-#include "utils.h"
-#include "lttng-sessiond.h"
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/uri.hpp>
+#include <common/relayd/relayd.hpp>
+#include <common/string-utils/format.hpp>
+
+#include "consumer.hpp"
+#include "health-sessiond.hpp"
+#include "ust-app.hpp"
+#include "utils.hpp"
+#include "lttng-sessiond.hpp"
 
 /*
  * Return allocated full pathname of the session using the consumer trace path
diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h
deleted file mode 100644 (file)
index ffba198..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _CONSUMER_H
-#define _CONSUMER_H
-
-#include <common/consumer/consumer.h>
-#include <common/hashtable/hashtable.h>
-#include <lttng/lttng.h>
-#include <urcu/ref.h>
-#include <algorithm>
-
-#include "snapshot.h"
-
-struct snapshot;
-struct snapshot_output;
-struct ltt_session;
-
-/*
- * Needed until we use C++14, where std::max is constexpr.
- *
- * Use a static_assert so we remember to remove it when we upgrade to a newer
- * C++.
- */
-static_assert(__cplusplus == 201103L, "");
-template <typename T>
-constexpr T max_constexpr(T l, T r)
-{
-       return l > r ? l : r;
-}
-
-enum consumer_dst_type {
-       CONSUMER_DST_LOCAL,
-       CONSUMER_DST_NET,
-};
-
-enum consumer_trace_chunk_exists_status {
-       CONSUMER_TRACE_CHUNK_EXISTS_STATUS_EXISTS_LOCAL,
-       CONSUMER_TRACE_CHUNK_EXISTS_STATUS_EXISTS_REMOTE,
-       CONSUMER_TRACE_CHUNK_EXISTS_STATUS_UNKNOWN_CHUNK,
-};
-
-struct consumer_socket {
-       /*
-        * File descriptor. This is just a reference to the consumer data meaning
-        * that every access must be locked and checked for a possible invalid
-        * value.
-        */
-       int *fd_ptr;
-
-       /*
-        * To use this socket (send/recv), this lock MUST be acquired.
-        */
-       pthread_mutex_t *lock;
-
-       /*
-        * Indicates if the socket was registered by a third part
-        * (REGISTER_CONSUMER) or is the spawn consumer of the session daemon.
-        * During the destroy phase of a consumer output, we close the socket if
-        * this flag is set to 1 since we don't need the fd anymore.
-        */
-       unsigned int registered;
-
-       /* Flag if network sockets were sent to the consumer. */
-       unsigned int control_sock_sent;
-       unsigned int data_sock_sent;
-
-       struct lttng_ht_node_ulong node;
-
-       enum lttng_consumer_type type;
-};
-
-struct consumer_data {
-       consumer_data (lttng_consumer_type type_)
-               : type(type_)
-       {}
-
-       enum lttng_consumer_type type;
-
-       /* Mutex to control consumerd pid assignation */
-       pthread_mutex_t pid_mutex = PTHREAD_MUTEX_INITIALIZER;
-       pid_t pid = 0;
-
-       int err_sock = -1;
-       /* These two sockets uses the cmd_unix_sock_path. */
-       int cmd_sock = -1;
-       /*
-        * Write-end of the channel monitoring pipe to be passed to the
-        * consumer.
-        */
-       int channel_monitor_pipe = -1;
-       /*
-        * The metadata socket object is handled differently and only created
-        * locally in this object thus it's the only reference available in the
-        * session daemon. For that reason, a variable for the fd is required and
-        * the metadata socket fd points to it.
-        */
-       int metadata_fd = 0;
-       struct consumer_socket metadata_sock {};
-
-       /* consumer error and command Unix socket path */
-       const char *err_unix_sock_path = nullptr;
-       const char *cmd_unix_sock_path = nullptr;
-
-       /*
-        * This lock has two purposes. It protects any change to the consumer
-        * socket and make sure only one thread uses this object for read/write
-        * operations.
-        */
-       pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-};
-
-/*
- * Network URIs
- */
-struct consumer_net {
-       /*
-        * Indicate if URI type is set. Those flags should only be set when the
-        * created URI is done AND valid.
-        */
-       int control_isset;
-       int data_isset;
-
-       /*
-        * The following two URIs MUST have the same destination address for
-        * network streaming to work. Network hop are not yet supported.
-        */
-
-       /* Control path for network streaming. */
-       struct lttng_uri control;
-
-       /* Data path for network streaming. */
-       struct lttng_uri data;
-
-       /* <hostname>/<session-name> */
-       char base_dir[PATH_MAX];
-};
-
-/*
- * Consumer output object describing where and how to send data.
- */
-struct consumer_output {
-       struct urcu_ref ref;    /* Refcount */
-
-       /* If the consumer is enabled meaning that should be used */
-       unsigned int enabled;
-       enum consumer_dst_type type;
-
-       /*
-        * The net_seq_index is the index of the network stream on the consumer
-        * side. It tells the consumer which streams goes to which relayd with this
-        * index. The relayd sockets are index with it on the consumer side.
-        */
-       uint64_t net_seq_index;
-       /* Store the relay protocol in use if the session is remote. */
-       uint32_t relay_major_version;
-       uint32_t relay_minor_version;
-
-       /* True if relayd supports the clear feature. */
-       bool relay_allows_clear;
-
-       /*
-        * Subdirectory path name used for both local and network
-        * consumer ("kernel", "ust", or empty).
-        */
-       char domain_subdir[
-               max_constexpr(sizeof(DEFAULT_KERNEL_TRACE_DIR),
-                       sizeof(DEFAULT_UST_TRACE_DIR))];
-
-       /*
-        * Hashtable of consumer_socket index by the file descriptor value. For
-        * multiarch consumer support, we can have more than one consumer (ex:
-        * 32 and 64 bit).
-        */
-       struct lttng_ht *socks;
-
-       /* Tell if this output is used for snapshot. */
-       unsigned int snapshot:1;
-
-       union {
-               char session_root_path[LTTNG_PATH_MAX];
-               struct consumer_net net;
-       } dst;
-
-       /*
-        * Sub-directory below the session_root_path where the next chunk of
-        * trace will be stored (\0 before the first session rotation).
-        */
-       char chunk_path[LTTNG_PATH_MAX];
-};
-
-struct consumer_socket *consumer_find_socket(int key,
-               const struct consumer_output *consumer);
-struct consumer_socket *consumer_find_socket_by_bitness(int bits,
-               const struct consumer_output *consumer);
-struct consumer_socket *consumer_allocate_socket(int *fd);
-void consumer_add_socket(struct consumer_socket *sock,
-               struct consumer_output *consumer);
-void consumer_del_socket(struct consumer_socket *sock,
-               struct consumer_output *consumer);
-void consumer_destroy_socket(struct consumer_socket *sock);
-int consumer_copy_sockets(struct consumer_output *dst,
-               struct consumer_output *src);
-void consumer_destroy_output_sockets(struct consumer_output *obj);
-int consumer_socket_send(struct consumer_socket *socket, const void *msg,
-               size_t len);
-int consumer_socket_recv(struct consumer_socket *socket, void *msg,
-               size_t len);
-
-struct consumer_output *consumer_create_output(enum consumer_dst_type type);
-struct consumer_output *consumer_copy_output(struct consumer_output *obj);
-void consumer_output_get(struct consumer_output *obj);
-void consumer_output_put(struct consumer_output *obj);
-int consumer_set_network_uri(const struct ltt_session *session,
-               struct consumer_output *obj,
-               struct lttng_uri *uri);
-int consumer_send_fds(struct consumer_socket *sock, const int *fds,
-               size_t nb_fd);
-int consumer_send_msg(struct consumer_socket *sock,
-               const struct lttcomm_consumer_msg *msg);
-int consumer_send_stream(struct consumer_socket *sock,
-               struct consumer_output *dst, struct lttcomm_consumer_msg *msg,
-               const int *fds, size_t nb_fd);
-int consumer_send_channel(struct consumer_socket *sock,
-               struct lttcomm_consumer_msg *msg);
-int consumer_send_relayd_socket(struct consumer_socket *consumer_sock,
-               struct lttcomm_relayd_sock *rsock, struct consumer_output *consumer,
-               enum lttng_stream_type type, uint64_t session_id,
-               const char *session_name, const char *hostname,
-               const char *base_path, int session_live_timer,
-               const uint64_t *current_chunk_id, time_t session_creation_time,
-               bool session_name_contains_creation_time);
-int consumer_send_channel_monitor_pipe(struct consumer_socket *consumer_sock,
-               int pipe);
-int consumer_send_destroy_relayd(struct consumer_socket *sock,
-               struct consumer_output *consumer);
-int consumer_recv_status_reply(struct consumer_socket *sock);
-int consumer_recv_status_channel(struct consumer_socket *sock,
-               uint64_t *key, unsigned int *stream_count);
-void consumer_output_send_destroy_relayd(struct consumer_output *consumer);
-int consumer_create_socket(struct consumer_data *data,
-               struct consumer_output *output);
-
-void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg,
-               uint64_t subbuf_size,
-               uint64_t num_subbuf,
-               int overwrite,
-               unsigned int switch_timer_interval,
-               unsigned int read_timer_interval,
-               unsigned int live_timer_interval,
-               bool is_in_live_session,
-               unsigned int monitor_timer_interval,
-               int output,
-               int type,
-               uint64_t session_id,
-               const char *pathname,
-               const char *name,
-               uint64_t relayd_id,
-               uint64_t key,
-               unsigned char *uuid,
-               uint32_t chan_id,
-               uint64_t tracefile_size,
-               uint64_t tracefile_count,
-               uint64_t session_id_per_pid,
-               unsigned int monitor,
-               uint32_t ust_app_uid,
-               int64_t blocking_timeout,
-               const char *root_shm_path,
-               const char *shm_path,
-               struct lttng_trace_chunk *trace_chunk,
-               const struct lttng_credentials *buffer_credentials);
-void consumer_init_add_stream_comm_msg(struct lttcomm_consumer_msg *msg,
-               uint64_t channel_key,
-               uint64_t stream_key,
-               int32_t cpu);
-void consumer_init_streams_sent_comm_msg(struct lttcomm_consumer_msg *msg,
-               enum lttng_consumer_command cmd,
-               uint64_t channel_key, uint64_t net_seq_idx);
-void consumer_init_add_channel_comm_msg(struct lttcomm_consumer_msg *msg,
-               uint64_t channel_key,
-               uint64_t session_id,
-               const char *pathname,
-               uid_t uid,
-               gid_t gid,
-               uint64_t relayd_id,
-               const char *name,
-               unsigned int nb_init_streams,
-               enum lttng_event_output output,
-               int type,
-               uint64_t tracefile_size,
-               uint64_t tracefile_count,
-               unsigned int monitor,
-               unsigned int live_timer_interval,
-               bool is_in_live_session,
-               unsigned int monitor_timer_interval,
-               struct lttng_trace_chunk *trace_chunk);
-int consumer_is_data_pending(uint64_t session_id,
-               struct consumer_output *consumer);
-int consumer_close_metadata(struct consumer_socket *socket,
-               uint64_t metadata_key);
-int consumer_setup_metadata(struct consumer_socket *socket,
-               uint64_t metadata_key);
-int consumer_push_metadata(struct consumer_socket *socket,
-               uint64_t metadata_key, char *metadata_str, size_t len,
-               size_t target_offset, uint64_t version);
-int consumer_flush_channel(struct consumer_socket *socket, uint64_t key);
-int consumer_clear_quiescent_channel(struct consumer_socket *socket, uint64_t key);
-int consumer_get_discarded_events(uint64_t session_id, uint64_t channel_key,
-               struct consumer_output *consumer, uint64_t *discarded);
-int consumer_get_lost_packets(uint64_t session_id, uint64_t channel_key,
-               struct consumer_output *consumer, uint64_t *lost);
-
-/* Snapshot command. */
-enum lttng_error_code consumer_snapshot_channel(struct consumer_socket *socket,
-               uint64_t key, const struct consumer_output *output, int metadata,
-               uid_t uid, gid_t gid, const char *channel_path, int wait,
-               uint64_t nb_packets_per_stream);
-
-/* Rotation commands. */
-int consumer_rotate_channel(struct consumer_socket *socket, uint64_t key,
-               uid_t uid, gid_t gid, struct consumer_output *output,
-               bool is_metadata_channel);
-int consumer_init(struct consumer_socket *socket,
-               const lttng_uuid sessiond_uuid);
-
-int consumer_create_trace_chunk(struct consumer_socket *socket,
-               uint64_t relayd_id, uint64_t session_id,
-               struct lttng_trace_chunk *chunk,
-               const char *domain_subdir);
-int consumer_close_trace_chunk(struct consumer_socket *socket,
-               uint64_t relayd_id, uint64_t session_id,
-               struct lttng_trace_chunk *chunk,
-               char *closed_trace_chunk_path);
-int consumer_trace_chunk_exists(struct consumer_socket *socket,
-               uint64_t relayd_id, uint64_t session_id,
-               struct lttng_trace_chunk *chunk,
-               enum consumer_trace_chunk_exists_status *result);
-int consumer_open_channel_packets(struct consumer_socket *socket, uint64_t key);
-
-char *setup_channel_trace_path(struct consumer_output *consumer,
-               const char *session_path, size_t *consumer_path_offset);
-
-/* Clear command */
-int consumer_clear_channel(struct consumer_socket *socket, uint64_t key);
-
-#endif /* _CONSUMER_H */
diff --git a/src/bin/lttng-sessiond/consumer.hpp b/src/bin/lttng-sessiond/consumer.hpp
new file mode 100644 (file)
index 0000000..4f48bd1
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _CONSUMER_H
+#define _CONSUMER_H
+
+#include <common/consumer/consumer.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <lttng/lttng.h>
+#include <urcu/ref.h>
+#include <algorithm>
+
+#include "snapshot.hpp"
+
+struct snapshot;
+struct snapshot_output;
+struct ltt_session;
+
+/*
+ * Needed until we use C++14, where std::max is constexpr.
+ *
+ * Use a static_assert so we remember to remove it when we upgrade to a newer
+ * C++.
+ */
+static_assert(__cplusplus == 201103L, "");
+template <typename T>
+constexpr T max_constexpr(T l, T r)
+{
+       return l > r ? l : r;
+}
+
+enum consumer_dst_type {
+       CONSUMER_DST_LOCAL,
+       CONSUMER_DST_NET,
+};
+
+enum consumer_trace_chunk_exists_status {
+       CONSUMER_TRACE_CHUNK_EXISTS_STATUS_EXISTS_LOCAL,
+       CONSUMER_TRACE_CHUNK_EXISTS_STATUS_EXISTS_REMOTE,
+       CONSUMER_TRACE_CHUNK_EXISTS_STATUS_UNKNOWN_CHUNK,
+};
+
+struct consumer_socket {
+       /*
+        * File descriptor. This is just a reference to the consumer data meaning
+        * that every access must be locked and checked for a possible invalid
+        * value.
+        */
+       int *fd_ptr;
+
+       /*
+        * To use this socket (send/recv), this lock MUST be acquired.
+        */
+       pthread_mutex_t *lock;
+
+       /*
+        * Indicates if the socket was registered by a third part
+        * (REGISTER_CONSUMER) or is the spawn consumer of the session daemon.
+        * During the destroy phase of a consumer output, we close the socket if
+        * this flag is set to 1 since we don't need the fd anymore.
+        */
+       unsigned int registered;
+
+       /* Flag if network sockets were sent to the consumer. */
+       unsigned int control_sock_sent;
+       unsigned int data_sock_sent;
+
+       struct lttng_ht_node_ulong node;
+
+       enum lttng_consumer_type type;
+};
+
+struct consumer_data {
+       consumer_data (lttng_consumer_type type_)
+               : type(type_)
+       {}
+
+       enum lttng_consumer_type type;
+
+       /* Mutex to control consumerd pid assignation */
+       pthread_mutex_t pid_mutex = PTHREAD_MUTEX_INITIALIZER;
+       pid_t pid = 0;
+
+       int err_sock = -1;
+       /* These two sockets uses the cmd_unix_sock_path. */
+       int cmd_sock = -1;
+       /*
+        * Write-end of the channel monitoring pipe to be passed to the
+        * consumer.
+        */
+       int channel_monitor_pipe = -1;
+       /*
+        * The metadata socket object is handled differently and only created
+        * locally in this object thus it's the only reference available in the
+        * session daemon. For that reason, a variable for the fd is required and
+        * the metadata socket fd points to it.
+        */
+       int metadata_fd = 0;
+       struct consumer_socket metadata_sock {};
+
+       /* consumer error and command Unix socket path */
+       const char *err_unix_sock_path = nullptr;
+       const char *cmd_unix_sock_path = nullptr;
+
+       /*
+        * This lock has two purposes. It protects any change to the consumer
+        * socket and make sure only one thread uses this object for read/write
+        * operations.
+        */
+       pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+};
+
+/*
+ * Network URIs
+ */
+struct consumer_net {
+       /*
+        * Indicate if URI type is set. Those flags should only be set when the
+        * created URI is done AND valid.
+        */
+       int control_isset;
+       int data_isset;
+
+       /*
+        * The following two URIs MUST have the same destination address for
+        * network streaming to work. Network hop are not yet supported.
+        */
+
+       /* Control path for network streaming. */
+       struct lttng_uri control;
+
+       /* Data path for network streaming. */
+       struct lttng_uri data;
+
+       /* <hostname>/<session-name> */
+       char base_dir[PATH_MAX];
+};
+
+/*
+ * Consumer output object describing where and how to send data.
+ */
+struct consumer_output {
+       struct urcu_ref ref;    /* Refcount */
+
+       /* If the consumer is enabled meaning that should be used */
+       unsigned int enabled;
+       enum consumer_dst_type type;
+
+       /*
+        * The net_seq_index is the index of the network stream on the consumer
+        * side. It tells the consumer which streams goes to which relayd with this
+        * index. The relayd sockets are index with it on the consumer side.
+        */
+       uint64_t net_seq_index;
+       /* Store the relay protocol in use if the session is remote. */
+       uint32_t relay_major_version;
+       uint32_t relay_minor_version;
+
+       /* True if relayd supports the clear feature. */
+       bool relay_allows_clear;
+
+       /*
+        * Subdirectory path name used for both local and network
+        * consumer ("kernel", "ust", or empty).
+        */
+       char domain_subdir[
+               max_constexpr(sizeof(DEFAULT_KERNEL_TRACE_DIR),
+                       sizeof(DEFAULT_UST_TRACE_DIR))];
+
+       /*
+        * Hashtable of consumer_socket index by the file descriptor value. For
+        * multiarch consumer support, we can have more than one consumer (ex:
+        * 32 and 64 bit).
+        */
+       struct lttng_ht *socks;
+
+       /* Tell if this output is used for snapshot. */
+       unsigned int snapshot:1;
+
+       union {
+               char session_root_path[LTTNG_PATH_MAX];
+               struct consumer_net net;
+       } dst;
+
+       /*
+        * Sub-directory below the session_root_path where the next chunk of
+        * trace will be stored (\0 before the first session rotation).
+        */
+       char chunk_path[LTTNG_PATH_MAX];
+};
+
+struct consumer_socket *consumer_find_socket(int key,
+               const struct consumer_output *consumer);
+struct consumer_socket *consumer_find_socket_by_bitness(int bits,
+               const struct consumer_output *consumer);
+struct consumer_socket *consumer_allocate_socket(int *fd);
+void consumer_add_socket(struct consumer_socket *sock,
+               struct consumer_output *consumer);
+void consumer_del_socket(struct consumer_socket *sock,
+               struct consumer_output *consumer);
+void consumer_destroy_socket(struct consumer_socket *sock);
+int consumer_copy_sockets(struct consumer_output *dst,
+               struct consumer_output *src);
+void consumer_destroy_output_sockets(struct consumer_output *obj);
+int consumer_socket_send(struct consumer_socket *socket, const void *msg,
+               size_t len);
+int consumer_socket_recv(struct consumer_socket *socket, void *msg,
+               size_t len);
+
+struct consumer_output *consumer_create_output(enum consumer_dst_type type);
+struct consumer_output *consumer_copy_output(struct consumer_output *obj);
+void consumer_output_get(struct consumer_output *obj);
+void consumer_output_put(struct consumer_output *obj);
+int consumer_set_network_uri(const struct ltt_session *session,
+               struct consumer_output *obj,
+               struct lttng_uri *uri);
+int consumer_send_fds(struct consumer_socket *sock, const int *fds,
+               size_t nb_fd);
+int consumer_send_msg(struct consumer_socket *sock,
+               const struct lttcomm_consumer_msg *msg);
+int consumer_send_stream(struct consumer_socket *sock,
+               struct consumer_output *dst, struct lttcomm_consumer_msg *msg,
+               const int *fds, size_t nb_fd);
+int consumer_send_channel(struct consumer_socket *sock,
+               struct lttcomm_consumer_msg *msg);
+int consumer_send_relayd_socket(struct consumer_socket *consumer_sock,
+               struct lttcomm_relayd_sock *rsock, struct consumer_output *consumer,
+               enum lttng_stream_type type, uint64_t session_id,
+               const char *session_name, const char *hostname,
+               const char *base_path, int session_live_timer,
+               const uint64_t *current_chunk_id, time_t session_creation_time,
+               bool session_name_contains_creation_time);
+int consumer_send_channel_monitor_pipe(struct consumer_socket *consumer_sock,
+               int pipe);
+int consumer_send_destroy_relayd(struct consumer_socket *sock,
+               struct consumer_output *consumer);
+int consumer_recv_status_reply(struct consumer_socket *sock);
+int consumer_recv_status_channel(struct consumer_socket *sock,
+               uint64_t *key, unsigned int *stream_count);
+void consumer_output_send_destroy_relayd(struct consumer_output *consumer);
+int consumer_create_socket(struct consumer_data *data,
+               struct consumer_output *output);
+
+void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg,
+               uint64_t subbuf_size,
+               uint64_t num_subbuf,
+               int overwrite,
+               unsigned int switch_timer_interval,
+               unsigned int read_timer_interval,
+               unsigned int live_timer_interval,
+               bool is_in_live_session,
+               unsigned int monitor_timer_interval,
+               int output,
+               int type,
+               uint64_t session_id,
+               const char *pathname,
+               const char *name,
+               uint64_t relayd_id,
+               uint64_t key,
+               unsigned char *uuid,
+               uint32_t chan_id,
+               uint64_t tracefile_size,
+               uint64_t tracefile_count,
+               uint64_t session_id_per_pid,
+               unsigned int monitor,
+               uint32_t ust_app_uid,
+               int64_t blocking_timeout,
+               const char *root_shm_path,
+               const char *shm_path,
+               struct lttng_trace_chunk *trace_chunk,
+               const struct lttng_credentials *buffer_credentials);
+void consumer_init_add_stream_comm_msg(struct lttcomm_consumer_msg *msg,
+               uint64_t channel_key,
+               uint64_t stream_key,
+               int32_t cpu);
+void consumer_init_streams_sent_comm_msg(struct lttcomm_consumer_msg *msg,
+               enum lttng_consumer_command cmd,
+               uint64_t channel_key, uint64_t net_seq_idx);
+void consumer_init_add_channel_comm_msg(struct lttcomm_consumer_msg *msg,
+               uint64_t channel_key,
+               uint64_t session_id,
+               const char *pathname,
+               uid_t uid,
+               gid_t gid,
+               uint64_t relayd_id,
+               const char *name,
+               unsigned int nb_init_streams,
+               enum lttng_event_output output,
+               int type,
+               uint64_t tracefile_size,
+               uint64_t tracefile_count,
+               unsigned int monitor,
+               unsigned int live_timer_interval,
+               bool is_in_live_session,
+               unsigned int monitor_timer_interval,
+               struct lttng_trace_chunk *trace_chunk);
+int consumer_is_data_pending(uint64_t session_id,
+               struct consumer_output *consumer);
+int consumer_close_metadata(struct consumer_socket *socket,
+               uint64_t metadata_key);
+int consumer_setup_metadata(struct consumer_socket *socket,
+               uint64_t metadata_key);
+int consumer_push_metadata(struct consumer_socket *socket,
+               uint64_t metadata_key, char *metadata_str, size_t len,
+               size_t target_offset, uint64_t version);
+int consumer_flush_channel(struct consumer_socket *socket, uint64_t key);
+int consumer_clear_quiescent_channel(struct consumer_socket *socket, uint64_t key);
+int consumer_get_discarded_events(uint64_t session_id, uint64_t channel_key,
+               struct consumer_output *consumer, uint64_t *discarded);
+int consumer_get_lost_packets(uint64_t session_id, uint64_t channel_key,
+               struct consumer_output *consumer, uint64_t *lost);
+
+/* Snapshot command. */
+enum lttng_error_code consumer_snapshot_channel(struct consumer_socket *socket,
+               uint64_t key, const struct consumer_output *output, int metadata,
+               uid_t uid, gid_t gid, const char *channel_path, int wait,
+               uint64_t nb_packets_per_stream);
+
+/* Rotation commands. */
+int consumer_rotate_channel(struct consumer_socket *socket, uint64_t key,
+               uid_t uid, gid_t gid, struct consumer_output *output,
+               bool is_metadata_channel);
+int consumer_init(struct consumer_socket *socket,
+               const lttng_uuid sessiond_uuid);
+
+int consumer_create_trace_chunk(struct consumer_socket *socket,
+               uint64_t relayd_id, uint64_t session_id,
+               struct lttng_trace_chunk *chunk,
+               const char *domain_subdir);
+int consumer_close_trace_chunk(struct consumer_socket *socket,
+               uint64_t relayd_id, uint64_t session_id,
+               struct lttng_trace_chunk *chunk,
+               char *closed_trace_chunk_path);
+int consumer_trace_chunk_exists(struct consumer_socket *socket,
+               uint64_t relayd_id, uint64_t session_id,
+               struct lttng_trace_chunk *chunk,
+               enum consumer_trace_chunk_exists_status *result);
+int consumer_open_channel_packets(struct consumer_socket *socket, uint64_t key);
+
+char *setup_channel_trace_path(struct consumer_output *consumer,
+               const char *session_path, size_t *consumer_path_offset);
+
+/* Clear command */
+int consumer_clear_channel(struct consumer_socket *socket, uint64_t key);
+
+#endif /* _CONSUMER_H */
index c8c89243823fe47a883e675532252065a75a551f..0c0509b93fb3858e099336e8d198d1b2ef672b71 100644 (file)
 #include <unistd.h>
 #include <urcu/list.h>
 
-#include <common/error.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-
-#include "context.h"
-#include "kernel.h"
-#include "ust-app.h"
-#include "trace-ust.h"
-#include "agent.h"
+#include <common/error.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+
+#include "context.hpp"
+#include "kernel.hpp"
+#include "ust-app.hpp"
+#include "trace-ust.hpp"
+#include "agent.hpp"
 
 /*
  * Add kernel context to all channel.
diff --git a/src/bin/lttng-sessiond/context.h b/src/bin/lttng-sessiond/context.h
deleted file mode 100644 (file)
index 5caa19c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_CONTEXT_H
-#define _LTT_CONTEXT_H
-
-#include <lttng/lttng.h>
-
-#include "trace-kernel.h"
-#include "trace-ust.h"
-#include "lttng-ust-ctl.h"
-
-int context_kernel_add(struct ltt_kernel_session *ksession,
-               const struct lttng_event_context *ctx, char *channel_name);
-int context_ust_add(struct ltt_ust_session *usess,
-               enum lttng_domain_type domain,
-               const struct lttng_event_context *ctx,
-               char *channel_name);
-
-#endif /* _LTT_CONTEXT_H */
diff --git a/src/bin/lttng-sessiond/context.hpp b/src/bin/lttng-sessiond/context.hpp
new file mode 100644 (file)
index 0000000..b802c28
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_CONTEXT_H
+#define _LTT_CONTEXT_H
+
+#include <lttng/lttng.h>
+
+#include "trace-kernel.hpp"
+#include "trace-ust.hpp"
+#include "lttng-ust-ctl.hpp"
+
+int context_kernel_add(struct ltt_kernel_session *ksession,
+               const struct lttng_event_context *ctx, char *channel_name);
+int context_ust_add(struct ltt_ust_session *usess,
+               enum lttng_domain_type domain,
+               const struct lttng_event_context *ctx,
+               char *channel_name);
+
+#endif /* _LTT_CONTEXT_H */
index b4092eb44793bc454641b1cf12ba5e60567bc419..5f5b1b2f46343320f8beda7209d9326c384ae28d 100644 (file)
 #include <stddef.h>
 #include <stdlib.h>
 #include <urcu.h>
-#include <common/futex.h>
-#include <common/macros.h>
-
-#include "dispatch.h"
-#include "ust-app.h"
-#include "testpoint.h"
-#include "fd-limit.h"
-#include "health-sessiond.h"
-#include "lttng-sessiond.h"
-#include "thread.h"
+#include <common/futex.hpp>
+#include <common/macros.hpp>
+
+#include "dispatch.hpp"
+#include "ust-app.hpp"
+#include "testpoint.hpp"
+#include "fd-limit.hpp"
+#include "health-sessiond.hpp"
+#include "lttng-sessiond.hpp"
+#include "thread.hpp"
 
 struct thread_notifiers {
        struct ust_cmd_queue *ust_cmd_queue;
diff --git a/src/bin/lttng-sessiond/dispatch.h b/src/bin/lttng-sessiond/dispatch.h
deleted file mode 100644 (file)
index fe253de..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SESSIOND_UST_DISPATCH_THREAD_H
-#define SESSIOND_UST_DISPATCH_THREAD_H
-
-#include <stdbool.h>
-#include "lttng-sessiond.h"
-
-bool launch_ust_dispatch_thread(struct ust_cmd_queue *cmd_queue,
-               int apps_cmd_pipe_write_fd,
-               int apps_cmd_notify_write_fd);
-
-#endif /* SESSIOND_UST_DISPATCH_THREAD_H */
diff --git a/src/bin/lttng-sessiond/dispatch.hpp b/src/bin/lttng-sessiond/dispatch.hpp
new file mode 100644 (file)
index 0000000..7d52ed3
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SESSIOND_UST_DISPATCH_THREAD_H
+#define SESSIOND_UST_DISPATCH_THREAD_H
+
+#include <stdbool.h>
+#include "lttng-sessiond.hpp"
+
+bool launch_ust_dispatch_thread(struct ust_cmd_queue *cmd_queue,
+               int apps_cmd_pipe_write_fd,
+               int apps_cmd_notify_write_fd);
+
+#endif /* SESSIOND_UST_DISPATCH_THREAD_H */
index c99c39338fbe1fbcf6c5237d75fd28fb1fde4b16..4cbae12ffa3957794da6719ceb026ec94e9fea3f 100644 (file)
 #include <urcu/compiler.h>
 #include <pthread.h>
 
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/index-allocator.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/shm.h>
-#include <lttng/trigger/trigger-internal.h>
-
-#include "event-notifier-error-accounting.h"
-#include "lttng-ust-error.h"
-#include "ust-app.h"
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/index-allocator.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/shm.hpp>
+#include <lttng/trigger/trigger-internal.hpp>
+
+#include "event-notifier-error-accounting.hpp"
+#include "lttng-ust-error.hpp"
+#include "ust-app.hpp"
 
 #define ERROR_COUNTER_INDEX_HT_INITIAL_SIZE 16
 
diff --git a/src/bin/lttng-sessiond/event-notifier-error-accounting.h b/src/bin/lttng-sessiond/event-notifier-error-accounting.h
deleted file mode 100644 (file)
index 319a488..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _EVENT_NOTIFIER_ERROR_ACCOUNTING_H
-#define _EVENT_NOTIFIER_ERROR_ACCOUNTING_H
-
-#include <stdint.h>
-
-#include <lttng/trigger/trigger.h>
-
-#include "ust-app.h"
-
-enum event_notifier_error_accounting_status {
-       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK,
-       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR,
-       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND,
-       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM,
-       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE,
-       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD,
-       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_UNSUPPORTED,
-};
-
-/*
- * Initialize the event notifier error accounting system.
- * `buffer_size_kernel` and `buffer_size_ust` represent the number of buckets
- * to be allocated for each domain.
- */
-enum event_notifier_error_accounting_status
-event_notifier_error_accounting_init(uint64_t buffer_size_kernel,
-               uint64_t buffer_size_ust);
-
-/*
- * Register the kernel event notifier group.
- * This allocates the counter object on the kernel side.
- */
-enum event_notifier_error_accounting_status
-event_notifier_error_accounting_register_kernel(
-               int kernel_event_notifier_group_fd);
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-/*
- * Register a UST application.
- *
- * This reuses (or creates) the counter object of the app UID.
- */
-enum event_notifier_error_accounting_status
-event_notifier_error_accounting_register_app(struct ust_app *app);
-
-/*
- * Unregister a UST application.
- */
-enum event_notifier_error_accounting_status
-event_notifier_error_accounting_unregister_app(struct ust_app *app);
-#else /* HAVE_LIBLTTNG_UST_CTL */
-static inline
-enum event_notifier_error_accounting_status
-event_notifier_error_accounting_register_app(struct ust_app *app)
-{
-       return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
-}
-
-static inline
-enum event_notifier_error_accounting_status
-event_notifier_error_accounting_unregister_app(struct ust_app *app)
-{
-       return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
-}
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-/*
- * Allocates, reserves and returns the error counter index for that trigger.
- */
-enum event_notifier_error_accounting_status
-event_notifier_error_accounting_register_event_notifier(
-               const struct lttng_trigger *trigger,
-               uint64_t *error_counter_index);
-
-enum event_notifier_error_accounting_status
-event_notifier_error_accounting_get_count(
-               const struct lttng_trigger *trigger,
-               uint64_t *count);
-
-void event_notifier_error_accounting_unregister_event_notifier(
-               const struct lttng_trigger *trigger);
-
-void event_notifier_error_accounting_fini(void);
-
-#endif /* _EVENT_NOTIFIER_ERROR_ACCOUNTING_H */
diff --git a/src/bin/lttng-sessiond/event-notifier-error-accounting.hpp b/src/bin/lttng-sessiond/event-notifier-error-accounting.hpp
new file mode 100644 (file)
index 0000000..e5adcae
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _EVENT_NOTIFIER_ERROR_ACCOUNTING_H
+#define _EVENT_NOTIFIER_ERROR_ACCOUNTING_H
+
+#include <stdint.h>
+
+#include <lttng/trigger/trigger.h>
+
+#include "ust-app.hpp"
+
+enum event_notifier_error_accounting_status {
+       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK,
+       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR,
+       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND,
+       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM,
+       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE,
+       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD,
+       EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_UNSUPPORTED,
+};
+
+/*
+ * Initialize the event notifier error accounting system.
+ * `buffer_size_kernel` and `buffer_size_ust` represent the number of buckets
+ * to be allocated for each domain.
+ */
+enum event_notifier_error_accounting_status
+event_notifier_error_accounting_init(uint64_t buffer_size_kernel,
+               uint64_t buffer_size_ust);
+
+/*
+ * Register the kernel event notifier group.
+ * This allocates the counter object on the kernel side.
+ */
+enum event_notifier_error_accounting_status
+event_notifier_error_accounting_register_kernel(
+               int kernel_event_notifier_group_fd);
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+/*
+ * Register a UST application.
+ *
+ * This reuses (or creates) the counter object of the app UID.
+ */
+enum event_notifier_error_accounting_status
+event_notifier_error_accounting_register_app(struct ust_app *app);
+
+/*
+ * Unregister a UST application.
+ */
+enum event_notifier_error_accounting_status
+event_notifier_error_accounting_unregister_app(struct ust_app *app);
+#else /* HAVE_LIBLTTNG_UST_CTL */
+static inline
+enum event_notifier_error_accounting_status
+event_notifier_error_accounting_register_app(struct ust_app *app)
+{
+       return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
+}
+
+static inline
+enum event_notifier_error_accounting_status
+event_notifier_error_accounting_unregister_app(struct ust_app *app)
+{
+       return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
+}
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+/*
+ * Allocates, reserves and returns the error counter index for that trigger.
+ */
+enum event_notifier_error_accounting_status
+event_notifier_error_accounting_register_event_notifier(
+               const struct lttng_trigger *trigger,
+               uint64_t *error_counter_index);
+
+enum event_notifier_error_accounting_status
+event_notifier_error_accounting_get_count(
+               const struct lttng_trigger *trigger,
+               uint64_t *count);
+
+void event_notifier_error_accounting_unregister_event_notifier(
+               const struct lttng_trigger *trigger);
+
+void event_notifier_error_accounting_fini(void);
+
+#endif /* _EVENT_NOTIFIER_ERROR_ACCOUNTING_H */
index 284a8c472b44012ab7fb4b5948c1aac5b665f710..28f2815696457aafe403f32433fff0742cf86108 100644 (file)
 #include <urcu/list.h>
 #include <string.h>
 
-#include <common/compat/errno.h>
+#include <common/compat/errno.hpp>
 #include <lttng/lttng.h>
 #include <lttng/condition/condition.h>
 #include <lttng/condition/event-rule-matches.h>
 #include <lttng/event-rule/event-rule.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <common/bytecode/bytecode.h>
-#include <common/error.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/filter.h>
-#include <common/context.h>
-
-#include "channel.h"
-#include "event.h"
-#include "kernel.h"
-#include "lttng-sessiond.h"
-#include "lttng-ust-ctl.h"
-#include "lttng-ust-error.h"
-#include "ust-app.h"
-#include "trace-kernel.h"
-#include "trace-ust.h"
-#include "agent.h"
-#include "utils.h"
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <common/bytecode/bytecode.hpp>
+#include <common/error.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/filter.hpp>
+#include <common/context.hpp>
+
+#include "channel.hpp"
+#include "event.hpp"
+#include "kernel.hpp"
+#include "lttng-sessiond.hpp"
+#include "lttng-ust-ctl.hpp"
+#include "lttng-ust-error.hpp"
+#include "ust-app.hpp"
+#include "trace-kernel.hpp"
+#include "trace-ust.hpp"
+#include "agent.hpp"
+#include "utils.hpp"
 
 /*
  * Add unique UST event based on the event name, filter bytecode and loglevel.
diff --git a/src/bin/lttng-sessiond/event.h b/src/bin/lttng-sessiond/event.h
deleted file mode 100644 (file)
index 8849ee7..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_EVENT_H
-#define _LTT_EVENT_H
-
-#include "trace-kernel.h"
-
-struct agent;
-
-int event_kernel_disable_event(struct ltt_kernel_channel *kchan,
-               const char *event_name, enum lttng_event_type event_type);
-
-int event_kernel_enable_event(struct ltt_kernel_channel *kchan,
-               struct lttng_event *event, char *filter_expression,
-               struct lttng_bytecode *filter);
-
-int event_ust_enable_tracepoint(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct lttng_event *event,
-               char *filter_expression,
-               struct lttng_bytecode *filter,
-               struct lttng_event_exclusion *exclusion,
-               bool internal_event);
-int event_ust_disable_tracepoint(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, const char *event_name);
-
-int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan);
-
-int event_agent_enable(struct ltt_ust_session *usess, struct agent *agt,
-               struct lttng_event *event, struct lttng_bytecode *filter,
-               char *filter_expression);
-int event_agent_enable_all(struct ltt_ust_session *usess, struct agent *agt,
-               struct lttng_event *event, struct lttng_bytecode *filter,
-               char *filter_expression);
-
-int event_agent_disable(struct ltt_ust_session *usess, struct agent *agt,
-               const char *event_name);
-int event_agent_disable_all(struct ltt_ust_session *usess, struct agent *agt);
-
-int trigger_agent_enable(
-               const struct lttng_trigger *trigger, struct agent *agt);
-int trigger_agent_disable(
-               const struct lttng_trigger *trigger, struct agent *agt);
-
-const char *event_get_default_agent_ust_name(enum lttng_domain_type domain);
-
-#endif /* _LTT_EVENT_H */
diff --git a/src/bin/lttng-sessiond/event.hpp b/src/bin/lttng-sessiond/event.hpp
new file mode 100644 (file)
index 0000000..5c5291d
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_EVENT_H
+#define _LTT_EVENT_H
+
+#include "trace-kernel.hpp"
+
+struct agent;
+
+int event_kernel_disable_event(struct ltt_kernel_channel *kchan,
+               const char *event_name, enum lttng_event_type event_type);
+
+int event_kernel_enable_event(struct ltt_kernel_channel *kchan,
+               struct lttng_event *event, char *filter_expression,
+               struct lttng_bytecode *filter);
+
+int event_ust_enable_tracepoint(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct lttng_event *event,
+               char *filter_expression,
+               struct lttng_bytecode *filter,
+               struct lttng_event_exclusion *exclusion,
+               bool internal_event);
+int event_ust_disable_tracepoint(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, const char *event_name);
+
+int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan);
+
+int event_agent_enable(struct ltt_ust_session *usess, struct agent *agt,
+               struct lttng_event *event, struct lttng_bytecode *filter,
+               char *filter_expression);
+int event_agent_enable_all(struct ltt_ust_session *usess, struct agent *agt,
+               struct lttng_event *event, struct lttng_bytecode *filter,
+               char *filter_expression);
+
+int event_agent_disable(struct ltt_ust_session *usess, struct agent *agt,
+               const char *event_name);
+int event_agent_disable_all(struct ltt_ust_session *usess, struct agent *agt);
+
+int trigger_agent_enable(
+               const struct lttng_trigger *trigger, struct agent *agt);
+int trigger_agent_disable(
+               const struct lttng_trigger *trigger, struct agent *agt);
+
+const char *event_get_default_agent_ust_name(enum lttng_domain_type domain);
+
+#endif /* _LTT_EVENT_H */
index 833b64714b2aa1e9b1920c953962bf787076ee79..1b68491b8524c4298cda07ebc9810545d56630e6 100644 (file)
@@ -10,9 +10,9 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <stdio.h>
-#include "fd-limit.h"
-#include <common/error.h>
-#include <common/compat/errno.h>
+#include "fd-limit.hpp"
+#include <common/error.hpp>
+#include <common/compat/errno.hpp>
 
 /* total count of fd. */
 static long fd_count;
diff --git a/src/bin/lttng-sessiond/fd-limit.h b/src/bin/lttng-sessiond/fd-limit.h
deleted file mode 100644 (file)
index 8666cdc..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _LTTNG_FD_LIMIT_H
-#define _LTTNG_FD_LIMIT_H
-
-/*
- * Copyright (C) 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-enum lttng_fd_type {
-       LTTNG_FD_APPS,
-       LTTNG_FD_NR_TYPES,
-};
-
-int lttng_fd_get(enum lttng_fd_type type, unsigned int nr);
-void lttng_fd_put(enum lttng_fd_type type, unsigned int nr);
-void lttng_fd_init(void);
-
-#endif /* _LTTNG_FD_LIMIT_H */
diff --git a/src/bin/lttng-sessiond/fd-limit.hpp b/src/bin/lttng-sessiond/fd-limit.hpp
new file mode 100644 (file)
index 0000000..8666cdc
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _LTTNG_FD_LIMIT_H
+#define _LTTNG_FD_LIMIT_H
+
+/*
+ * Copyright (C) 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+enum lttng_fd_type {
+       LTTNG_FD_APPS,
+       LTTNG_FD_NR_TYPES,
+};
+
+int lttng_fd_get(enum lttng_fd_type type, unsigned int nr);
+void lttng_fd_put(enum lttng_fd_type type, unsigned int nr);
+void lttng_fd_init(void);
+
+#endif /* _LTTNG_FD_LIMIT_H */
index b4cedf337678b253de987e0f790405f7fc6d2edf..573737f19bf29fe265f106eafcf4eb6072769f62 100644 (file)
@@ -7,8 +7,8 @@
  *
  */
 
-#include "lttng-sessiond.h"
-#include <common/uuid.h>
+#include "lttng-sessiond.hpp"
+#include <common/uuid.hpp>
 
 lttng_uuid the_sessiond_uuid;
 
diff --git a/src/bin/lttng-sessiond/health-sessiond.h b/src/bin/lttng-sessiond/health-sessiond.h
deleted file mode 100644 (file)
index af950b1..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef HEALTH_SESSIOND_H
-#define HEALTH_SESSIOND_H
-
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <lttng/health-internal.h>
-#include <stdbool.h>
-
-enum health_type_sessiond {
-       HEALTH_SESSIOND_TYPE_CMD                = 0,
-       HEALTH_SESSIOND_TYPE_APP_MANAGE         = 1,
-       HEALTH_SESSIOND_TYPE_APP_REG            = 2,
-       HEALTH_SESSIOND_TYPE_KERNEL             = 3,
-       HEALTH_SESSIOND_TYPE_CONSUMER           = 4,
-       HEALTH_SESSIOND_TYPE_HT_CLEANUP         = 5,
-       HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY  = 6,
-       HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH   = 7,
-       HEALTH_SESSIOND_TYPE_NOTIFICATION       = 8,
-       HEALTH_SESSIOND_TYPE_ROTATION           = 9,
-       HEALTH_SESSIOND_TYPE_TIMER              = 10,
-       HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR    = 11,
-
-       NR_HEALTH_SESSIOND_TYPES,
-};
-
-/* Application health monitoring */
-extern struct health_app *the_health_sessiond;
-
-bool launch_health_management_thread(void);
-
-#endif /* HEALTH_SESSIOND_H */
diff --git a/src/bin/lttng-sessiond/health-sessiond.hpp b/src/bin/lttng-sessiond/health-sessiond.hpp
new file mode 100644 (file)
index 0000000..59aaa73
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef HEALTH_SESSIOND_H
+#define HEALTH_SESSIOND_H
+
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <lttng/health-internal.hpp>
+#include <stdbool.h>
+
+enum health_type_sessiond {
+       HEALTH_SESSIOND_TYPE_CMD                = 0,
+       HEALTH_SESSIOND_TYPE_APP_MANAGE         = 1,
+       HEALTH_SESSIOND_TYPE_APP_REG            = 2,
+       HEALTH_SESSIOND_TYPE_KERNEL             = 3,
+       HEALTH_SESSIOND_TYPE_CONSUMER           = 4,
+       HEALTH_SESSIOND_TYPE_HT_CLEANUP         = 5,
+       HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY  = 6,
+       HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH   = 7,
+       HEALTH_SESSIOND_TYPE_NOTIFICATION       = 8,
+       HEALTH_SESSIOND_TYPE_ROTATION           = 9,
+       HEALTH_SESSIOND_TYPE_TIMER              = 10,
+       HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR    = 11,
+
+       NR_HEALTH_SESSIOND_TYPES,
+};
+
+/* Application health monitoring */
+extern struct health_app *the_health_sessiond;
+
+bool launch_health_management_thread(void);
+
+#endif /* HEALTH_SESSIOND_H */
index 53b9ee01f0e362171dcee85fcb888f26da49c8a5..a7f4bdcbb534dc82ae6b6cebaae876043a8f71f5 100644 (file)
@@ -6,16 +6,16 @@
  *
  */
 
-#include "lttng-sessiond.h"
-#include "health-sessiond.h"
-#include <common/macros.h>
-#include <common/error.h>
-#include <common/utils.h>
-#include <common/pipe.h>
+#include "lttng-sessiond.hpp"
+#include "health-sessiond.hpp"
+#include <common/macros.hpp>
+#include <common/error.hpp>
+#include <common/utils.hpp>
+#include <common/pipe.hpp>
 #include <inttypes.h>
 #include <sys/stat.h>
-#include "utils.h"
-#include "thread.h"
+#include "utils.hpp"
+#include "thread.hpp"
 
 struct thread_notifiers {
        struct lttng_pipe *quit_pipe;
index 050f18e2bc38a5fb0e65f1044c687b516b0f240a..f709af5025bcb47b7b8ab8ef57241236d1fa9e83 100644 (file)
@@ -7,16 +7,16 @@
 
 #define _LGPL_SOURCE
 
-#include <common/hashtable/hashtable.h>
-#include <common/common.h>
-#include <common/utils.h>
+#include <common/hashtable/hashtable.hpp>
+#include <common/common.hpp>
+#include <common/utils.hpp>
 #include <pthread.h>
 
-#include "lttng-sessiond.h"
-#include "health-sessiond.h"
-#include "testpoint.h"
-#include "utils.h"
-#include "ht-cleanup.h"
+#include "lttng-sessiond.hpp"
+#include "health-sessiond.hpp"
+#include "testpoint.hpp"
+#include "utils.hpp"
+#include "ht-cleanup.hpp"
 
 static int ht_cleanup_quit_pipe[2] = { -1, -1 };
 
diff --git a/src/bin/lttng-sessiond/ht-cleanup.h b/src/bin/lttng-sessiond/ht-cleanup.h
deleted file mode 100644 (file)
index 52cca83..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_HT_CLEANUP_H
-#define _LTTNG_HT_CLEANUP_H
-
-#include <pthread.h>
-#include "thread.h"
-
-struct lttng_thread *launch_ht_cleanup_thread(void);
-
-#endif /* _LTTNG_HT_CLEANUP_H */
diff --git a/src/bin/lttng-sessiond/ht-cleanup.hpp b/src/bin/lttng-sessiond/ht-cleanup.hpp
new file mode 100644 (file)
index 0000000..145ad23
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_HT_CLEANUP_H
+#define _LTTNG_HT_CLEANUP_H
+
+#include <pthread.h>
+#include "thread.hpp"
+
+struct lttng_thread *launch_ht_cleanup_thread(void);
+
+#endif /* _LTTNG_HT_CLEANUP_H */
diff --git a/src/bin/lttng-sessiond/kern-modules.h b/src/bin/lttng-sessiond/kern-modules.h
deleted file mode 100644 (file)
index d914362..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _KERN_MODULES_H
-#define _KERN_MODULES_H
-
-/*
- * Compatible lttng-modules version.
- */
-#define KERN_MODULES_PRE_MAJOR     1
-#define KERN_MODULES_PRE_MINOR     9
-
-#define KERN_MODULES_MAJOR         2
-#define KERN_MODULES_MINOR         0
-
-enum kernel_module_property_load_policy {
-       KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED = 0,
-       KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL = 1,
-};
-
-struct kern_modules_param {
-       char *name;
-    enum kernel_module_property_load_policy load_policy;
-       bool loaded;
-};
-
-#endif /* _KERN_MODULES_H */
diff --git a/src/bin/lttng-sessiond/kern-modules.hpp b/src/bin/lttng-sessiond/kern-modules.hpp
new file mode 100644 (file)
index 0000000..d914362
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _KERN_MODULES_H
+#define _KERN_MODULES_H
+
+/*
+ * Compatible lttng-modules version.
+ */
+#define KERN_MODULES_PRE_MAJOR     1
+#define KERN_MODULES_PRE_MINOR     9
+
+#define KERN_MODULES_MAJOR         2
+#define KERN_MODULES_MINOR         0
+
+enum kernel_module_property_load_policy {
+       KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED = 0,
+       KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL = 1,
+};
+
+struct kern_modules_param {
+       char *name;
+    enum kernel_module_property_load_policy load_policy;
+       bool loaded;
+};
+
+#endif /* _KERN_MODULES_H */
index 364705fcb31d7f91e5d095d0740b38488c0bd712..f95498851443512b37a2ea27a670f27533ee117e 100644 (file)
 #include <unistd.h>
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/compat/string.h>
-
-#include "consumer.h"
-#include "health-sessiond.h"
-#include "kernel-consumer.h"
-#include "notification-thread-commands.h"
-#include "session.h"
-#include "lttng-sessiond.h"
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/compat/string.hpp>
+
+#include "consumer.hpp"
+#include "health-sessiond.hpp"
+#include "kernel-consumer.hpp"
+#include "notification-thread-commands.hpp"
+#include "session.hpp"
+#include "lttng-sessiond.hpp"
 
 static char *create_channel_path(struct consumer_output *consumer,
                size_t *consumer_path_offset)
diff --git a/src/bin/lttng-sessiond/kernel-consumer.h b/src/bin/lttng-sessiond/kernel-consumer.h
deleted file mode 100644 (file)
index 3177170..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <sys/types.h>
-
-#include <common/sessiond-comm/sessiond-comm.h>
-
-#include "trace-kernel.h"
-
-int kernel_consumer_send_channel_streams(struct consumer_socket *sock,
-               struct ltt_kernel_channel *channel, struct ltt_kernel_session *session,
-               unsigned int monitor);
-
-int kernel_consumer_send_session(struct consumer_socket *sock,
-               struct ltt_kernel_session *session);
-
-int kernel_consumer_add_metadata(struct consumer_socket *sock,
-               struct ltt_kernel_session *session, unsigned int monitor);
-
-int kernel_consumer_destroy_channel(struct consumer_socket *socket,
-               struct ltt_kernel_channel *channel);
-
-int kernel_consumer_destroy_metadata(struct consumer_socket *socket,
-               struct ltt_kernel_metadata *metadata);
-
-int kernel_consumer_streams_sent(struct consumer_socket *sock,
-               struct ltt_kernel_session *session, uint64_t channel_key);
diff --git a/src/bin/lttng-sessiond/kernel-consumer.hpp b/src/bin/lttng-sessiond/kernel-consumer.hpp
new file mode 100644 (file)
index 0000000..276312e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <sys/types.h>
+
+#include <common/sessiond-comm/sessiond-comm.hpp>
+
+#include "trace-kernel.hpp"
+
+int kernel_consumer_send_channel_streams(struct consumer_socket *sock,
+               struct ltt_kernel_channel *channel, struct ltt_kernel_session *session,
+               unsigned int monitor);
+
+int kernel_consumer_send_session(struct consumer_socket *sock,
+               struct ltt_kernel_session *session);
+
+int kernel_consumer_add_metadata(struct consumer_socket *sock,
+               struct ltt_kernel_session *session, unsigned int monitor);
+
+int kernel_consumer_destroy_channel(struct consumer_socket *socket,
+               struct ltt_kernel_channel *channel);
+
+int kernel_consumer_destroy_metadata(struct consumer_socket *socket,
+               struct ltt_kernel_metadata *metadata);
+
+int kernel_consumer_streams_sent(struct consumer_socket *sock,
+               struct ltt_kernel_session *session, uint64_t channel_key);
index 22ce819b525b49523b17dca282aa1656644c7825..8a364d1e597d1bd6c50dbe8caae5a890281295f6 100644 (file)
 #include <inttypes.h>
 #include <sys/types.h>
 
-#include <common/common.h>
-#include <common/hashtable/utils.h>
-#include <common/trace-chunk.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/kernel-ctl/kernel-ioctl.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/tracker.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/kernel-ctl/kernel-ioctl.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/tracker.hpp>
+#include <common/utils.hpp>
 #include <lttng/event.h>
 #include <lttng/lttng-error.h>
 #include <lttng/tracker.h>
 
 #include <lttng/userspace-probe.h>
-#include <lttng/userspace-probe-internal.h>
+#include <lttng/userspace-probe-internal.hpp>
 #include <lttng/condition/event-rule-matches.h>
-#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/condition/event-rule-matches-internal.hpp>
 #include <lttng/event-rule/event-rule.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/kernel-uprobe-internal.h>
-
-#include "event-notifier-error-accounting.h"
-#include "lttng-sessiond.h"
-#include "lttng-syscall.h"
-#include "condition-internal.h"
-#include "consumer.h"
-#include "kernel.h"
-#include "kernel-consumer.h"
-#include "kern-modules.h"
-#include "sessiond-config.h"
-#include "utils.h"
-#include "rotate.h"
-#include "modprobe.h"
-#include "tracker.h"
-#include "notification-thread-commands.h"
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/kernel-uprobe-internal.hpp>
+
+#include "event-notifier-error-accounting.hpp"
+#include "lttng-sessiond.hpp"
+#include "lttng-syscall.hpp"
+#include "condition-internal.hpp"
+#include "consumer.hpp"
+#include "kernel.hpp"
+#include "kernel-consumer.hpp"
+#include "kern-modules.hpp"
+#include "sessiond-config.hpp"
+#include "utils.hpp"
+#include "rotate.hpp"
+#include "modprobe.hpp"
+#include "tracker.hpp"
+#include "notification-thread-commands.hpp"
 
 /*
  * Key used to reference a channel between the sessiond and the consumer. This
diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h
deleted file mode 100644 (file)
index 7af1928..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_KERNEL_CTL_H
-#define _LTT_KERNEL_CTL_H
-
-#include "lttng/lttng-error.h"
-#include "lttng/tracker.h"
-#include "session.h"
-#include "snapshot.h"
-#include "trace-kernel.h"
-
-/*
- * Default size for the event list when kernel_list_events is called. This size
- * value is based on the initial LTTng 2.0 version set of tracepoints.
- *
- * This is NOT an upper bound because if the real event list size is bigger,
- * dynamic reallocation is performed.
- */
-#define KERNEL_EVENT_INIT_LIST_SIZE 64
-
-int kernel_add_channel_context(struct ltt_kernel_channel *chan,
-               struct ltt_kernel_context *ctx);
-int kernel_create_session(struct ltt_session *session);
-int kernel_create_channel(struct ltt_kernel_session *session,
-               struct lttng_channel *chan);
-int kernel_create_event(struct lttng_event *ev, struct ltt_kernel_channel *channel,
-               char *filter_expression, struct lttng_bytecode *filter);
-int kernel_disable_channel(struct ltt_kernel_channel *chan);
-int kernel_disable_event(struct ltt_kernel_event *event);
-int kernel_enable_event(struct ltt_kernel_event *event);
-int kernel_enable_channel(struct ltt_kernel_channel *chan);
-enum lttng_error_code kernel_process_attr_tracker_set_tracking_policy(
-               struct ltt_kernel_session *session,
-               enum lttng_process_attr process_attr,
-               enum lttng_tracking_policy policy);
-enum lttng_error_code kernel_process_attr_tracker_inclusion_set_add_value(
-               struct ltt_kernel_session *session,
-               enum lttng_process_attr process_attr,
-               const struct process_attr_value *value);
-enum lttng_error_code kernel_process_attr_tracker_inclusion_set_remove_value(
-               struct ltt_kernel_session *session,
-               enum lttng_process_attr process_attr,
-               const struct process_attr_value *value);
-const struct process_attr_tracker *kernel_get_process_attr_tracker(
-               struct ltt_kernel_session *session,
-               enum lttng_process_attr process_attr);
-int kernel_open_metadata(struct ltt_kernel_session *session);
-int kernel_open_metadata_stream(struct ltt_kernel_session *session);
-int kernel_open_channel_stream(struct ltt_kernel_channel *channel);
-int kernel_flush_buffer(struct ltt_kernel_channel *channel);
-int kernel_metadata_flush_buffer(int fd);
-int kernel_start_session(struct ltt_kernel_session *session);
-int kernel_stop_session(struct ltt_kernel_session *session);
-ssize_t kernel_list_events(struct lttng_event **event_list);
-void kernel_wait_quiescent(void);
-int kernel_validate_version(struct lttng_kernel_abi_tracer_version *kernel_tracer_version,
-               struct lttng_kernel_abi_tracer_abi_version *kernel_tracer_abi_version);
-void kernel_destroy_session(struct ltt_kernel_session *ksess);
-void kernel_free_session(struct ltt_kernel_session *ksess);
-void kernel_destroy_channel(struct ltt_kernel_channel *kchan);
-enum lttng_error_code kernel_snapshot_record(
-               struct ltt_kernel_session *ksess,
-               const struct consumer_output *output, int wait,
-               uint64_t nb_packets_per_stream);
-int kernel_syscall_mask(int chan_fd, char **syscall_mask, uint32_t *nr_bits);
-enum lttng_error_code kernel_rotate_session(struct ltt_session *session);
-enum lttng_error_code kernel_clear_session(struct ltt_session *session);
-
-int init_kernel_workarounds(void);
-int kernel_supports_ring_buffer_snapshot_sample_positions(void);
-int kernel_supports_ring_buffer_packet_sequence_number(void);
-int kernel_supports_event_notifiers(void);
-int init_kernel_tracer(void);
-void cleanup_kernel_tracer(void);
-bool kernel_tracer_is_initialized(void);
-
-enum lttng_error_code kernel_create_channel_subdirectories(
-               const struct ltt_kernel_session *ksess);
-
-enum lttng_error_code kernel_create_event_notifier_group_notification_fd(
-               int *event_notifier_group_notification_fd);
-enum lttng_error_code kernel_destroy_event_notifier_group_notification_fd(
-               int event_notifier_group_notification_fd);
-
-enum lttng_error_code kernel_register_event_notifier(
-               struct lttng_trigger *trigger,
-               const struct lttng_credentials *cmd_creds);
-enum lttng_error_code kernel_unregister_event_notifier(
-               const struct lttng_trigger *trigger);
-
-int kernel_get_notification_fd(void);
-
-#endif /* _LTT_KERNEL_CTL_H */
diff --git a/src/bin/lttng-sessiond/kernel.hpp b/src/bin/lttng-sessiond/kernel.hpp
new file mode 100644 (file)
index 0000000..7b466dd
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_KERNEL_CTL_H
+#define _LTT_KERNEL_CTL_H
+
+#include "lttng/lttng-error.h"
+#include "lttng/tracker.h"
+#include "session.hpp"
+#include "snapshot.hpp"
+#include "trace-kernel.hpp"
+
+/*
+ * Default size for the event list when kernel_list_events is called. This size
+ * value is based on the initial LTTng 2.0 version set of tracepoints.
+ *
+ * This is NOT an upper bound because if the real event list size is bigger,
+ * dynamic reallocation is performed.
+ */
+#define KERNEL_EVENT_INIT_LIST_SIZE 64
+
+int kernel_add_channel_context(struct ltt_kernel_channel *chan,
+               struct ltt_kernel_context *ctx);
+int kernel_create_session(struct ltt_session *session);
+int kernel_create_channel(struct ltt_kernel_session *session,
+               struct lttng_channel *chan);
+int kernel_create_event(struct lttng_event *ev, struct ltt_kernel_channel *channel,
+               char *filter_expression, struct lttng_bytecode *filter);
+int kernel_disable_channel(struct ltt_kernel_channel *chan);
+int kernel_disable_event(struct ltt_kernel_event *event);
+int kernel_enable_event(struct ltt_kernel_event *event);
+int kernel_enable_channel(struct ltt_kernel_channel *chan);
+enum lttng_error_code kernel_process_attr_tracker_set_tracking_policy(
+               struct ltt_kernel_session *session,
+               enum lttng_process_attr process_attr,
+               enum lttng_tracking_policy policy);
+enum lttng_error_code kernel_process_attr_tracker_inclusion_set_add_value(
+               struct ltt_kernel_session *session,
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value);
+enum lttng_error_code kernel_process_attr_tracker_inclusion_set_remove_value(
+               struct ltt_kernel_session *session,
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value);
+const struct process_attr_tracker *kernel_get_process_attr_tracker(
+               struct ltt_kernel_session *session,
+               enum lttng_process_attr process_attr);
+int kernel_open_metadata(struct ltt_kernel_session *session);
+int kernel_open_metadata_stream(struct ltt_kernel_session *session);
+int kernel_open_channel_stream(struct ltt_kernel_channel *channel);
+int kernel_flush_buffer(struct ltt_kernel_channel *channel);
+int kernel_metadata_flush_buffer(int fd);
+int kernel_start_session(struct ltt_kernel_session *session);
+int kernel_stop_session(struct ltt_kernel_session *session);
+ssize_t kernel_list_events(struct lttng_event **event_list);
+void kernel_wait_quiescent(void);
+int kernel_validate_version(struct lttng_kernel_abi_tracer_version *kernel_tracer_version,
+               struct lttng_kernel_abi_tracer_abi_version *kernel_tracer_abi_version);
+void kernel_destroy_session(struct ltt_kernel_session *ksess);
+void kernel_free_session(struct ltt_kernel_session *ksess);
+void kernel_destroy_channel(struct ltt_kernel_channel *kchan);
+enum lttng_error_code kernel_snapshot_record(
+               struct ltt_kernel_session *ksess,
+               const struct consumer_output *output, int wait,
+               uint64_t nb_packets_per_stream);
+int kernel_syscall_mask(int chan_fd, char **syscall_mask, uint32_t *nr_bits);
+enum lttng_error_code kernel_rotate_session(struct ltt_session *session);
+enum lttng_error_code kernel_clear_session(struct ltt_session *session);
+
+int init_kernel_workarounds(void);
+int kernel_supports_ring_buffer_snapshot_sample_positions(void);
+int kernel_supports_ring_buffer_packet_sequence_number(void);
+int kernel_supports_event_notifiers(void);
+int init_kernel_tracer(void);
+void cleanup_kernel_tracer(void);
+bool kernel_tracer_is_initialized(void);
+
+enum lttng_error_code kernel_create_channel_subdirectories(
+               const struct ltt_kernel_session *ksess);
+
+enum lttng_error_code kernel_create_event_notifier_group_notification_fd(
+               int *event_notifier_group_notification_fd);
+enum lttng_error_code kernel_destroy_event_notifier_group_notification_fd(
+               int event_notifier_group_notification_fd);
+
+enum lttng_error_code kernel_register_event_notifier(
+               struct lttng_trigger *trigger,
+               const struct lttng_credentials *cmd_creds);
+enum lttng_error_code kernel_unregister_event_notifier(
+               const struct lttng_trigger *trigger);
+
+int kernel_get_notification_fd(void);
+
+#endif /* _LTT_KERNEL_CTL_H */
diff --git a/src/bin/lttng-sessiond/lttng-sessiond.h b/src/bin/lttng-sessiond/lttng-sessiond.h
deleted file mode 100644 (file)
index 8a82c45..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2013 Raphaël Beamonte <raphael.beamonte@gmail.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_SESSIOND_H
-#define _LTT_SESSIOND_H
-
-#include <urcu.h>
-#include <urcu/wfcqueue.h>
-
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/payload.h>
-#include <common/compat/poll.h>
-#include <common/compat/socket.h>
-#include <common/uuid.h>
-
-#include "session.h"
-#include "ust-app.h"
-#include "notification-thread.h"
-#include "sessiond-config.h"
-
-/*
- * Consumer daemon state which is changed when spawning it, killing it or in
- * case of a fatal error.
- */
-enum consumerd_state {
-       CONSUMER_STARTED = 1,
-       CONSUMER_STOPPED = 2,
-       CONSUMER_ERROR   = 3,
-};
-
-/* Unique identifier of a session daemon instance. */
-extern lttng_uuid the_sessiond_uuid;
-
-/*
- * This consumer daemon state is used to validate if a client command will be
- * able to reach the consumer. If not, the client is informed. For instance,
- * doing a "lttng start" when the consumer state is set to ERROR will return an
- * error to the client.
- *
- * The following example shows a possible race condition of this scheme:
- *
- * consumer thread error happens
- *                                    client cmd arrives
- *                                    client cmd checks state -> still OK
- * consumer thread exit, sets error
- *                                    client cmd try to talk to consumer
- *                                    ...
- *
- * However, since the consumer is a different daemon, we have no way of making
- * sure the command will reach it safely even with this state flag. This is why
- * we consider that up to the state validation during command processing, the
- * command is safe. After that, we can not guarantee the correctness of the
- * client request vis-a-vis the consumer.
- */
-extern enum consumerd_state the_ust_consumerd_state;
-extern enum consumerd_state the_kernel_consumerd_state;
-
-/* Set in main.c at boot time of the daemon */
-extern struct lttng_kernel_abi_tracer_version the_kernel_tracer_version;
-extern struct lttng_kernel_abi_tracer_abi_version the_kernel_tracer_abi_version;
-
-/* Notification thread handle. */
-extern struct notification_thread_handle *the_notification_thread_handle;
-
-/*
- * This contains extra data needed for processing a command received by the
- * session daemon from the lttng client.
- */
-struct command_ctx {
-       unsigned int lttng_msg_size;
-       struct ltt_session *session;
-       /* Input message */
-       struct lttcomm_session_msg lsm;
-       /* Reply content, starts with an lttcomm_lttng_msg header. */
-       struct lttng_payload reply_payload;
-       lttng_sock_cred creds;
-};
-
-struct ust_command {
-       int sock;
-       struct ust_register_msg reg_msg;
-       struct cds_wfcq_node node;
-};
-
-/*
- * Queue used to enqueue UST registration request (ust_command) and synchronized
- * by a futex with a scheme N wakers / 1 waiters. See futex.c/.h
- */
-struct ust_cmd_queue {
-       int32_t futex;
-       struct cds_wfcq_head head;
-       struct cds_wfcq_tail tail;
-};
-
-/*
- * This is the wait queue containing wait nodes during the application
- * registration process.
- */
-struct ust_reg_wait_queue {
-       unsigned long count;
-       struct cds_list_head head;
-};
-
-/*
- * Use by the dispatch registration to queue UST command socket to wait for the
- * notify socket.
- */
-struct ust_reg_wait_node {
-       struct ust_app *app;
-       struct cds_list_head head;
-};
-
-/*
- * Used to notify that a hash table needs to be destroyed by dedicated
- * thread. Required by design because we don't want to move destroy
- * paths outside of large RCU read-side lock paths, and destroy cannot
- * be called by call_rcu thread, because it may hang (waiting for
- * call_rcu completion).
- */
-extern int the_ht_cleanup_pipe[2];
-
-extern int the_kernel_poll_pipe[2];
-
-/*
- * Populated when the daemon starts with the current page size of the system.
- * Set in main() with the current page size.
- */
-extern long the_page_size;
-
-/* Application health monitoring */
-extern struct health_app *the_health_sessiond;
-
-extern struct sessiond_config the_config;
-
-extern int the_ust_consumerd64_fd, the_ust_consumerd32_fd;
-
-/* Parent PID for --sig-parent option */
-extern pid_t the_ppid;
-/* Internal parent PID use with daemonize. */
-extern pid_t the_child_ppid;
-
-/* Consumer daemon specific control data. */
-extern struct consumer_data the_ustconsumer32_data;
-extern struct consumer_data the_ustconsumer64_data;
-extern struct consumer_data the_kconsumer_data;
-
-int sessiond_init_thread_quit_pipe(void);
-int sessiond_check_thread_quit_pipe(int fd, uint32_t events);
-int sessiond_wait_for_quit_pipe(int timeout_ms);
-int sessiond_notify_quit_pipe(void);
-void sessiond_close_quit_pipe(void);
-
-int sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size);
-void sessiond_signal_parents(void);
-
-void sessiond_set_client_thread_state(bool running);
-void sessiond_wait_client_thread_stopped(void);
-
-void *thread_manage_consumer(void *data);
-
-#endif /* _LTT_SESSIOND_H */
diff --git a/src/bin/lttng-sessiond/lttng-sessiond.hpp b/src/bin/lttng-sessiond/lttng-sessiond.hpp
new file mode 100644 (file)
index 0000000..e990740
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2013 Raphaël Beamonte <raphael.beamonte@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_SESSIOND_H
+#define _LTT_SESSIOND_H
+
+#include <urcu.h>
+#include <urcu/wfcqueue.h>
+
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/payload.hpp>
+#include <common/compat/poll.hpp>
+#include <common/compat/socket.hpp>
+#include <common/uuid.hpp>
+
+#include "session.hpp"
+#include "ust-app.hpp"
+#include "notification-thread.hpp"
+#include "sessiond-config.hpp"
+
+/*
+ * Consumer daemon state which is changed when spawning it, killing it or in
+ * case of a fatal error.
+ */
+enum consumerd_state {
+       CONSUMER_STARTED = 1,
+       CONSUMER_STOPPED = 2,
+       CONSUMER_ERROR   = 3,
+};
+
+/* Unique identifier of a session daemon instance. */
+extern lttng_uuid the_sessiond_uuid;
+
+/*
+ * This consumer daemon state is used to validate if a client command will be
+ * able to reach the consumer. If not, the client is informed. For instance,
+ * doing a "lttng start" when the consumer state is set to ERROR will return an
+ * error to the client.
+ *
+ * The following example shows a possible race condition of this scheme:
+ *
+ * consumer thread error happens
+ *                                    client cmd arrives
+ *                                    client cmd checks state -> still OK
+ * consumer thread exit, sets error
+ *                                    client cmd try to talk to consumer
+ *                                    ...
+ *
+ * However, since the consumer is a different daemon, we have no way of making
+ * sure the command will reach it safely even with this state flag. This is why
+ * we consider that up to the state validation during command processing, the
+ * command is safe. After that, we can not guarantee the correctness of the
+ * client request vis-a-vis the consumer.
+ */
+extern enum consumerd_state the_ust_consumerd_state;
+extern enum consumerd_state the_kernel_consumerd_state;
+
+/* Set in main.c at boot time of the daemon */
+extern struct lttng_kernel_abi_tracer_version the_kernel_tracer_version;
+extern struct lttng_kernel_abi_tracer_abi_version the_kernel_tracer_abi_version;
+
+/* Notification thread handle. */
+extern struct notification_thread_handle *the_notification_thread_handle;
+
+/*
+ * This contains extra data needed for processing a command received by the
+ * session daemon from the lttng client.
+ */
+struct command_ctx {
+       unsigned int lttng_msg_size;
+       struct ltt_session *session;
+       /* Input message */
+       struct lttcomm_session_msg lsm;
+       /* Reply content, starts with an lttcomm_lttng_msg header. */
+       struct lttng_payload reply_payload;
+       lttng_sock_cred creds;
+};
+
+struct ust_command {
+       int sock;
+       struct ust_register_msg reg_msg;
+       struct cds_wfcq_node node;
+};
+
+/*
+ * Queue used to enqueue UST registration request (ust_command) and synchronized
+ * by a futex with a scheme N wakers / 1 waiters. See futex.c/.h
+ */
+struct ust_cmd_queue {
+       int32_t futex;
+       struct cds_wfcq_head head;
+       struct cds_wfcq_tail tail;
+};
+
+/*
+ * This is the wait queue containing wait nodes during the application
+ * registration process.
+ */
+struct ust_reg_wait_queue {
+       unsigned long count;
+       struct cds_list_head head;
+};
+
+/*
+ * Use by the dispatch registration to queue UST command socket to wait for the
+ * notify socket.
+ */
+struct ust_reg_wait_node {
+       struct ust_app *app;
+       struct cds_list_head head;
+};
+
+/*
+ * Used to notify that a hash table needs to be destroyed by dedicated
+ * thread. Required by design because we don't want to move destroy
+ * paths outside of large RCU read-side lock paths, and destroy cannot
+ * be called by call_rcu thread, because it may hang (waiting for
+ * call_rcu completion).
+ */
+extern int the_ht_cleanup_pipe[2];
+
+extern int the_kernel_poll_pipe[2];
+
+/*
+ * Populated when the daemon starts with the current page size of the system.
+ * Set in main() with the current page size.
+ */
+extern long the_page_size;
+
+/* Application health monitoring */
+extern struct health_app *the_health_sessiond;
+
+extern struct sessiond_config the_config;
+
+extern int the_ust_consumerd64_fd, the_ust_consumerd32_fd;
+
+/* Parent PID for --sig-parent option */
+extern pid_t the_ppid;
+/* Internal parent PID use with daemonize. */
+extern pid_t the_child_ppid;
+
+/* Consumer daemon specific control data. */
+extern struct consumer_data the_ustconsumer32_data;
+extern struct consumer_data the_ustconsumer64_data;
+extern struct consumer_data the_kconsumer_data;
+
+int sessiond_init_thread_quit_pipe(void);
+int sessiond_check_thread_quit_pipe(int fd, uint32_t events);
+int sessiond_wait_for_quit_pipe(int timeout_ms);
+int sessiond_notify_quit_pipe(void);
+void sessiond_close_quit_pipe(void);
+
+int sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size);
+void sessiond_signal_parents(void);
+
+void sessiond_set_client_thread_state(bool running);
+void sessiond_wait_client_thread_stopped(void);
+
+void *thread_manage_consumer(void *data);
+
+#endif /* _LTT_SESSIOND_H */
index f14563457aeff498f1815d83c5725ce316febf76..032d023a9d7d9ca24c140937d4b58bc70fe90ead 100644 (file)
@@ -8,13 +8,13 @@
 #define _LGPL_SOURCE
 #include <stdbool.h>
 
-#include <common/common.h>
-#include <common/kernel-ctl/kernel-ctl.h>
+#include <common/common.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
 
-#include "lttng-sessiond.h"
-#include "kernel.h"
-#include "lttng-syscall.h"
-#include "utils.h"
+#include "lttng-sessiond.hpp"
+#include "kernel.hpp"
+#include "lttng-syscall.hpp"
+#include "utils.hpp"
 
 /* Global syscall table. */
 struct syscall *syscall_table;
diff --git a/src/bin/lttng-sessiond/lttng-syscall.h b/src/bin/lttng-sessiond/lttng-syscall.h
deleted file mode 100644 (file)
index fa77c70..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2014 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_SYSCALL_H
-#define LTTNG_SYSCALL_H
-
-#include <common/hashtable/hashtable.h>
-#include <lttng/event.h>
-
-#include "trace-kernel.h"
-
-/*
- * Default size of the kernel system call array. With this size, we usually
- * reallocate twice considering a 32 bit compat layer also.
- */
-#define SYSCALL_TABLE_INIT_SIZE    256
-
-/* Maximum length of a syscall name. */
-#define SYSCALL_NAME_LEN           255
-
-/*
- * Represent a kernel syscall and used when we are populating the internal
- * list.
- */
-struct syscall {
-       uint32_t index;
-       uint32_t bitness;
-       char name[SYSCALL_NAME_LEN];
-       /* Used by the list syscalls command. */
-       struct lttng_ht_node_str node;
-};
-
-/*
- * Allocated once when listing all syscalls at boot time. This is an array
- * indexed by the syscall index provided in the listing.
- */
-extern struct syscall *syscall_table;
-
-/* Use to list kernel system calls. */
-int syscall_init_table(int tracer_fd);
-ssize_t syscall_table_list(struct lttng_event **events);
-
-#endif /* LTTNG_SYSCALL_H */
diff --git a/src/bin/lttng-sessiond/lttng-syscall.hpp b/src/bin/lttng-sessiond/lttng-syscall.hpp
new file mode 100644 (file)
index 0000000..78691f9
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_SYSCALL_H
+#define LTTNG_SYSCALL_H
+
+#include <common/hashtable/hashtable.hpp>
+#include <lttng/event.h>
+
+#include "trace-kernel.hpp"
+
+/*
+ * Default size of the kernel system call array. With this size, we usually
+ * reallocate twice considering a 32 bit compat layer also.
+ */
+#define SYSCALL_TABLE_INIT_SIZE    256
+
+/* Maximum length of a syscall name. */
+#define SYSCALL_NAME_LEN           255
+
+/*
+ * Represent a kernel syscall and used when we are populating the internal
+ * list.
+ */
+struct syscall {
+       uint32_t index;
+       uint32_t bitness;
+       char name[SYSCALL_NAME_LEN];
+       /* Used by the list syscalls command. */
+       struct lttng_ht_node_str node;
+};
+
+/*
+ * Allocated once when listing all syscalls at boot time. This is an array
+ * indexed by the syscall index provided in the listing.
+ */
+extern struct syscall *syscall_table;
+
+/* Use to list kernel system calls. */
+int syscall_init_table(int tracer_fd);
+ssize_t syscall_table_list(struct lttng_event **events);
+
+#endif /* LTTNG_SYSCALL_H */
diff --git a/src/bin/lttng-sessiond/lttng-ust-abi.h b/src/bin/lttng-sessiond/lttng-ust-abi.h
deleted file mode 100644 (file)
index e2b8cf9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_UST_ABI_H
-#define LTTNG_UST_ABI_H
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-#include <lttng/ust-abi.h>
-#else /* HAVE_LIBLTTNG_UST_CTL */
-/* Use local copy of the LTTng-UST header. */
-#include "ust-abi-internal.h"
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* LTTNG_UST_ABI_H */
diff --git a/src/bin/lttng-sessiond/lttng-ust-abi.hpp b/src/bin/lttng-sessiond/lttng-ust-abi.hpp
new file mode 100644 (file)
index 0000000..faf2321
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_UST_ABI_H
+#define LTTNG_UST_ABI_H
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+#include <lttng/ust-abi.h>
+#else /* HAVE_LIBLTTNG_UST_CTL */
+/* Use local copy of the LTTng-UST header. */
+#include "ust-abi-internal.hpp"
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* LTTNG_UST_ABI_H */
diff --git a/src/bin/lttng-sessiond/lttng-ust-ctl.h b/src/bin/lttng-sessiond/lttng-ust-ctl.h
deleted file mode 100644 (file)
index 7e5713b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_UST_CTL_H
-#define LTTNG_UST_CTL_H
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-#include <lttng/ust-ctl.h>
-#else /* HAVE_LIBLTTNG_UST_CTL */
-/* Use local copy of the LTTng-UST header. */
-#include "ust-ctl-internal.h"
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* LTTNG_UST_CTL_H */
diff --git a/src/bin/lttng-sessiond/lttng-ust-ctl.hpp b/src/bin/lttng-sessiond/lttng-ust-ctl.hpp
new file mode 100644 (file)
index 0000000..dcd6bf6
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_UST_CTL_H
+#define LTTNG_UST_CTL_H
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+#include <lttng/ust-ctl.h>
+#else /* HAVE_LIBLTTNG_UST_CTL */
+/* Use local copy of the LTTng-UST header. */
+#include "ust-ctl-internal.hpp"
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* LTTNG_UST_CTL_H */
diff --git a/src/bin/lttng-sessiond/lttng-ust-error.h b/src/bin/lttng-sessiond/lttng-ust-error.h
deleted file mode 100644 (file)
index 326383b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_UST_ERROR_H
-#define LTTNG_UST_ERROR_H
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-#include <lttng/ust-error.h>
-#else /* HAVE_LIBLTTNG_UST_CTL */
-/* Use local copy of the LTTng-UST header. */
-#include "ust-error-internal.h"
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* LTTNG_UST_ERROR_H */
diff --git a/src/bin/lttng-sessiond/lttng-ust-error.hpp b/src/bin/lttng-sessiond/lttng-ust-error.hpp
new file mode 100644 (file)
index 0000000..173908e
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_UST_ERROR_H
+#define LTTNG_UST_ERROR_H
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+#include <lttng/ust-error.h>
+#else /* HAVE_LIBLTTNG_UST_CTL */
+/* Use local copy of the LTTng-UST header. */
+#include "ust-error-internal.hpp"
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* LTTNG_UST_ERROR_H */
index a676b257fc818b8b8dea711731ad3d7b2ac2e23f..30ce84eecdd1968eb9b0eb2c99cca3db67756bd6 100644 (file)
 #include <unistd.h>
 #include <ctype.h>
 
-#include <common/common.h>
-#include <common/compat/socket.h>
-#include <common/compat/getenv.h>
-#include <common/defaults.h>
-#include <common/kernel-consumer/kernel-consumer.h>
-#include <common/futex.h>
-#include <common/relayd/relayd.h>
-#include <common/utils.h>
-#include <common/daemonize.h>
-#include <common/config/session-config.h>
-#include <common/ini-config/ini-config.h>
-#include <common/dynamic-buffer.h>
-#include <lttng/event-internal.h>
-
-#include "lttng-sessiond.h"
-#include "buffer-registry.h"
-#include "channel.h"
-#include "cmd.h"
-#include "consumer.h"
-#include "context.h"
-#include "event.h"
-#include "event-notifier-error-accounting.h"
-#include "kernel.h"
-#include "kernel-consumer.h"
-#include "lttng-ust-ctl.h"
-#include "ust-consumer.h"
-#include "utils.h"
-#include "fd-limit.h"
-#include "health-sessiond.h"
-#include "testpoint.h"
-#include "notify-apps.h"
-#include "agent-thread.h"
-#include "save.h"
-#include "notification-thread.h"
-#include "notification-thread-commands.h"
-#include "rotation-thread.h"
-#include "agent.h"
-#include "ht-cleanup.h"
-#include "sessiond-config.h"
-#include "timer.h"
-#include "thread.h"
-#include "client.h"
-#include "dispatch.h"
-#include "register.h"
-#include "manage-apps.h"
-#include "manage-kernel.h"
-#include "modprobe.h"
-#include "ust-sigbus.h"
+#include <common/common.hpp>
+#include <common/compat/socket.hpp>
+#include <common/compat/getenv.hpp>
+#include <common/defaults.hpp>
+#include <common/kernel-consumer/kernel-consumer.hpp>
+#include <common/futex.hpp>
+#include <common/relayd/relayd.hpp>
+#include <common/utils.hpp>
+#include <common/daemonize.hpp>
+#include <common/config/session-config.hpp>
+#include <common/ini-config/ini-config.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <lttng/event-internal.hpp>
+
+#include "lttng-sessiond.hpp"
+#include "buffer-registry.hpp"
+#include "channel.hpp"
+#include "cmd.hpp"
+#include "consumer.hpp"
+#include "context.hpp"
+#include "event.hpp"
+#include "event-notifier-error-accounting.hpp"
+#include "kernel.hpp"
+#include "kernel-consumer.hpp"
+#include "lttng-ust-ctl.hpp"
+#include "ust-consumer.hpp"
+#include "utils.hpp"
+#include "fd-limit.hpp"
+#include "health-sessiond.hpp"
+#include "testpoint.hpp"
+#include "notify-apps.hpp"
+#include "agent-thread.hpp"
+#include "save.hpp"
+#include "notification-thread.hpp"
+#include "notification-thread-commands.hpp"
+#include "rotation-thread.hpp"
+#include "agent.hpp"
+#include "ht-cleanup.hpp"
+#include "sessiond-config.hpp"
+#include "timer.hpp"
+#include "thread.hpp"
+#include "client.hpp"
+#include "dispatch.hpp"
+#include "register.hpp"
+#include "manage-apps.hpp"
+#include "manage-kernel.hpp"
+#include "modprobe.hpp"
+#include "ust-sigbus.hpp"
 
 static const char *help_msg =
 #ifdef LTTNG_EMBED_HELP
index cff56cbadfe03a9c963bb063836d4b947b800051..e92201d464c9fec80c2e55b0822733a034fe4c69 100644 (file)
@@ -7,11 +7,11 @@
  *
  */
 
-#include "manage-apps.h"
-#include "testpoint.h"
-#include "health-sessiond.h"
-#include "utils.h"
-#include "thread.h"
+#include "manage-apps.hpp"
+#include "testpoint.hpp"
+#include "health-sessiond.hpp"
+#include "utils.hpp"
+#include "thread.hpp"
 
 struct thread_notifiers {
        struct lttng_pipe *quit_pipe;
diff --git a/src/bin/lttng-sessiond/manage-apps.h b/src/bin/lttng-sessiond/manage-apps.h
deleted file mode 100644 (file)
index dad63ba..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SESSIOND_APPLICATION_MANAGEMENT_THREAD_H
-#define SESSIOND_APPLICATION_MANAGEMENT_THREAD_H
-
-#include <stdbool.h>
-#include "lttng-sessiond.h"
-
-bool launch_application_management_thread(int apps_cmd_pipe_read_fd);
-
-#endif /* SESSIOND_APPLICATION_MANAGEMENT_THREAD_H */
diff --git a/src/bin/lttng-sessiond/manage-apps.hpp b/src/bin/lttng-sessiond/manage-apps.hpp
new file mode 100644 (file)
index 0000000..595e4a6
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SESSIOND_APPLICATION_MANAGEMENT_THREAD_H
+#define SESSIOND_APPLICATION_MANAGEMENT_THREAD_H
+
+#include <stdbool.h>
+#include "lttng-sessiond.hpp"
+
+bool launch_application_management_thread(int apps_cmd_pipe_read_fd);
+
+#endif /* SESSIOND_APPLICATION_MANAGEMENT_THREAD_H */
index d7df6ce8fac9959fe1242f1812364e8bacf4360b..f28507b225cd9bd8eeee91fc76a8b560a0ab5e8c 100644 (file)
@@ -9,15 +9,15 @@
 
 #include <signal.h>
 
-#include <common/pipe.h>
-#include <common/utils.h>
-
-#include "manage-consumer.h"
-#include "testpoint.h"
-#include "health-sessiond.h"
-#include "utils.h"
-#include "thread.h"
-#include "ust-consumer.h"
+#include <common/pipe.hpp>
+#include <common/utils.hpp>
+
+#include "manage-consumer.hpp"
+#include "testpoint.hpp"
+#include "health-sessiond.hpp"
+#include "utils.hpp"
+#include "thread.hpp"
+#include "ust-consumer.hpp"
 
 struct thread_notifiers {
        struct lttng_pipe *quit_pipe;
diff --git a/src/bin/lttng-sessiond/manage-consumer.h b/src/bin/lttng-sessiond/manage-consumer.h
deleted file mode 100644 (file)
index c99734d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SESSIOND_CONSUMER_MANAGEMENT_THREAD_H
-#define SESSIOND_CONSUMER_MANAGEMENT_THREAD_H
-
-#include <stdbool.h>
-#include "lttng-sessiond.h"
-
-bool launch_consumer_management_thread(struct consumer_data *consumer_data);
-
-#endif /* SESSIOND_CONSUMER_MANAGEMENT_THREAD_H */
diff --git a/src/bin/lttng-sessiond/manage-consumer.hpp b/src/bin/lttng-sessiond/manage-consumer.hpp
new file mode 100644 (file)
index 0000000..89bbd7a
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SESSIOND_CONSUMER_MANAGEMENT_THREAD_H
+#define SESSIOND_CONSUMER_MANAGEMENT_THREAD_H
+
+#include <stdbool.h>
+#include "lttng-sessiond.hpp"
+
+bool launch_consumer_management_thread(struct consumer_data *consumer_data);
+
+#endif /* SESSIOND_CONSUMER_MANAGEMENT_THREAD_H */
index 2ffe60919a08b08f08d51923704e040422630862..33d1f561329af0451b5604455bb12a8262e168ad 100644 (file)
@@ -7,16 +7,16 @@
  *
  */
 
-#include <common/pipe.h>
-#include <common/utils.h>
-
-#include "manage-kernel.h"
-#include "testpoint.h"
-#include "health-sessiond.h"
-#include "utils.h"
-#include "thread.h"
-#include "kernel.h"
-#include "kernel-consumer.h"
+#include <common/pipe.hpp>
+#include <common/utils.hpp>
+
+#include "manage-kernel.hpp"
+#include "testpoint.hpp"
+#include "health-sessiond.hpp"
+#include "utils.hpp"
+#include "thread.hpp"
+#include "kernel.hpp"
+#include "kernel-consumer.hpp"
 
 struct thread_notifiers {
        struct lttng_pipe *quit_pipe;
diff --git a/src/bin/lttng-sessiond/manage-kernel.h b/src/bin/lttng-sessiond/manage-kernel.h
deleted file mode 100644 (file)
index 0670377..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SESSIOND_KERNEL_MANAGEMENT_THREAD_H
-#define SESSIOND_KERNEL_MANAGEMENT_THREAD_H
-
-#include <stdbool.h>
-#include "lttng-sessiond.h"
-
-bool launch_kernel_management_thread(int kernel_poll_pipe_read_fd);
-
-#endif /* SESSIOND_KERNEL_MANAGEMENT_THREAD_H */
diff --git a/src/bin/lttng-sessiond/manage-kernel.hpp b/src/bin/lttng-sessiond/manage-kernel.hpp
new file mode 100644 (file)
index 0000000..9a68306
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SESSIOND_KERNEL_MANAGEMENT_THREAD_H
+#define SESSIOND_KERNEL_MANAGEMENT_THREAD_H
+
+#include <stdbool.h>
+#include "lttng-sessiond.hpp"
+
+bool launch_kernel_management_thread(int kernel_poll_pipe_read_fd);
+
+#endif /* SESSIOND_KERNEL_MANAGEMENT_THREAD_H */
index 4c1d62b486e2b37f4181f398a7c03da58289b65d..b0c39ef5e36e83d0edc58fb797e74f015410bf8e 100644 (file)
 #include <stdlib.h>
 #include <sys/wait.h>
 
-#include <common/common.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/utils.hpp>
 
-#include "modprobe.h"
-#include "kern-modules.h"
-#include "lttng-sessiond.h"
+#include "modprobe.hpp"
+#include "kern-modules.hpp"
+#include "lttng-sessiond.hpp"
 
 /* LTTng kernel tracer mandatory core modules list */
 struct kern_modules_param kern_modules_control_core[] = {
diff --git a/src/bin/lttng-sessiond/modprobe.h b/src/bin/lttng-sessiond/modprobe.h
deleted file mode 100644 (file)
index f0ad01c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _MODPROBE_H
-#define _MODPROBE_H
-
-void modprobe_remove_lttng_all(void);
-void modprobe_remove_lttng_control(void);
-void modprobe_remove_lttng_data(void);
-int modprobe_lttng_control(void);
-int modprobe_lttng_data(void);
-
-#endif /* _MODPROBE_H */
diff --git a/src/bin/lttng-sessiond/modprobe.hpp b/src/bin/lttng-sessiond/modprobe.hpp
new file mode 100644 (file)
index 0000000..f0ad01c
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _MODPROBE_H
+#define _MODPROBE_H
+
+void modprobe_remove_lttng_all(void);
+void modprobe_remove_lttng_control(void);
+void modprobe_remove_lttng_data(void);
+int modprobe_lttng_control(void);
+int modprobe_lttng_data(void);
+
+#endif /* _MODPROBE_H */
index 60095115947e5e8c362415b046e5d6816b5bda56..ce499eb1cb3418ac10085f1ac98baa3cf2bf2d56 100644 (file)
@@ -7,9 +7,9 @@
 
 #include <lttng/trigger/trigger.h>
 #include <lttng/lttng-error.h>
-#include "notification-thread.h"
-#include "notification-thread-commands.h"
-#include <common/error.h>
+#include "notification-thread.hpp"
+#include "notification-thread-commands.hpp"
+#include <common/error.hpp>
 #include <unistd.h>
 #include <stdint.h>
 #include <inttypes.h>
diff --git a/src/bin/lttng-sessiond/notification-thread-commands.h b/src/bin/lttng-sessiond/notification-thread-commands.h
deleted file mode 100644 (file)
index 643b0e6..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef NOTIFICATION_THREAD_COMMANDS_H
-#define NOTIFICATION_THREAD_COMMANDS_H
-
-#include <lttng/domain.h>
-#include <lttng/lttng-error.h>
-#include <urcu/rculfhash.h>
-#include "notification-thread.h"
-#include "notification-thread-internal.h"
-#include "notification-thread-events.h"
-#include <common/waiter.h>
-#include <stdbool.h>
-
-struct notification_thread_data;
-struct lttng_trigger;
-
-enum notification_thread_command_type {
-       NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER,
-       NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER,
-       NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL,
-       NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL,
-       NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING,
-       NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED,
-       NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE,
-       NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE,
-       NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS,
-       NOTIFICATION_COMMAND_TYPE_QUIT,
-       NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE,
-       NOTIFICATION_COMMAND_TYPE_GET_TRIGGER,
-};
-
-struct notification_thread_command {
-       struct cds_list_head cmd_list_node;
-
-       enum notification_thread_command_type type;
-       union {
-               /* Register trigger. */
-               struct {
-                       struct lttng_trigger *trigger;
-                       bool is_trigger_anonymous;
-               } register_trigger;
-               /* Unregister trigger. */
-               struct {
-                       const struct lttng_trigger *trigger;
-               } unregister_trigger;
-               /* Add channel. */
-               struct {
-                       struct {
-                               const char *name;
-                               uid_t uid;
-                               gid_t gid;
-                       } session;
-                       struct {
-                               const char *name;
-                               enum lttng_domain_type domain;
-                               uint64_t key;
-                               uint64_t capacity;
-                       } channel;
-               } add_channel;
-               /* Remove channel. */
-               struct {
-                       uint64_t key;
-                       enum lttng_domain_type domain;
-               } remove_channel;
-               struct {
-                       const char *session_name;
-                       uid_t uid;
-                       gid_t gid;
-                       uint64_t trace_archive_chunk_id;
-                       /* Weak reference. */
-                       struct lttng_trace_archive_location *location;
-               } session_rotation;
-               /* Add/Remove tracer event source fd. */
-               struct {
-                       int tracer_event_source_fd;
-                       enum lttng_domain_type domain;
-               } tracer_event_source;
-               /* List triggers. */
-               struct {
-                       /* Credentials of the requesting user. */
-                       uid_t uid;
-               } list_triggers;
-               /* Client communication update. */
-               struct {
-                       notification_client_id id;
-                       enum client_transmission_status status;
-               } client_communication_update;
-
-               struct {
-                       const struct lttng_trigger *trigger;
-               } get_trigger;
-
-       } parameters;
-
-       union {
-               struct {
-                       struct lttng_triggers *triggers;
-               } list_triggers;
-               struct {
-                       struct lttng_trigger *trigger;
-               } get_trigger;
-       } reply;
-       /* lttng_waiter on which to wait for command reply (optional). */
-       struct lttng_waiter reply_waiter;
-       enum lttng_error_code reply_code;
-       bool is_async;
-};
-
-enum lttng_error_code notification_thread_command_register_trigger(
-               struct notification_thread_handle *handle,
-               struct lttng_trigger *trigger,
-               bool is_anonymous_trigger);
-
-enum lttng_error_code notification_thread_command_unregister_trigger(
-               struct notification_thread_handle *handle,
-               const struct lttng_trigger *trigger);
-
-enum lttng_error_code notification_thread_command_add_channel(
-               struct notification_thread_handle *handle,
-               char *session_name, uid_t session_uid, gid_t session_gid,
-               char *channel_name, uint64_t key,
-               enum lttng_domain_type domain, uint64_t capacity);
-
-enum lttng_error_code notification_thread_command_remove_channel(
-               struct notification_thread_handle *handle,
-               uint64_t key, enum lttng_domain_type domain);
-
-enum lttng_error_code notification_thread_command_session_rotation_ongoing(
-               struct notification_thread_handle *handle,
-               const char *session_name, uid_t session_uid, gid_t session_gid,
-               uint64_t trace_archive_chunk_id);
-
-/* Ownership of location is transferred. */
-enum lttng_error_code notification_thread_command_session_rotation_completed(
-               struct notification_thread_handle *handle,
-               const char *session_name, uid_t session_uid, gid_t session_gid,
-               uint64_t trace_archive_chunk_id,
-               struct lttng_trace_archive_location *location);
-
-/*
- * Return the set of triggers visible to a given client.
- *
- * The trigger objects contained in the set are the actual trigger instances
- * used by the notification subsystem (i.e. not a copy). Given that the command
- * is only used to serialize the triggers, this is fine: the properties that
- * are serialized are immutable over the lifetime of the triggers.
- *
- * Moreover, the lifetime of the trigger instances is protected through
- * reference counting (references are held by the trigger set).
- *
- * The caller has the exclusive ownership of the returned trigger set.
- */
-enum lttng_error_code notification_thread_command_list_triggers(
-               struct notification_thread_handle *handle,
-               uid_t client_uid,
-               struct lttng_triggers **triggers);
-
-/*
- * The ownership of trigger_event_application_pipe is _not_ transferred to
- * the notification thread.
- */
-enum lttng_error_code notification_thread_command_add_tracer_event_source(
-               struct notification_thread_handle *handle,
-               int tracer_event_source_fd,
-               enum lttng_domain_type domain);
-
-enum lttng_error_code notification_thread_command_remove_tracer_event_source(
-               struct notification_thread_handle *handle,
-               int tracer_event_source_fd);
-
-void notification_thread_command_quit(
-               struct notification_thread_handle *handle);
-
-enum lttng_error_code notification_thread_command_get_trigger(
-               struct notification_thread_handle *handle,
-               const struct lttng_trigger *trigger,
-               struct lttng_trigger **real_trigger);
-
-#endif /* NOTIFICATION_THREAD_COMMANDS_H */
diff --git a/src/bin/lttng-sessiond/notification-thread-commands.hpp b/src/bin/lttng-sessiond/notification-thread-commands.hpp
new file mode 100644 (file)
index 0000000..98b0abc
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef NOTIFICATION_THREAD_COMMANDS_H
+#define NOTIFICATION_THREAD_COMMANDS_H
+
+#include <lttng/domain.h>
+#include <lttng/lttng-error.h>
+#include <urcu/rculfhash.h>
+#include "notification-thread.hpp"
+#include "notification-thread-internal.hpp"
+#include "notification-thread-events.hpp"
+#include <common/waiter.hpp>
+#include <stdbool.h>
+
+struct notification_thread_data;
+struct lttng_trigger;
+
+enum notification_thread_command_type {
+       NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER,
+       NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER,
+       NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL,
+       NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL,
+       NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING,
+       NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED,
+       NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE,
+       NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE,
+       NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS,
+       NOTIFICATION_COMMAND_TYPE_QUIT,
+       NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE,
+       NOTIFICATION_COMMAND_TYPE_GET_TRIGGER,
+};
+
+struct notification_thread_command {
+       struct cds_list_head cmd_list_node;
+
+       enum notification_thread_command_type type;
+       union {
+               /* Register trigger. */
+               struct {
+                       struct lttng_trigger *trigger;
+                       bool is_trigger_anonymous;
+               } register_trigger;
+               /* Unregister trigger. */
+               struct {
+                       const struct lttng_trigger *trigger;
+               } unregister_trigger;
+               /* Add channel. */
+               struct {
+                       struct {
+                               const char *name;
+                               uid_t uid;
+                               gid_t gid;
+                       } session;
+                       struct {
+                               const char *name;
+                               enum lttng_domain_type domain;
+                               uint64_t key;
+                               uint64_t capacity;
+                       } channel;
+               } add_channel;
+               /* Remove channel. */
+               struct {
+                       uint64_t key;
+                       enum lttng_domain_type domain;
+               } remove_channel;
+               struct {
+                       const char *session_name;
+                       uid_t uid;
+                       gid_t gid;
+                       uint64_t trace_archive_chunk_id;
+                       /* Weak reference. */
+                       struct lttng_trace_archive_location *location;
+               } session_rotation;
+               /* Add/Remove tracer event source fd. */
+               struct {
+                       int tracer_event_source_fd;
+                       enum lttng_domain_type domain;
+               } tracer_event_source;
+               /* List triggers. */
+               struct {
+                       /* Credentials of the requesting user. */
+                       uid_t uid;
+               } list_triggers;
+               /* Client communication update. */
+               struct {
+                       notification_client_id id;
+                       enum client_transmission_status status;
+               } client_communication_update;
+
+               struct {
+                       const struct lttng_trigger *trigger;
+               } get_trigger;
+
+       } parameters;
+
+       union {
+               struct {
+                       struct lttng_triggers *triggers;
+               } list_triggers;
+               struct {
+                       struct lttng_trigger *trigger;
+               } get_trigger;
+       } reply;
+       /* lttng_waiter on which to wait for command reply (optional). */
+       struct lttng_waiter reply_waiter;
+       enum lttng_error_code reply_code;
+       bool is_async;
+};
+
+enum lttng_error_code notification_thread_command_register_trigger(
+               struct notification_thread_handle *handle,
+               struct lttng_trigger *trigger,
+               bool is_anonymous_trigger);
+
+enum lttng_error_code notification_thread_command_unregister_trigger(
+               struct notification_thread_handle *handle,
+               const struct lttng_trigger *trigger);
+
+enum lttng_error_code notification_thread_command_add_channel(
+               struct notification_thread_handle *handle,
+               char *session_name, uid_t session_uid, gid_t session_gid,
+               char *channel_name, uint64_t key,
+               enum lttng_domain_type domain, uint64_t capacity);
+
+enum lttng_error_code notification_thread_command_remove_channel(
+               struct notification_thread_handle *handle,
+               uint64_t key, enum lttng_domain_type domain);
+
+enum lttng_error_code notification_thread_command_session_rotation_ongoing(
+               struct notification_thread_handle *handle,
+               const char *session_name, uid_t session_uid, gid_t session_gid,
+               uint64_t trace_archive_chunk_id);
+
+/* Ownership of location is transferred. */
+enum lttng_error_code notification_thread_command_session_rotation_completed(
+               struct notification_thread_handle *handle,
+               const char *session_name, uid_t session_uid, gid_t session_gid,
+               uint64_t trace_archive_chunk_id,
+               struct lttng_trace_archive_location *location);
+
+/*
+ * Return the set of triggers visible to a given client.
+ *
+ * The trigger objects contained in the set are the actual trigger instances
+ * used by the notification subsystem (i.e. not a copy). Given that the command
+ * is only used to serialize the triggers, this is fine: the properties that
+ * are serialized are immutable over the lifetime of the triggers.
+ *
+ * Moreover, the lifetime of the trigger instances is protected through
+ * reference counting (references are held by the trigger set).
+ *
+ * The caller has the exclusive ownership of the returned trigger set.
+ */
+enum lttng_error_code notification_thread_command_list_triggers(
+               struct notification_thread_handle *handle,
+               uid_t client_uid,
+               struct lttng_triggers **triggers);
+
+/*
+ * The ownership of trigger_event_application_pipe is _not_ transferred to
+ * the notification thread.
+ */
+enum lttng_error_code notification_thread_command_add_tracer_event_source(
+               struct notification_thread_handle *handle,
+               int tracer_event_source_fd,
+               enum lttng_domain_type domain);
+
+enum lttng_error_code notification_thread_command_remove_tracer_event_source(
+               struct notification_thread_handle *handle,
+               int tracer_event_source_fd);
+
+void notification_thread_command_quit(
+               struct notification_thread_handle *handle);
+
+enum lttng_error_code notification_thread_command_get_trigger(
+               struct notification_thread_handle *handle,
+               const struct lttng_trigger *trigger,
+               struct lttng_trigger **real_trigger);
+
+#endif /* NOTIFICATION_THREAD_COMMANDS_H */
index 6f449fc638cef0df78f88c8abcc5d575f6376ad6..dcf3c7a76632cfa09ce45fccfe711cc11d73597e 100644 (file)
@@ -6,46 +6,46 @@
  */
 
 #include "lttng/action/action.h"
-#include "lttng/trigger/trigger-internal.h"
+#include "lttng/trigger/trigger-internal.hpp"
 #define _LGPL_SOURCE
 #include <urcu.h>
 #include <urcu/rculfhash.h>
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/futex.h>
-#include <common/unix.h>
-#include <common/dynamic-buffer.h>
-#include <common/hashtable/utils.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/macros.h>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/futex.hpp>
+#include <common/unix.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/macros.hpp>
 #include <lttng/condition/condition.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/list-internal.h>
-#include <lttng/domain-internal.h>
-#include <lttng/notification/notification-internal.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/buffer-usage-internal.h>
-#include <lttng/condition/session-consumed-size-internal.h>
-#include <lttng/condition/session-rotation-internal.h>
-#include <lttng/condition/event-rule-matches-internal.h>
-#include <lttng/domain-internal.h>
-#include <lttng/notification/channel-internal.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/list-internal.hpp>
+#include <lttng/domain-internal.hpp>
+#include <lttng/notification/notification-internal.hpp>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/buffer-usage-internal.hpp>
+#include <lttng/condition/session-consumed-size-internal.hpp>
+#include <lttng/condition/session-rotation-internal.hpp>
+#include <lttng/condition/event-rule-matches-internal.hpp>
+#include <lttng/domain-internal.hpp>
+#include <lttng/notification/channel-internal.hpp>
+#include <lttng/trigger/trigger-internal.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
 
 #include <time.h>
 #include <unistd.h>
 #include <inttypes.h>
 #include <fcntl.h>
 
-#include "condition-internal.h"
-#include "event-notifier-error-accounting.h"
-#include "notification-thread.h"
-#include "notification-thread-events.h"
-#include "notification-thread-commands.h"
-#include "lttng-sessiond.h"
-#include "kernel.h"
+#include "condition-internal.hpp"
+#include "event-notifier-error-accounting.hpp"
+#include "notification-thread.hpp"
+#include "notification-thread-events.hpp"
+#include "notification-thread-commands.hpp"
+#include "lttng-sessiond.hpp"
+#include "kernel.hpp"
 
 #define CLIENT_POLL_MASK_IN (LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP)
 #define CLIENT_POLL_MASK_IN_OUT (CLIENT_POLL_MASK_IN | LPOLLOUT)
diff --git a/src/bin/lttng-sessiond/notification-thread-events.h b/src/bin/lttng-sessiond/notification-thread-events.h
deleted file mode 100644 (file)
index 2657191..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef NOTIFICATION_THREAD_EVENTS_H
-#define NOTIFICATION_THREAD_EVENTS_H
-
-#include <lttng/domain.h>
-#include "notification-thread.h"
-
-/**
- * Event handling function shall only return an error if
- * the thread should be stopped.
- */
-int handle_notification_thread_command(
-               struct notification_thread_handle *handle,
-               struct notification_thread_state *state);
-
-int handle_notification_thread_client_connect(
-               struct notification_thread_state *state);
-
-int handle_notification_thread_client_disconnect(
-               int client_fd,
-               struct notification_thread_state *state);
-
-int handle_notification_thread_client_disconnect_all(
-               struct notification_thread_state *state);
-
-int handle_notification_thread_trigger_unregister_all(
-               struct notification_thread_state *state);
-
-int handle_notification_thread_tracer_event_source_died(
-               struct notification_thread_state *state,
-               int tracer_event_source_fd);
-
-int handle_notification_thread_client_in(
-               struct notification_thread_state *state,
-               int socket);
-
-int handle_notification_thread_client_out(
-               struct notification_thread_state *state,
-               int socket);
-
-int handle_notification_thread_channel_sample(
-               struct notification_thread_state *state, int pipe,
-               enum lttng_domain_type domain);
-
-int handle_notification_thread_event_notification(
-               struct notification_thread_state *state, int pipe,
-               enum lttng_domain_type domain);
-
-#endif /* NOTIFICATION_THREAD_EVENTS_H */
diff --git a/src/bin/lttng-sessiond/notification-thread-events.hpp b/src/bin/lttng-sessiond/notification-thread-events.hpp
new file mode 100644 (file)
index 0000000..50abad9
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef NOTIFICATION_THREAD_EVENTS_H
+#define NOTIFICATION_THREAD_EVENTS_H
+
+#include <lttng/domain.h>
+#include "notification-thread.hpp"
+
+/**
+ * Event handling function shall only return an error if
+ * the thread should be stopped.
+ */
+int handle_notification_thread_command(
+               struct notification_thread_handle *handle,
+               struct notification_thread_state *state);
+
+int handle_notification_thread_client_connect(
+               struct notification_thread_state *state);
+
+int handle_notification_thread_client_disconnect(
+               int client_fd,
+               struct notification_thread_state *state);
+
+int handle_notification_thread_client_disconnect_all(
+               struct notification_thread_state *state);
+
+int handle_notification_thread_trigger_unregister_all(
+               struct notification_thread_state *state);
+
+int handle_notification_thread_tracer_event_source_died(
+               struct notification_thread_state *state,
+               int tracer_event_source_fd);
+
+int handle_notification_thread_client_in(
+               struct notification_thread_state *state,
+               int socket);
+
+int handle_notification_thread_client_out(
+               struct notification_thread_state *state,
+               int socket);
+
+int handle_notification_thread_channel_sample(
+               struct notification_thread_state *state, int pipe,
+               enum lttng_domain_type domain);
+
+int handle_notification_thread_event_notification(
+               struct notification_thread_state *state, int pipe,
+               enum lttng_domain_type domain);
+
+#endif /* NOTIFICATION_THREAD_EVENTS_H */
diff --git a/src/bin/lttng-sessiond/notification-thread-internal.h b/src/bin/lttng-sessiond/notification-thread-internal.h
deleted file mode 100644 (file)
index 9e7059a..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef NOTIFICATION_THREAD_INTERNAL_H
-#define NOTIFICATION_THREAD_INTERNAL_H
-
-#include <common/compat/socket.h>
-#include <common/credentials.h>
-#include <common/payload.h>
-#include <lttng/notification/channel-internal.h>
-#include <lttng/ref-internal.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <urcu/rculfhash.h>
-#include <urcu/ref.h>
-#include <urcu/call-rcu.h>
-#include "notification-thread.h"
-
-struct lttng_evaluation;
-struct notification_thread_handle;
-
-struct channel_key {
-       uint64_t key;
-       enum lttng_domain_type domain;
-};
-
-struct session_info {
-       struct lttng_ref ref;
-       char *name;
-       uid_t uid;
-       gid_t gid;
-       /*
-        * Hashtable containing back-refs (weak) to all channels in this session.
-        * The hashtable's key is a hash of (struct channel_key) and
-        * the value is of type (struct channel_info *).
-        */
-       struct cds_lfht *channel_infos_ht;
-       struct lttng_session_trigger_list *trigger_list;
-       /* Node in the notification thread state's sessions_ht. */
-       struct cds_lfht_node sessions_ht_node;
-       /*
-        * Weak reference to the thread state's sessions_ht. Used for removal on
-        * destruction.
-        */
-       struct cds_lfht *sessions_ht;
-       uint64_t consumed_data_size;
-       struct {
-               /* Whether a rotation is ongoing for this session. */
-               bool ongoing;
-               /* Identifier of the currently ongoing rotation. */
-               uint64_t id;
-       } rotation;
-       /* call_rcu delayed reclaim. */
-       struct rcu_head rcu_node;
-};
-
-struct channel_info {
-       struct channel_key key;
-       char *name;
-       uint64_t capacity;
-       /*
-        * A channel info holds a reference (lttng_ref) on session_info.
-        * session_info, in return, holds a weak reference to the channel.
-        */
-       struct session_info *session_info;
-       /* Node in the notification thread state's channels_ht. */
-       struct cds_lfht_node channels_ht_node;
-       /* Node in the session_info's channels_ht. */
-       struct cds_lfht_node session_info_channels_ht_node;
-       /* call_rcu delayed reclaim. */
-       struct rcu_head rcu_node;
-};
-
-/*
- * Facilities to carry the different notifications type in the action
- * processing code path.
- */
-struct lttng_event_notifier_notification {
-       uint64_t tracer_token;
-       enum lttng_domain_type type;
-       size_t capture_buf_size;
-       char *capture_buffer;
-};
-
-struct notification_client_list_element {
-       struct notification_client *client;
-       struct cds_list_head node;
-};
-
-/*
- * Thread safety of notification_client and notification_client_list.
- *
- * The notification thread (main thread) and the action executor
- * interact through client lists. Hence, when the action executor
- * thread looks-up the list of clients subscribed to a given
- * condition, it will acquire a reference to the list and lock it
- * while attempting to communicate with the various clients.
- *
- * It is not necessary to reference-count clients as they are guaranteed
- * to be 'alive' if they are present in a list and that list is locked. Indeed,
- * removing references to the client from those subscription lists is part of
- * the work performed on destruction of a client.
- *
- * No provision for other access scenarios are taken into account;
- * this is the bare minimum to make these accesses safe and the
- * notification thread's state is _not_ "thread-safe" in any general
- * sense.
- */
-struct notification_client_list {
-       pthread_mutex_t lock;
-       struct urcu_ref ref;
-       struct lttng_condition *condition;
-       /* List of triggers that have an identical condition than `condition`. */
-       struct cds_list_head triggers_list;
-       struct cds_list_head clients_list;
-       /* Weak reference to container. */
-       struct cds_lfht *notification_trigger_clients_ht;
-       struct cds_lfht_node notification_trigger_clients_ht_node;
-       /* call_rcu delayed reclaim. */
-       struct rcu_head rcu_node;
-};
-
-struct notification_client {
-       /*
-        * Nests within the notification_client_list lock.
-        *
-        * Protects the outbound communication and the active flag which
-        * is used by both the notification and action executor threads.
-        *
-        * The remaining fields of the object can be used without any
-        * synchronization as they are either immutable (id, creds, version) or
-        * only accessed by the notification thread.
-        */
-       pthread_mutex_t lock;
-       notification_client_id id;
-       int socket;
-       /* Client protocol version. */
-       uint8_t major, minor;
-       uid_t uid;
-       gid_t gid;
-       bool is_sessiond;
-       /*
-        * Indicates if the credentials and versions of the client have been
-        * checked.
-        */
-       bool validated;
-       /*
-        * Conditions to which the client's notification channel is subscribed.
-        * List of struct lttng_condition_list_node. The condition member is
-        * owned by the client.
-        */
-       struct cds_list_head condition_list;
-       struct cds_lfht_node client_socket_ht_node;
-       struct cds_lfht_node client_id_ht_node;
-       struct {
-               /*
-                * If a client's communication is inactive, it means that a
-                * fatal error has occurred (could be either a protocol error or
-                * the socket API returned a fatal error). No further
-                * communication should be attempted; the client is queued for
-                * clean-up.
-                */
-               bool active;
-               struct {
-                       /*
-                        * During the reception of a message, the reception
-                        * buffers' "size" is set to contain the current
-                        * message's complete payload.
-                        */
-                       struct lttng_payload payload;
-                       /* Bytes left to receive for the current message. */
-                       size_t bytes_to_receive;
-                       /* FDs left to receive for the current message. */
-                       int fds_to_receive;
-                       /* Type of the message being received. */
-                       enum lttng_notification_channel_message_type msg_type;
-                       /*
-                        * Indicates whether or not credentials are expected
-                        * from the client.
-                        */
-                       bool expect_creds;
-                       /*
-                        * Indicates whether or not credentials were received
-                        * from the client.
-                        */
-                       bool creds_received;
-                       /* Only used during credentials reception. */
-                       lttng_sock_cred creds;
-               } inbound;
-               struct {
-                       /*
-                        * Indicates whether or not a notification addressed to
-                        * this client was dropped because a command reply was
-                        * already buffered.
-                        *
-                        * A notification is dropped whenever the buffer is not
-                        * empty.
-                        */
-                       bool dropped_notification;
-                       /*
-                        * Indicates whether or not a command reply is already
-                        * buffered. In this case, it means that the client is
-                        * not consuming command replies before emitting a new
-                        * one. This could be caused by a protocol error or a
-                        * misbehaving/malicious client.
-                        */
-                       bool queued_command_reply;
-                       struct lttng_payload payload;
-               } outbound;
-       } communication;
-       /* call_rcu delayed reclaim. */
-       struct rcu_head rcu_node;
-};
-
-enum client_transmission_status {
-       CLIENT_TRANSMISSION_STATUS_COMPLETE,
-       CLIENT_TRANSMISSION_STATUS_QUEUED,
-       /* Communication failure. */
-       CLIENT_TRANSMISSION_STATUS_FAIL,
-       /* Fatal error. */
-       CLIENT_TRANSMISSION_STATUS_ERROR,
-};
-
-bool notification_client_list_get(struct notification_client_list *list);
-
-void notification_client_list_put(struct notification_client_list *list);
-
-/* Only returns a non-zero value if a fatal error occurred. */
-typedef int (*report_client_transmission_result_cb)(
-               struct notification_client *client,
-               enum client_transmission_status status,
-               void *user_data);
-
-int notification_client_list_send_evaluation(
-               struct notification_client_list *list,
-               const struct lttng_trigger *trigger,
-               const struct lttng_evaluation *evaluation,
-               const struct lttng_credentials *source_object_creds,
-               report_client_transmission_result_cb client_report,
-               void *user_data);
-
-int notification_thread_client_communication_update(
-               struct notification_thread_handle *handle,
-               notification_client_id id,
-               enum client_transmission_status transmission_status);
-
-/*
- * Takes ownership of the payload if present.
- */
-struct lttng_event_notifier_notification *lttng_event_notifier_notification_create(
-               uint64_t tracer_token,
-               enum lttng_domain_type domain,
-               char *payload,
-               size_t payload_size);
-
-void lttng_event_notifier_notification_destroy(
-               struct lttng_event_notifier_notification *event_notifier_notification);
-
-#endif /* NOTIFICATION_THREAD_INTERNAL_H */
diff --git a/src/bin/lttng-sessiond/notification-thread-internal.hpp b/src/bin/lttng-sessiond/notification-thread-internal.hpp
new file mode 100644 (file)
index 0000000..497484b
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef NOTIFICATION_THREAD_INTERNAL_H
+#define NOTIFICATION_THREAD_INTERNAL_H
+
+#include <common/compat/socket.hpp>
+#include <common/credentials.hpp>
+#include <common/payload.hpp>
+#include <lttng/notification/channel-internal.hpp>
+#include <lttng/ref-internal.hpp>
+#include <stdbool.h>
+#include <unistd.h>
+#include <urcu/rculfhash.h>
+#include <urcu/ref.h>
+#include <urcu/call-rcu.h>
+#include "notification-thread.hpp"
+
+struct lttng_evaluation;
+struct notification_thread_handle;
+
+struct channel_key {
+       uint64_t key;
+       enum lttng_domain_type domain;
+};
+
+struct session_info {
+       struct lttng_ref ref;
+       char *name;
+       uid_t uid;
+       gid_t gid;
+       /*
+        * Hashtable containing back-refs (weak) to all channels in this session.
+        * The hashtable's key is a hash of (struct channel_key) and
+        * the value is of type (struct channel_info *).
+        */
+       struct cds_lfht *channel_infos_ht;
+       struct lttng_session_trigger_list *trigger_list;
+       /* Node in the notification thread state's sessions_ht. */
+       struct cds_lfht_node sessions_ht_node;
+       /*
+        * Weak reference to the thread state's sessions_ht. Used for removal on
+        * destruction.
+        */
+       struct cds_lfht *sessions_ht;
+       uint64_t consumed_data_size;
+       struct {
+               /* Whether a rotation is ongoing for this session. */
+               bool ongoing;
+               /* Identifier of the currently ongoing rotation. */
+               uint64_t id;
+       } rotation;
+       /* call_rcu delayed reclaim. */
+       struct rcu_head rcu_node;
+};
+
+struct channel_info {
+       struct channel_key key;
+       char *name;
+       uint64_t capacity;
+       /*
+        * A channel info holds a reference (lttng_ref) on session_info.
+        * session_info, in return, holds a weak reference to the channel.
+        */
+       struct session_info *session_info;
+       /* Node in the notification thread state's channels_ht. */
+       struct cds_lfht_node channels_ht_node;
+       /* Node in the session_info's channels_ht. */
+       struct cds_lfht_node session_info_channels_ht_node;
+       /* call_rcu delayed reclaim. */
+       struct rcu_head rcu_node;
+};
+
+/*
+ * Facilities to carry the different notifications type in the action
+ * processing code path.
+ */
+struct lttng_event_notifier_notification {
+       uint64_t tracer_token;
+       enum lttng_domain_type type;
+       size_t capture_buf_size;
+       char *capture_buffer;
+};
+
+struct notification_client_list_element {
+       struct notification_client *client;
+       struct cds_list_head node;
+};
+
+/*
+ * Thread safety of notification_client and notification_client_list.
+ *
+ * The notification thread (main thread) and the action executor
+ * interact through client lists. Hence, when the action executor
+ * thread looks-up the list of clients subscribed to a given
+ * condition, it will acquire a reference to the list and lock it
+ * while attempting to communicate with the various clients.
+ *
+ * It is not necessary to reference-count clients as they are guaranteed
+ * to be 'alive' if they are present in a list and that list is locked. Indeed,
+ * removing references to the client from those subscription lists is part of
+ * the work performed on destruction of a client.
+ *
+ * No provision for other access scenarios are taken into account;
+ * this is the bare minimum to make these accesses safe and the
+ * notification thread's state is _not_ "thread-safe" in any general
+ * sense.
+ */
+struct notification_client_list {
+       pthread_mutex_t lock;
+       struct urcu_ref ref;
+       struct lttng_condition *condition;
+       /* List of triggers that have an identical condition than `condition`. */
+       struct cds_list_head triggers_list;
+       struct cds_list_head clients_list;
+       /* Weak reference to container. */
+       struct cds_lfht *notification_trigger_clients_ht;
+       struct cds_lfht_node notification_trigger_clients_ht_node;
+       /* call_rcu delayed reclaim. */
+       struct rcu_head rcu_node;
+};
+
+struct notification_client {
+       /*
+        * Nests within the notification_client_list lock.
+        *
+        * Protects the outbound communication and the active flag which
+        * is used by both the notification and action executor threads.
+        *
+        * The remaining fields of the object can be used without any
+        * synchronization as they are either immutable (id, creds, version) or
+        * only accessed by the notification thread.
+        */
+       pthread_mutex_t lock;
+       notification_client_id id;
+       int socket;
+       /* Client protocol version. */
+       uint8_t major, minor;
+       uid_t uid;
+       gid_t gid;
+       bool is_sessiond;
+       /*
+        * Indicates if the credentials and versions of the client have been
+        * checked.
+        */
+       bool validated;
+       /*
+        * Conditions to which the client's notification channel is subscribed.
+        * List of struct lttng_condition_list_node. The condition member is
+        * owned by the client.
+        */
+       struct cds_list_head condition_list;
+       struct cds_lfht_node client_socket_ht_node;
+       struct cds_lfht_node client_id_ht_node;
+       struct {
+               /*
+                * If a client's communication is inactive, it means that a
+                * fatal error has occurred (could be either a protocol error or
+                * the socket API returned a fatal error). No further
+                * communication should be attempted; the client is queued for
+                * clean-up.
+                */
+               bool active;
+               struct {
+                       /*
+                        * During the reception of a message, the reception
+                        * buffers' "size" is set to contain the current
+                        * message's complete payload.
+                        */
+                       struct lttng_payload payload;
+                       /* Bytes left to receive for the current message. */
+                       size_t bytes_to_receive;
+                       /* FDs left to receive for the current message. */
+                       int fds_to_receive;
+                       /* Type of the message being received. */
+                       enum lttng_notification_channel_message_type msg_type;
+                       /*
+                        * Indicates whether or not credentials are expected
+                        * from the client.
+                        */
+                       bool expect_creds;
+                       /*
+                        * Indicates whether or not credentials were received
+                        * from the client.
+                        */
+                       bool creds_received;
+                       /* Only used during credentials reception. */
+                       lttng_sock_cred creds;
+               } inbound;
+               struct {
+                       /*
+                        * Indicates whether or not a notification addressed to
+                        * this client was dropped because a command reply was
+                        * already buffered.
+                        *
+                        * A notification is dropped whenever the buffer is not
+                        * empty.
+                        */
+                       bool dropped_notification;
+                       /*
+                        * Indicates whether or not a command reply is already
+                        * buffered. In this case, it means that the client is
+                        * not consuming command replies before emitting a new
+                        * one. This could be caused by a protocol error or a
+                        * misbehaving/malicious client.
+                        */
+                       bool queued_command_reply;
+                       struct lttng_payload payload;
+               } outbound;
+       } communication;
+       /* call_rcu delayed reclaim. */
+       struct rcu_head rcu_node;
+};
+
+enum client_transmission_status {
+       CLIENT_TRANSMISSION_STATUS_COMPLETE,
+       CLIENT_TRANSMISSION_STATUS_QUEUED,
+       /* Communication failure. */
+       CLIENT_TRANSMISSION_STATUS_FAIL,
+       /* Fatal error. */
+       CLIENT_TRANSMISSION_STATUS_ERROR,
+};
+
+bool notification_client_list_get(struct notification_client_list *list);
+
+void notification_client_list_put(struct notification_client_list *list);
+
+/* Only returns a non-zero value if a fatal error occurred. */
+typedef int (*report_client_transmission_result_cb)(
+               struct notification_client *client,
+               enum client_transmission_status status,
+               void *user_data);
+
+int notification_client_list_send_evaluation(
+               struct notification_client_list *list,
+               const struct lttng_trigger *trigger,
+               const struct lttng_evaluation *evaluation,
+               const struct lttng_credentials *source_object_creds,
+               report_client_transmission_result_cb client_report,
+               void *user_data);
+
+int notification_thread_client_communication_update(
+               struct notification_thread_handle *handle,
+               notification_client_id id,
+               enum client_transmission_status transmission_status);
+
+/*
+ * Takes ownership of the payload if present.
+ */
+struct lttng_event_notifier_notification *lttng_event_notifier_notification_create(
+               uint64_t tracer_token,
+               enum lttng_domain_type domain,
+               char *payload,
+               size_t payload_size);
+
+void lttng_event_notifier_notification_destroy(
+               struct lttng_event_notifier_notification *event_notifier_notification);
+
+#endif /* NOTIFICATION_THREAD_INTERNAL_H */
index 867fc7c044c679d658c331c3c94420bd8b1bf2e2..74e37902db0056d5599fa57dd4da4a72678451ea 100644 (file)
@@ -7,30 +7,30 @@
 
 #define _LGPL_SOURCE
 #include <lttng/trigger/trigger.h>
-#include <lttng/notification/channel-internal.h>
-#include <lttng/notification/notification-internal.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/buffer-usage-internal.h>
-#include <common/error.h>
-#include <common/config/session-config.h>
-#include <common/defaults.h>
-#include <common/utils.h>
-#include <common/align.h>
-#include <common/time.h>
+#include <lttng/notification/channel-internal.hpp>
+#include <lttng/notification/notification-internal.hpp>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/buffer-usage-internal.hpp>
+#include <common/error.hpp>
+#include <common/config/session-config.hpp>
+#include <common/defaults.hpp>
+#include <common/utils.hpp>
+#include <common/align.hpp>
+#include <common/time.hpp>
 #include <sys/stat.h>
 #include <time.h>
 #include <signal.h>
 
-#include "notification-thread.h"
-#include "notification-thread-events.h"
-#include "notification-thread-commands.h"
-#include "lttng-sessiond.h"
-#include "health-sessiond.h"
-#include "thread.h"
-#include "testpoint.h"
+#include "notification-thread.hpp"
+#include "notification-thread-events.hpp"
+#include "notification-thread-commands.hpp"
+#include "lttng-sessiond.hpp"
+#include "health-sessiond.hpp"
+#include "thread.hpp"
+#include "testpoint.hpp"
 
-#include "kernel.h"
-#include <common/kernel-ctl/kernel-ctl.h>
+#include "kernel.hpp"
+#include <common/kernel-ctl/kernel-ctl.hpp>
 
 #include <urcu.h>
 #include <urcu/list.h>
diff --git a/src/bin/lttng-sessiond/notification-thread.h b/src/bin/lttng-sessiond/notification-thread.h
deleted file mode 100644 (file)
index 8b4c7af..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef NOTIFICATION_THREAD_H
-#define NOTIFICATION_THREAD_H
-
-#include "action-executor.h"
-#include "thread.h"
-#include <common/compat/poll.h>
-#include <common/hashtable/hashtable.h>
-#include <common/pipe.h>
-#include <lttng/trigger/trigger.h>
-#include <lttng/domain.h>
-#include <pthread.h>
-#include <semaphore.h>
-#include <urcu.h>
-#include <urcu/list.h>
-#include <urcu/rculfhash.h>
-
-typedef uint64_t notification_client_id;
-
-/*
- * The notification thread holds no ownership of the tracer event source pipe
- * file descriptor. The tracer management logic must remove the event source
- * from the notification thread (see external commands) before releasing
- * this file descriptor.
- */
-struct notification_event_tracer_event_source_element {
-       int fd;
-       /*
-        * A tracer event source can be removed from the notification thread's
-        * poll set before the end of its lifetime (for instance, when an error
-        * or hang-up is detected on its file descriptor). This is done to
-        * allow the notification thread to ignore follow-up events on this
-        * file descriptors.
-        *
-        * Under such circumstances, the notification thread still expects
-        * the normal clean-up to occur through the 'REMOVE_TRACER_EVENT_SOURCE'
-        * command.
-        */
-       bool is_fd_in_poll_set;
-       enum lttng_domain_type domain;
-       struct cds_list_head node;
-};
-
-struct notification_trigger_tokens_ht_element {
-       uint64_t token;
-       /* Weak reference to the trigger. */
-       struct lttng_trigger *trigger;
-       struct cds_lfht_node node;
-       /* call_rcu delayed reclaim. */
-       struct rcu_head rcu_node;
-};
-
-struct notification_thread_handle {
-       /*
-        * Queue of struct notification command.
-        * event_pipe must be WRITE(2) to signal that a new command
-        * has been enqueued.
-        */
-       struct {
-               struct lttng_pipe *event_pipe;
-               struct cds_list_head list;
-               pthread_mutex_t lock;
-       } cmd_queue;
-       /*
-        * Read side of pipes used to receive channel status info collected
-        * by the various consumer daemons.
-        */
-       struct {
-               int ust32_consumer;
-               int ust64_consumer;
-               int kernel_consumer;
-       } channel_monitoring_pipes;
-       /* Used to wait for the launch of the notification thread. */
-       sem_t ready;
-};
-
-/**
- * This thread maintains an internal state associating clients and triggers.
- *
- * In order to speed-up and simplify queries, hash tables providing the
- * following associations are maintained:
- *
- *   - client_socket_ht: associate a client's socket (fd) to its
- *             "struct notification_client".
- *             This hash table owns the "struct notification_client" which must
- *             thus be disposed-of on removal from the hash table.
- *
- *   - client_id_ht: associate a client's id to its "struct notification_client"
- *             This hash table holds a _weak_ reference to the
- *             "struct notification_client".
- *
- *   - channel_triggers_ht:
- *             associates a channel key to a list of
- *             struct lttng_trigger_list_nodes. The triggers in this list are
- *             those that have conditions that apply to a particular channel.
- *             A channel entry is only created when a channel is added; the
- *             list of triggers applying to such a channel is built at that
- *             moment.
- *             This hash table owns the list, but not the triggers themselves.
- *
- *   - session_triggers_ht:
- *             associates a session name to a list of
- *             struct lttng_trigger_list_nodes. The triggers in this list are
- *             those that have conditions that apply to a particular session.
- *             A session entry is only created when a session is created; the
- *             list of triggers applying to this new session is built at that
- *             moment. This happens at the time of creation of a session_info.
- *             Likewise, the list is destroyed at the time of the session_info's
- *             destruction.
- *
- *   - channel_state_ht:
- *             associates a pair (channel key, channel domain) to its last
- *             sampled state received from the consumer daemon
- *             (struct channel_state).
- *             This previous sample is kept to implement edge-triggered
- *             conditions as we need to detect the state transitions.
- *             This hash table owns the channel state.
- *
- *   - notification_trigger_clients_ht:
- *             associates notification-emitting triggers to clients
- *             (struct notification_client_list) subscribed to those
- *             conditions.
- *             The condition's hash and match functions are used directly since
- *             all triggers in this hash table have the "notify" action.
- *             This hash table holds no ownership.
- *
- *   - channels_ht:
- *             associates a channel_key to a struct channel_info. The hash table
- *             holds the ownership of the struct channel_info.
- *
- *   - sessions_ht:
- *             associates a session_name (hash) to a struct session_info. The
- *             hash table holds no ownership of the struct session_info;
- *             the session_info structure is owned by the session's various
- *             channels through their struct channel_info (ref-counting is used).
- *
- *   - triggers_ht:
- *             associates a trigger to a struct lttng_trigger_ht_element.
- *             The hash table holds the ownership of the
- *             lttng_trigger_ht_elements along with the triggers themselves.
- *   - triggers_by_name_uid_ht:
- *             associates a trigger (name, uid) tuple to
- *             a struct lttng_trigger_ht_element.
- *             The hash table does not hold any ownership and is used strictly
- *             for lookup on registration.
- *   - tracer_event_sources_list:
- *             A list of tracer event source (read side fd) of type
-*              struct notification_event_tracer_event_source_element.
-*
- *
- * The thread reacts to the following internal events:
- *   1) creation of a tracing channel,
- *   2) destruction of a tracing channel,
- *   3) registration of a trigger,
- *   4) unregistration of a trigger,
- *   5) reception of a channel monitor sample from the consumer daemon,
- *   6) Session rotation ongoing,
- *   7) Session rotation completed,
- *   8) registration of a tracer event source,
- *   9) unregistration of a tracer event source,
- *
- * Events specific to notification-emitting triggers:
- *   9) connection of a notification client,
- *   10) disconnection of a notification client,
- *   11) subscription of a client to a conditions' notifications,
- *   12) unsubscription of a client from a conditions' notifications,
- *
- *
- * 1) Creation of a tracing channel
- *    - notification_trigger_clients_ht is traversed to identify
- *      triggers which apply to this new channel,
- *      - triggers identified are added to the channel_triggers_ht.
- *    - add channel to channels_ht
- *    - if it is the first channel of a session, a session_info is created and
- *      added to the sessions_ht. A list of the triggers associated with that
- *      session is built, and it is added to session_triggers_ht.
- *
- * 2) Destruction of a tracing channel
- *    - remove entry from channel_triggers_ht, releasing the list wrapper and
- *      elements,
- *    - remove entry from the channel_state_ht.
- *    - remove channel from channels_ht
- *    - if it was the last known channel of a session, the session_info
- *      structure is torndown, which in return destroys the list of triggers
- *      applying to that session.
- *
- * 3) Registration of a trigger
- *    - if the trigger's action is of type "notify",
- *      - traverse the list of conditions of every client to build a list of
- *        clients which have to be notified when this trigger's condition is met,
- *        - add list of clients (even if it is empty) to the
- *          notification_trigger_clients_ht,
- *    - add trigger to channel_triggers_ht (if applicable),
- *    - add trigger to session_triggers_ht (if applicable),
- *    - add trigger to triggers_by_name_uid_ht
- *    - add trigger to triggers_ht
- *    - evaluate the trigger's condition right away to react if that condition
- *      is true from the beginning.
- *
- * 4) Unregistration of a trigger
- *    - if the trigger's action is of type "notify",
- *      - remove the trigger from the notification_trigger_clients_ht,
- *    - remove trigger from channel_triggers_ht (if applicable),
- *    - remove trigger from session_triggers_ht (if applicable),
- *    - remove trigger from triggers_by_name_uid_ht
- *    - remove trigger from triggers_ht
- *
- * 5) Reception of a channel monitor sample from the consumer daemon
- *    - evaluate the conditions associated with the triggers found in
- *      the channel_triggers_ht,
- *      - if a condition evaluates to "true" and the condition is of type
- *        "notify", query the notification_trigger_clients_ht and send
- *        a notification to the clients.
- *
- * 6) Session rotation ongoing
- *
- * 7) Session rotation completed
- *
- * 8) Registration of a tracer event source
- *    - Add the tracer event source of the application to
- *      tracer_event_sources_list,
- *    - Add the trace event source to the pollset.
- *
- * 8) Unregistration of a tracer event source
- *    - Remove the tracer event source of the application from
- *      tracer_event_sources_list,
- *    - Remove the trace event source from the pollset.
- *
- * 10) Connection of a client
- *    - add client socket to the client_socket_ht,
- *    - add client socket to the client_id_ht.
- *
- * 11) Disconnection of a client
- *    - remove client socket from the client_id_ht,
- *    - remove client socket from the client_socket_ht,
- *    - traverse all conditions to which the client is subscribed and remove
- *      the client from the notification_trigger_clients_ht.
- *
- * 12) Subscription of a client to a condition's notifications
- *    - Add the condition to the client's list of subscribed conditions,
- *    - Look-up notification_trigger_clients_ht and add the client to
- *      list of clients.
- *    - Evaluate the condition for the client that subscribed if the trigger
- *      was already registered.
- *
- * 13) Unsubscription of a client to a condition's notifications
- *    - Remove the condition from the client's list of subscribed conditions,
- *    - Look-up notification_trigger_clients_ht and remove the client
- *      from the list of clients.
- */
-struct notification_thread_state {
-       int notification_channel_socket;
-       struct lttng_poll_event events;
-       struct cds_lfht *client_socket_ht;
-       struct cds_lfht *client_id_ht;
-       struct cds_lfht *channel_triggers_ht;
-       struct cds_lfht *session_triggers_ht;
-       struct cds_lfht *channel_state_ht;
-       struct cds_lfht *notification_trigger_clients_ht;
-       struct cds_lfht *channels_ht;
-       struct cds_lfht *sessions_ht;
-       struct cds_lfht *triggers_ht;
-       struct cds_lfht *triggers_by_name_uid_ht;
-       struct cds_lfht *trigger_tokens_ht;
-       struct {
-               uint64_t next_tracer_token;
-               uint64_t name_offset;
-       } trigger_id;
-       /*
-        * Read side of the pipes used to receive tracer events. As their name
-        * implies, tracer event source activity originate from either
-        * registered applications (user space tracer) or from the kernel
-        * tracer.
-        *
-        * The list is not protected by a lock since add and remove operations
-        * are currently done only by the notification thread through in
-        * response to blocking commands.
-        */
-       struct cds_list_head tracer_event_sources_list;
-       notification_client_id next_notification_client_id;
-       struct action_executor *executor;
-
-       /*
-        * Indicates the thread to break for the poll event processing loop and
-        * call _poll_wait() again.
-        *
-        * This is necessary because some events on one fd might trigger the
-        * consumption of another fd.
-        * For example, a single _poll_wait() call can return notification
-        * thread commands and events from the tracer event source (event
-        * notifier).
-        * Picture a scenario where we receive two events:
-        *  the first one is a _REMOVE_TRACER_EVENT_SOURCE command, and
-        *  the second is an POLLIN on the tracer event source fd.
-        *
-        * The _REMOVE_TRACER_EVENT_SOURCE will read all the data of the
-        * removed tracer event source.
-        *
-        * The second event is now invalid has we consumed all the data for
-        * which we received the POLLIN.
-        *
-        * For this reason, we need to break for the event processing loop and
-        * call _poll_wait() again to get a clean view of the activity on the
-        * fds.
-        */
-       bool restart_poll;
-};
-
-/* notification_thread_data takes ownership of the channel monitor pipes. */
-struct notification_thread_handle *notification_thread_handle_create(
-               struct lttng_pipe *ust32_channel_monitor_pipe,
-               struct lttng_pipe *ust64_channel_monitor_pipe,
-               struct lttng_pipe *kernel_channel_monitor_pipe);
-void notification_thread_handle_destroy(
-               struct notification_thread_handle *handle);
-struct lttng_thread *launch_notification_thread(
-               struct notification_thread_handle *handle);
-
-#endif /* NOTIFICATION_THREAD_H */
diff --git a/src/bin/lttng-sessiond/notification-thread.hpp b/src/bin/lttng-sessiond/notification-thread.hpp
new file mode 100644 (file)
index 0000000..3444af9
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef NOTIFICATION_THREAD_H
+#define NOTIFICATION_THREAD_H
+
+#include "action-executor.hpp"
+#include "thread.hpp"
+#include <common/compat/poll.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/pipe.hpp>
+#include <lttng/trigger/trigger.h>
+#include <lttng/domain.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <urcu.h>
+#include <urcu/list.h>
+#include <urcu/rculfhash.h>
+
+typedef uint64_t notification_client_id;
+
+/*
+ * The notification thread holds no ownership of the tracer event source pipe
+ * file descriptor. The tracer management logic must remove the event source
+ * from the notification thread (see external commands) before releasing
+ * this file descriptor.
+ */
+struct notification_event_tracer_event_source_element {
+       int fd;
+       /*
+        * A tracer event source can be removed from the notification thread's
+        * poll set before the end of its lifetime (for instance, when an error
+        * or hang-up is detected on its file descriptor). This is done to
+        * allow the notification thread to ignore follow-up events on this
+        * file descriptors.
+        *
+        * Under such circumstances, the notification thread still expects
+        * the normal clean-up to occur through the 'REMOVE_TRACER_EVENT_SOURCE'
+        * command.
+        */
+       bool is_fd_in_poll_set;
+       enum lttng_domain_type domain;
+       struct cds_list_head node;
+};
+
+struct notification_trigger_tokens_ht_element {
+       uint64_t token;
+       /* Weak reference to the trigger. */
+       struct lttng_trigger *trigger;
+       struct cds_lfht_node node;
+       /* call_rcu delayed reclaim. */
+       struct rcu_head rcu_node;
+};
+
+struct notification_thread_handle {
+       /*
+        * Queue of struct notification command.
+        * event_pipe must be WRITE(2) to signal that a new command
+        * has been enqueued.
+        */
+       struct {
+               struct lttng_pipe *event_pipe;
+               struct cds_list_head list;
+               pthread_mutex_t lock;
+       } cmd_queue;
+       /*
+        * Read side of pipes used to receive channel status info collected
+        * by the various consumer daemons.
+        */
+       struct {
+               int ust32_consumer;
+               int ust64_consumer;
+               int kernel_consumer;
+       } channel_monitoring_pipes;
+       /* Used to wait for the launch of the notification thread. */
+       sem_t ready;
+};
+
+/**
+ * This thread maintains an internal state associating clients and triggers.
+ *
+ * In order to speed-up and simplify queries, hash tables providing the
+ * following associations are maintained:
+ *
+ *   - client_socket_ht: associate a client's socket (fd) to its
+ *             "struct notification_client".
+ *             This hash table owns the "struct notification_client" which must
+ *             thus be disposed-of on removal from the hash table.
+ *
+ *   - client_id_ht: associate a client's id to its "struct notification_client"
+ *             This hash table holds a _weak_ reference to the
+ *             "struct notification_client".
+ *
+ *   - channel_triggers_ht:
+ *             associates a channel key to a list of
+ *             struct lttng_trigger_list_nodes. The triggers in this list are
+ *             those that have conditions that apply to a particular channel.
+ *             A channel entry is only created when a channel is added; the
+ *             list of triggers applying to such a channel is built at that
+ *             moment.
+ *             This hash table owns the list, but not the triggers themselves.
+ *
+ *   - session_triggers_ht:
+ *             associates a session name to a list of
+ *             struct lttng_trigger_list_nodes. The triggers in this list are
+ *             those that have conditions that apply to a particular session.
+ *             A session entry is only created when a session is created; the
+ *             list of triggers applying to this new session is built at that
+ *             moment. This happens at the time of creation of a session_info.
+ *             Likewise, the list is destroyed at the time of the session_info's
+ *             destruction.
+ *
+ *   - channel_state_ht:
+ *             associates a pair (channel key, channel domain) to its last
+ *             sampled state received from the consumer daemon
+ *             (struct channel_state).
+ *             This previous sample is kept to implement edge-triggered
+ *             conditions as we need to detect the state transitions.
+ *             This hash table owns the channel state.
+ *
+ *   - notification_trigger_clients_ht:
+ *             associates notification-emitting triggers to clients
+ *             (struct notification_client_list) subscribed to those
+ *             conditions.
+ *             The condition's hash and match functions are used directly since
+ *             all triggers in this hash table have the "notify" action.
+ *             This hash table holds no ownership.
+ *
+ *   - channels_ht:
+ *             associates a channel_key to a struct channel_info. The hash table
+ *             holds the ownership of the struct channel_info.
+ *
+ *   - sessions_ht:
+ *             associates a session_name (hash) to a struct session_info. The
+ *             hash table holds no ownership of the struct session_info;
+ *             the session_info structure is owned by the session's various
+ *             channels through their struct channel_info (ref-counting is used).
+ *
+ *   - triggers_ht:
+ *             associates a trigger to a struct lttng_trigger_ht_element.
+ *             The hash table holds the ownership of the
+ *             lttng_trigger_ht_elements along with the triggers themselves.
+ *   - triggers_by_name_uid_ht:
+ *             associates a trigger (name, uid) tuple to
+ *             a struct lttng_trigger_ht_element.
+ *             The hash table does not hold any ownership and is used strictly
+ *             for lookup on registration.
+ *   - tracer_event_sources_list:
+ *             A list of tracer event source (read side fd) of type
+*              struct notification_event_tracer_event_source_element.
+*
+ *
+ * The thread reacts to the following internal events:
+ *   1) creation of a tracing channel,
+ *   2) destruction of a tracing channel,
+ *   3) registration of a trigger,
+ *   4) unregistration of a trigger,
+ *   5) reception of a channel monitor sample from the consumer daemon,
+ *   6) Session rotation ongoing,
+ *   7) Session rotation completed,
+ *   8) registration of a tracer event source,
+ *   9) unregistration of a tracer event source,
+ *
+ * Events specific to notification-emitting triggers:
+ *   9) connection of a notification client,
+ *   10) disconnection of a notification client,
+ *   11) subscription of a client to a conditions' notifications,
+ *   12) unsubscription of a client from a conditions' notifications,
+ *
+ *
+ * 1) Creation of a tracing channel
+ *    - notification_trigger_clients_ht is traversed to identify
+ *      triggers which apply to this new channel,
+ *      - triggers identified are added to the channel_triggers_ht.
+ *    - add channel to channels_ht
+ *    - if it is the first channel of a session, a session_info is created and
+ *      added to the sessions_ht. A list of the triggers associated with that
+ *      session is built, and it is added to session_triggers_ht.
+ *
+ * 2) Destruction of a tracing channel
+ *    - remove entry from channel_triggers_ht, releasing the list wrapper and
+ *      elements,
+ *    - remove entry from the channel_state_ht.
+ *    - remove channel from channels_ht
+ *    - if it was the last known channel of a session, the session_info
+ *      structure is torndown, which in return destroys the list of triggers
+ *      applying to that session.
+ *
+ * 3) Registration of a trigger
+ *    - if the trigger's action is of type "notify",
+ *      - traverse the list of conditions of every client to build a list of
+ *        clients which have to be notified when this trigger's condition is met,
+ *        - add list of clients (even if it is empty) to the
+ *          notification_trigger_clients_ht,
+ *    - add trigger to channel_triggers_ht (if applicable),
+ *    - add trigger to session_triggers_ht (if applicable),
+ *    - add trigger to triggers_by_name_uid_ht
+ *    - add trigger to triggers_ht
+ *    - evaluate the trigger's condition right away to react if that condition
+ *      is true from the beginning.
+ *
+ * 4) Unregistration of a trigger
+ *    - if the trigger's action is of type "notify",
+ *      - remove the trigger from the notification_trigger_clients_ht,
+ *    - remove trigger from channel_triggers_ht (if applicable),
+ *    - remove trigger from session_triggers_ht (if applicable),
+ *    - remove trigger from triggers_by_name_uid_ht
+ *    - remove trigger from triggers_ht
+ *
+ * 5) Reception of a channel monitor sample from the consumer daemon
+ *    - evaluate the conditions associated with the triggers found in
+ *      the channel_triggers_ht,
+ *      - if a condition evaluates to "true" and the condition is of type
+ *        "notify", query the notification_trigger_clients_ht and send
+ *        a notification to the clients.
+ *
+ * 6) Session rotation ongoing
+ *
+ * 7) Session rotation completed
+ *
+ * 8) Registration of a tracer event source
+ *    - Add the tracer event source of the application to
+ *      tracer_event_sources_list,
+ *    - Add the trace event source to the pollset.
+ *
+ * 8) Unregistration of a tracer event source
+ *    - Remove the tracer event source of the application from
+ *      tracer_event_sources_list,
+ *    - Remove the trace event source from the pollset.
+ *
+ * 10) Connection of a client
+ *    - add client socket to the client_socket_ht,
+ *    - add client socket to the client_id_ht.
+ *
+ * 11) Disconnection of a client
+ *    - remove client socket from the client_id_ht,
+ *    - remove client socket from the client_socket_ht,
+ *    - traverse all conditions to which the client is subscribed and remove
+ *      the client from the notification_trigger_clients_ht.
+ *
+ * 12) Subscription of a client to a condition's notifications
+ *    - Add the condition to the client's list of subscribed conditions,
+ *    - Look-up notification_trigger_clients_ht and add the client to
+ *      list of clients.
+ *    - Evaluate the condition for the client that subscribed if the trigger
+ *      was already registered.
+ *
+ * 13) Unsubscription of a client to a condition's notifications
+ *    - Remove the condition from the client's list of subscribed conditions,
+ *    - Look-up notification_trigger_clients_ht and remove the client
+ *      from the list of clients.
+ */
+struct notification_thread_state {
+       int notification_channel_socket;
+       struct lttng_poll_event events;
+       struct cds_lfht *client_socket_ht;
+       struct cds_lfht *client_id_ht;
+       struct cds_lfht *channel_triggers_ht;
+       struct cds_lfht *session_triggers_ht;
+       struct cds_lfht *channel_state_ht;
+       struct cds_lfht *notification_trigger_clients_ht;
+       struct cds_lfht *channels_ht;
+       struct cds_lfht *sessions_ht;
+       struct cds_lfht *triggers_ht;
+       struct cds_lfht *triggers_by_name_uid_ht;
+       struct cds_lfht *trigger_tokens_ht;
+       struct {
+               uint64_t next_tracer_token;
+               uint64_t name_offset;
+       } trigger_id;
+       /*
+        * Read side of the pipes used to receive tracer events. As their name
+        * implies, tracer event source activity originate from either
+        * registered applications (user space tracer) or from the kernel
+        * tracer.
+        *
+        * The list is not protected by a lock since add and remove operations
+        * are currently done only by the notification thread through in
+        * response to blocking commands.
+        */
+       struct cds_list_head tracer_event_sources_list;
+       notification_client_id next_notification_client_id;
+       struct action_executor *executor;
+
+       /*
+        * Indicates the thread to break for the poll event processing loop and
+        * call _poll_wait() again.
+        *
+        * This is necessary because some events on one fd might trigger the
+        * consumption of another fd.
+        * For example, a single _poll_wait() call can return notification
+        * thread commands and events from the tracer event source (event
+        * notifier).
+        * Picture a scenario where we receive two events:
+        *  the first one is a _REMOVE_TRACER_EVENT_SOURCE command, and
+        *  the second is an POLLIN on the tracer event source fd.
+        *
+        * The _REMOVE_TRACER_EVENT_SOURCE will read all the data of the
+        * removed tracer event source.
+        *
+        * The second event is now invalid has we consumed all the data for
+        * which we received the POLLIN.
+        *
+        * For this reason, we need to break for the event processing loop and
+        * call _poll_wait() again to get a clean view of the activity on the
+        * fds.
+        */
+       bool restart_poll;
+};
+
+/* notification_thread_data takes ownership of the channel monitor pipes. */
+struct notification_thread_handle *notification_thread_handle_create(
+               struct lttng_pipe *ust32_channel_monitor_pipe,
+               struct lttng_pipe *ust64_channel_monitor_pipe,
+               struct lttng_pipe *kernel_channel_monitor_pipe);
+void notification_thread_handle_destroy(
+               struct notification_thread_handle *handle);
+struct lttng_thread *launch_notification_thread(
+               struct notification_thread_handle *handle);
+
+#endif /* NOTIFICATION_THREAD_H */
index 0e799ff261a5b11d0822004e5293f0b0c96d1a77..8e238e5c15ba4a68a471979fead43753061954b5 100644 (file)
@@ -7,16 +7,16 @@
 
 #define _LGPL_SOURCE
 
-#include <common/common.h>
-#include <common/utils.h>
-
-#include "fd-limit.h"
-#include "lttng-sessiond.h"
-#include "notify-apps.h"
-#include "health-sessiond.h"
-#include "testpoint.h"
-#include "utils.h"
-#include "thread.h"
+#include <common/common.hpp>
+#include <common/utils.hpp>
+
+#include "fd-limit.hpp"
+#include "lttng-sessiond.hpp"
+#include "notify-apps.hpp"
+#include "health-sessiond.hpp"
+#include "testpoint.hpp"
+#include "utils.hpp"
+#include "thread.hpp"
 
 struct thread_notifiers {
        struct lttng_pipe *quit_pipe;
diff --git a/src/bin/lttng-sessiond/notify-apps.h b/src/bin/lttng-sessiond/notify-apps.h
deleted file mode 100644 (file)
index ab6289a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef UST_THREAD_H
-#define UST_THREAD_H
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-bool launch_application_notification_thread(int apps_cmd_notify_pipe_read_fd);
-
-#else /* HAVE_LIBLTTNG_UST_CTL */
-
-static
-bool launch_application_notification_thread(int apps_cmd_notify_pipe_read_fd)
-{
-       return true;
-}
-
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* UST_THREAD_H */
diff --git a/src/bin/lttng-sessiond/notify-apps.hpp b/src/bin/lttng-sessiond/notify-apps.hpp
new file mode 100644 (file)
index 0000000..ab6289a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef UST_THREAD_H
+#define UST_THREAD_H
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+bool launch_application_notification_thread(int apps_cmd_notify_pipe_read_fd);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+static
+bool launch_application_notification_thread(int apps_cmd_notify_pipe_read_fd)
+{
+       return true;
+}
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* UST_THREAD_H */
index 2d629b547e396dd1eee8ff1f3c6cc5aecaaa21d5..b6922e74dad715ebe8f786f2d8061387de35fdb4 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #include <signal.h>
-#include "lttng-sessiond.h"
+#include "lttng-sessiond.hpp"
 
 /* Notify parents that we are ready for cmd and health check */
 void sessiond_signal_parents(void)
index 5bcc637b0f5c18be82d5ef217f58309e991ffa24..37e41db4833ad7520ca830f5b6595e1ea7899678 100644 (file)
 #include <stddef.h>
 #include <stdlib.h>
 #include <urcu.h>
-#include <common/futex.h>
-#include <common/macros.h>
-#include <common/shm.h>
-#include <common/utils.h>
+#include <common/futex.hpp>
+#include <common/macros.hpp>
+#include <common/shm.hpp>
+#include <common/utils.hpp>
 #include <sys/stat.h>
 
-#include "register.h"
-#include "lttng-sessiond.h"
-#include "testpoint.h"
-#include "health-sessiond.h"
-#include "fd-limit.h"
-#include "utils.h"
-#include "thread.h"
+#include "register.hpp"
+#include "lttng-sessiond.hpp"
+#include "testpoint.hpp"
+#include "health-sessiond.hpp"
+#include "fd-limit.hpp"
+#include "utils.hpp"
+#include "thread.hpp"
 
 struct thread_state {
        struct lttng_pipe *quit_pipe;
diff --git a/src/bin/lttng-sessiond/register.h b/src/bin/lttng-sessiond/register.h
deleted file mode 100644 (file)
index 7f5b088..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SESSIOND_APPLICATION_REGISTRATION_THREAD_H
-#define SESSIOND_APPLICATION_REGISTRATION_THREAD_H
-
-#include <stdbool.h>
-#include "lttng-sessiond.h"
-
-struct lttng_thread *launch_application_registration_thread(
-               struct ust_cmd_queue *cmd_queue);
-
-#endif /* SESSIOND_APPLICATION_REGISTRATION_THREAD_H */
diff --git a/src/bin/lttng-sessiond/register.hpp b/src/bin/lttng-sessiond/register.hpp
new file mode 100644 (file)
index 0000000..7ca79c5
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SESSIOND_APPLICATION_REGISTRATION_THREAD_H
+#define SESSIOND_APPLICATION_REGISTRATION_THREAD_H
+
+#include <stdbool.h>
+#include "lttng-sessiond.hpp"
+
+struct lttng_thread *launch_application_registration_thread(
+               struct ust_cmd_queue *cmd_queue);
+
+#endif /* SESSIOND_APPLICATION_REGISTRATION_THREAD_H */
index cdf95f353dbbfa2cb0ba276cdba6292d26dc92ae..51fc5e8aad81a6e94f73bdb5984beaaea45f4412 100644 (file)
@@ -8,32 +8,32 @@
 
 #define _LGPL_SOURCE
 #include <lttng/trigger/trigger.h>
-#include <common/error.h>
-#include <common/config/session-config.h>
-#include <common/defaults.h>
-#include <common/utils.h>
-#include <common/futex.h>
-#include <common/align.h>
-#include <common/time.h>
-#include <common/hashtable/utils.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/credentials.h>
+#include <common/error.hpp>
+#include <common/config/session-config.hpp>
+#include <common/defaults.hpp>
+#include <common/utils.hpp>
+#include <common/futex.hpp>
+#include <common/align.hpp>
+#include <common/time.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/credentials.hpp>
 #include <sys/stat.h>
 #include <time.h>
 #include <signal.h>
 #include <inttypes.h>
 
-#include <lttng/notification/channel-internal.h>
-#include <lttng/rotate-internal.h>
-
-#include "session.h"
-#include "rotate.h"
-#include "rotation-thread.h"
-#include "lttng-sessiond.h"
-#include "health-sessiond.h"
-#include "cmd.h"
-#include "utils.h"
-#include "notification-thread-commands.h"
+#include <lttng/notification/channel-internal.hpp>
+#include <lttng/rotate-internal.hpp>
+
+#include "session.hpp"
+#include "rotate.hpp"
+#include "rotation-thread.hpp"
+#include "lttng-sessiond.hpp"
+#include "health-sessiond.hpp"
+#include "cmd.hpp"
+#include "utils.hpp"
+#include "notification-thread-commands.hpp"
 
 #include <urcu.h>
 #include <urcu/list.h>
diff --git a/src/bin/lttng-sessiond/rotate.h b/src/bin/lttng-sessiond/rotate.h
deleted file mode 100644 (file)
index a2adaf0..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef ROTATE_H
-#define ROTATE_H
-
-#include "rotation-thread.h"
-#include <stdint.h>
-
-/*
- * Subscribe/unsubscribe the notification_channel from the rotation_thread to
- * session usage notifications to perform size-based rotations.
- */
-int subscribe_session_consumed_size_rotation(struct ltt_session *session,
-               uint64_t size,
-               struct notification_thread_handle *notification_thread_handle);
-int unsubscribe_session_consumed_size_rotation(struct ltt_session *session,
-               struct notification_thread_handle *notification_thread_handle);
-
-#endif /* ROTATE_H */
diff --git a/src/bin/lttng-sessiond/rotate.hpp b/src/bin/lttng-sessiond/rotate.hpp
new file mode 100644 (file)
index 0000000..965a8c7
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef ROTATE_H
+#define ROTATE_H
+
+#include "rotation-thread.hpp"
+#include <stdint.h>
+
+/*
+ * Subscribe/unsubscribe the notification_channel from the rotation_thread to
+ * session usage notifications to perform size-based rotations.
+ */
+int subscribe_session_consumed_size_rotation(struct ltt_session *session,
+               uint64_t size,
+               struct notification_thread_handle *notification_thread_handle);
+int unsubscribe_session_consumed_size_rotation(struct ltt_session *session,
+               struct notification_thread_handle *notification_thread_handle);
+
+#endif /* ROTATE_H */
index 8754d48a1d2eeb519d2273cba67332c01bf50f31..0479b6bc7eec5cbe5a66583dff73b70f9304d68d 100644 (file)
@@ -8,34 +8,34 @@
 
 #define _LGPL_SOURCE
 #include <lttng/trigger/trigger.h>
-#include <common/error.h>
-#include <common/config/session-config.h>
-#include <common/defaults.h>
-#include <common/utils.h>
-#include <common/futex.h>
-#include <common/align.h>
-#include <common/time.h>
-#include <common/hashtable/utils.h>
+#include <common/error.hpp>
+#include <common/config/session-config.hpp>
+#include <common/defaults.hpp>
+#include <common/utils.hpp>
+#include <common/futex.hpp>
+#include <common/align.hpp>
+#include <common/time.hpp>
+#include <common/hashtable/utils.hpp>
 #include <sys/stat.h>
 #include <time.h>
 #include <signal.h>
 #include <inttypes.h>
 
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <lttng/notification/channel-internal.h>
-#include <lttng/rotate-internal.h>
-#include <lttng/location-internal.h>
-
-#include "rotation-thread.h"
-#include "lttng-sessiond.h"
-#include "health-sessiond.h"
-#include "rotate.h"
-#include "cmd.h"
-#include "session.h"
-#include "timer.h"
-#include "notification-thread-commands.h"
-#include "utils.h"
-#include "thread.h"
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <lttng/notification/channel-internal.hpp>
+#include <lttng/rotate-internal.hpp>
+#include <lttng/location-internal.hpp>
+
+#include "rotation-thread.hpp"
+#include "lttng-sessiond.hpp"
+#include "health-sessiond.hpp"
+#include "rotate.hpp"
+#include "cmd.hpp"
+#include "session.hpp"
+#include "timer.hpp"
+#include "notification-thread-commands.hpp"
+#include "utils.hpp"
+#include "thread.hpp"
 
 #include <urcu.h>
 #include <urcu/list.h>
diff --git a/src/bin/lttng-sessiond/rotation-thread.h b/src/bin/lttng-sessiond/rotation-thread.h
deleted file mode 100644 (file)
index 27ef395..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef ROTATION_THREAD_H
-#define ROTATION_THREAD_H
-
-#include <urcu/list.h>
-#include <urcu.h>
-#include <urcu/rculfhash.h>
-#include <lttng/domain.h>
-#include <common/pipe.h>
-#include <common/compat/poll.h>
-#include <common/hashtable/hashtable.h>
-#include <pthread.h>
-#include <semaphore.h>
-#include "session.h"
-#include "notification-thread.h"
-
-extern struct lttng_notification_channel *rotate_notification_channel;
-
-enum rotation_thread_job_type {
-       ROTATION_THREAD_JOB_TYPE_SCHEDULED_ROTATION,
-       ROTATION_THREAD_JOB_TYPE_CHECK_PENDING_ROTATION
-};
-
-struct rotation_thread_timer_queue;
-struct rotation_thread_handle;
-
-struct rotation_thread_timer_queue *rotation_thread_timer_queue_create(void);
-void rotation_thread_timer_queue_destroy(
-               struct rotation_thread_timer_queue *queue);
-
-struct rotation_thread_handle *rotation_thread_handle_create(
-               struct rotation_thread_timer_queue *rotation_timer_queue,
-               struct notification_thread_handle *notification_thread_handle);
-
-void rotation_thread_handle_destroy(
-               struct rotation_thread_handle *handle);
-
-void rotation_thread_enqueue_job(struct rotation_thread_timer_queue *queue,
-               enum rotation_thread_job_type job_type,
-               struct ltt_session *session);
-
-bool launch_rotation_thread(struct rotation_thread_handle *handle);
-
-#endif /* ROTATION_THREAD_H */
diff --git a/src/bin/lttng-sessiond/rotation-thread.hpp b/src/bin/lttng-sessiond/rotation-thread.hpp
new file mode 100644 (file)
index 0000000..d2bbf29
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef ROTATION_THREAD_H
+#define ROTATION_THREAD_H
+
+#include <urcu/list.h>
+#include <urcu.h>
+#include <urcu/rculfhash.h>
+#include <lttng/domain.h>
+#include <common/pipe.hpp>
+#include <common/compat/poll.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <pthread.h>
+#include <semaphore.h>
+#include "session.hpp"
+#include "notification-thread.hpp"
+
+extern struct lttng_notification_channel *rotate_notification_channel;
+
+enum rotation_thread_job_type {
+       ROTATION_THREAD_JOB_TYPE_SCHEDULED_ROTATION,
+       ROTATION_THREAD_JOB_TYPE_CHECK_PENDING_ROTATION
+};
+
+struct rotation_thread_timer_queue;
+struct rotation_thread_handle;
+
+struct rotation_thread_timer_queue *rotation_thread_timer_queue_create(void);
+void rotation_thread_timer_queue_destroy(
+               struct rotation_thread_timer_queue *queue);
+
+struct rotation_thread_handle *rotation_thread_handle_create(
+               struct rotation_thread_timer_queue *rotation_timer_queue,
+               struct notification_thread_handle *notification_thread_handle);
+
+void rotation_thread_handle_destroy(
+               struct rotation_thread_handle *handle);
+
+void rotation_thread_enqueue_job(struct rotation_thread_timer_queue *queue,
+               enum rotation_thread_job_type job_type,
+               struct ltt_session *session);
+
+bool launch_rotation_thread(struct rotation_thread_handle *handle);
+
+#endif /* ROTATION_THREAD_H */
index 2055e867de5eac86496a7cd599c0aee488510026..16b2705149e9fd59ce1ffedfa63ae8b32fa1922b 100644 (file)
 #include <urcu/uatomic.h>
 #include <unistd.h>
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/config/session-config.h>
-#include <common/utils.h>
-#include <common/runas.h>
-#include <lttng/save-internal.h>
-
-#include "kernel.h"
-#include "save.h"
-#include "session.h"
-#include "lttng-syscall.h"
-#include "trace-ust.h"
-#include "agent.h"
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/config/session-config.hpp>
+#include <common/utils.hpp>
+#include <common/runas.hpp>
+#include <lttng/save-internal.hpp>
+
+#include "kernel.hpp"
+#include "save.hpp"
+#include "session.hpp"
+#include "lttng-syscall.hpp"
+#include "trace-ust.hpp"
+#include "agent.hpp"
 
 /* Return LTTNG_OK on success else a LTTNG_ERR* code. */
 static
diff --git a/src/bin/lttng-sessiond/save.h b/src/bin/lttng-sessiond/save.h
deleted file mode 100644 (file)
index a39a12a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SAVE_H
-#define SAVE_H
-
-#include <lttng/save.h>
-#include <common/compat/socket.h>
-
-int cmd_save_sessions(struct lttng_save_session_attr *attr,
-       lttng_sock_cred *creds);
-
-#endif /* SAVE_H */
diff --git a/src/bin/lttng-sessiond/save.hpp b/src/bin/lttng-sessiond/save.hpp
new file mode 100644 (file)
index 0000000..367b41c
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SAVE_H
+#define SAVE_H
+
+#include <lttng/save.h>
+#include <common/compat/socket.hpp>
+
+int cmd_save_sessions(struct lttng_save_session_attr *attr,
+       lttng_sock_cred *creds);
+
+#endif /* SAVE_H */
index 64fd19d04485023815f73ed27adb9a6abcf914e7..5cc74ffe027c13202095061d22176756cfd57e44 100644 (file)
 #include <sys/types.h>
 #include <pthread.h>
 
-#include <common/common.h>
-#include <common/utils.h>
-#include <common/trace-chunk.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/location-internal.h>
-#include "lttng-sessiond.h"
-#include "kernel.h"
-
-#include "session.h"
-#include "utils.h"
-#include "trace-ust.h"
-#include "timer.h"
-#include "cmd.h"
+#include <common/common.hpp>
+#include <common/utils.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <lttng/location-internal.hpp>
+#include "lttng-sessiond.hpp"
+#include "kernel.hpp"
+
+#include "session.hpp"
+#include "utils.hpp"
+#include "trace-ust.hpp"
+#include "timer.hpp"
+#include "cmd.hpp"
 
 struct ltt_session_destroy_notifier_element {
        ltt_session_destroy_notifier notifier;
diff --git a/src/bin/lttng-sessiond/session.h b/src/bin/lttng-sessiond/session.h
deleted file mode 100644 (file)
index 1a31d3f..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_SESSION_H
-#define _LTT_SESSION_H
-
-#include <limits.h>
-#include <stdbool.h>
-#include <urcu/list.h>
-
-#include <common/hashtable/hashtable.h>
-#include <common/dynamic-array.h>
-#include <lttng/rotation.h>
-#include <lttng/location.h>
-#include <lttng/lttng-error.h>
-
-#include "snapshot.h"
-#include "trace-kernel.h"
-#include "consumer.h"
-
-struct ltt_ust_session;
-
-typedef void (*ltt_session_destroy_notifier)(const struct ltt_session *session,
-               void *user_data);
-typedef void (*ltt_session_clear_notifier)(const struct ltt_session *session,
-               void *user_data);
-
-/*
- * Tracing session list
- *
- * Statically declared in session.c and can be accessed by using
- * session_get_list() function that returns the pointer to the list.
- */
-struct ltt_session_list {
-       /*
-        * This lock protects any read/write access to the list and
-        * next_uuid. All public functions in session.c acquire this
-        * lock and release it before returning. If none of those
-        * functions are used, the lock MUST be acquired in order to
-        * iterate or/and do any actions on that list.
-        */
-       pthread_mutex_t lock;
-       /*
-        * This condition variable is signaled on every removal from
-        * the session list.
-        */
-       pthread_cond_t removal_cond;
-
-       /*
-        * Session unique ID generator. The session list lock MUST be
-        * upon update and read of this counter.
-        */
-       uint64_t next_uuid;
-
-       /* Linked list head */
-       struct cds_list_head head;
-};
-
-/*
- * This data structure contains information needed to identify a tracing
- * session for both LTTng and UST.
- */
-struct ltt_session {
-       char name[NAME_MAX];
-       bool has_auto_generated_name;
-       bool name_contains_creation_time;
-       char hostname[LTTNG_HOST_NAME_MAX]; /* Local hostname. */
-       /* Path of the last closed chunk. */
-       char last_chunk_path[LTTNG_PATH_MAX];
-       time_t creation_time;
-       struct ltt_kernel_session *kernel_session;
-       struct ltt_ust_session *ust_session;
-       struct urcu_ref ref;
-       /*
-        * Protect any read/write on this session data structure. This lock must be
-        * acquired *before* using any public functions declared below. Use
-        * session_lock() and session_unlock() for that.
-        */
-       pthread_mutex_t lock;
-       struct cds_list_head list;
-       uint64_t id;            /* session unique identifier */
-       /* Indicates if the session has been added to the session list and ht.*/
-       bool published;
-       /* Indicates if a destroy command has been applied to this session. */
-       bool destroyed;
-       /* UID/GID of the user owning the session */
-       uid_t uid;
-       gid_t gid;
-       /*
-        * Network session handle. A value of 0 means that there is no remote
-        * session established.
-        */
-       uint64_t net_handle;
-       /*
-        * This consumer is only set when the create_session_uri call is made.
-        * This contains the temporary information for a consumer output. Upon
-        * creation of the UST or kernel session, this consumer, if available, is
-        * copied into those sessions.
-        */
-       struct consumer_output *consumer;
-       /*
-        * Indicates whether or not the user has specified an output directory
-        * or if it was configured using the default configuration.
-        */
-       bool has_user_specified_directory;
-       /* Did at least ONE start command has been triggered?. */
-       unsigned int has_been_started:1;
-       /*
-        * Is the session active? Start trace command sets this to 1 and the stop
-        * command reset it to 0.
-        */
-       unsigned int active:1;
-
-       /* Snapshot representation in a session. */
-       struct snapshot snapshot;
-       /* Indicate if the session has to output the traces or not. */
-       unsigned int output_traces;
-       /*
-        * This session is in snapshot mode. This means that channels enabled
-        * will be set in overwrite mode by default and must be in mmap
-        * output mode. Note that snapshots can be taken on a session that
-        * is not in "snapshot_mode". This parameter only affects channel
-        * creation defaults.
-        */
-       unsigned int snapshot_mode;
-       /*
-        * A session that has channels that don't use 'mmap' output can't be
-        * used to capture snapshots. This is set to true whenever a
-        * 'splice' kernel channel is enabled.
-        */
-       bool has_non_mmap_channel;
-       /*
-        * Timer set when the session is created for live reading.
-        */
-       unsigned int live_timer;
-       /*
-        * Path where to keep the shared memory files.
-        */
-       char shm_path[PATH_MAX];
-       /*
-        * Node in ltt_sessions_ht_by_id.
-        */
-       struct lttng_ht_node_u64 node;
-       /*
-        * Node in ltt_sessions_ht_by_name.
-        */
-       struct lttng_ht_node_str node_by_name;
-       /*
-        * Timer to check periodically if a relay and/or consumer has completed
-        * the last rotation.
-        */
-       bool rotation_pending_check_timer_enabled;
-       timer_t rotation_pending_check_timer;
-       /* Timer to periodically rotate a session. */
-       bool rotation_schedule_timer_enabled;
-       timer_t rotation_schedule_timer;
-       /* Value for periodic rotations, 0 if disabled. */
-       uint64_t rotate_timer_period;
-       /* Value for size-based rotations, 0 if disabled. */
-       uint64_t rotate_size;
-       /*
-        * Keep a state if this session was rotated after the last stop command.
-        * We only allow one rotation after a stop. At destroy, we also need to
-        * know if a rotation occurred since the last stop to rename the current
-        * chunk. After a stop followed by rotate, all subsequent clear
-        * (without prior start) will succeed, but will be effect-less.
-        */
-       bool rotated_after_last_stop;
-       /*
-        * Track whether the session was cleared after last stop. All subsequent
-        * clear (without prior start) will succeed, but will be effect-less. A
-        * subsequent rotate (without prior start) will return an error.
-        */
-       bool cleared_after_last_stop;
-       /*
-        * True if the session has had an explicit non-quiet rotation.
-        */
-       bool rotated;
-       /*
-        * Condition and trigger for size-based rotations.
-        */
-       struct lttng_condition *rotate_condition;
-       struct lttng_trigger *rotate_trigger;
-       LTTNG_OPTIONAL(uint64_t) most_recent_chunk_id;
-       struct lttng_trace_chunk *current_trace_chunk;
-       struct lttng_trace_chunk *chunk_being_archived;
-       /* Current state of a rotation. */
-       enum lttng_rotation_state rotation_state;
-       bool quiet_rotation;
-       char *last_archived_chunk_name;
-       LTTNG_OPTIONAL(uint64_t) last_archived_chunk_id;
-       struct lttng_dynamic_array destroy_notifiers;
-       struct lttng_dynamic_array clear_notifiers;
-       /* Session base path override. Set non-null. */
-       char *base_path;
-};
-
-enum lttng_error_code session_create(const char *name, uid_t uid, gid_t gid,
-               struct ltt_session **out_session);
-void session_lock(struct ltt_session *session);
-void session_unlock(struct ltt_session *session);
-
-/*
- * The session list lock covers more ground than its name implies. While
- * it does protect against concurent mutations of the session list, it is
- * also used as a multi-session lock when synchronizing newly-registered
- * 'user space tracer' and 'agent' applications.
- *
- * In other words, it prevents tracer configurations from changing while they
- * are being transmitted to the various applications.
- */
-void session_lock_list(void);
-int session_trylock_list(void);
-void session_unlock_list(void);
-
-void session_destroy(struct ltt_session *session);
-int session_add_destroy_notifier(struct ltt_session *session,
-               ltt_session_destroy_notifier notifier, void *user_data);
-
-int session_add_clear_notifier(struct ltt_session *session,
-               ltt_session_clear_notifier notifier, void *user_data);
-void session_notify_clear(struct ltt_session *session);
-
-bool session_get(struct ltt_session *session);
-void session_put(struct ltt_session *session);
-
-enum consumer_dst_type session_get_consumer_destination_type(
-               const struct ltt_session *session);
-const char *session_get_net_consumer_hostname(
-               const struct ltt_session *session);
-void session_get_net_consumer_ports(
-               const struct ltt_session *session,
-               uint16_t *control_port, uint16_t *data_port);
-struct lttng_trace_archive_location *session_get_trace_archive_location(
-               const struct ltt_session *session);
-
-struct ltt_session *session_find_by_name(const char *name);
-struct ltt_session *session_find_by_id(uint64_t id);
-
-struct ltt_session_list *session_get_list(void);
-void session_list_wait_empty(void);
-
-bool session_access_ok(struct ltt_session *session, uid_t uid);
-
-int session_reset_rotation_state(struct ltt_session *session,
-               enum lttng_rotation_state result);
-
-/* Create a new trace chunk object from the session's configuration. */
-struct lttng_trace_chunk *session_create_new_trace_chunk(
-               const struct ltt_session *session,
-               const struct consumer_output *consumer_output_override,
-               const char *session_base_path_override,
-               const char *chunk_name_override);
-
-/*
- * Set `new_trace_chunk` as the session's current trace chunk. A reference
- * to `new_trace_chunk` is acquired by the session. The chunk is created
- * on remote peers (consumer and relay daemons).
- *
- * A reference to the session's current trace chunk is returned through
- * `current_session_trace_chunk` on success.
- */
-int session_set_trace_chunk(struct ltt_session *session,
-               struct lttng_trace_chunk *new_trace_chunk,
-               struct lttng_trace_chunk **current_session_trace_chunk);
-
-/*
- * Close a chunk on the remote peers of a session. Has no effect on the
- * ltt_session itself.
- */
-int session_close_trace_chunk(struct ltt_session *session,
-               struct lttng_trace_chunk *trace_chunk,
-               enum lttng_trace_chunk_command_type close_command,
-               char *path);
-
-/* Open a packet in all channels of a given session. */
-enum lttng_error_code session_open_packets(struct ltt_session *session);
-
-bool session_output_supports_trace_chunks(const struct ltt_session *session);
-
-/*
- * Sample the id of a session looked up via its name.
- * Here the term "sampling" hint the caller that this return the id at a given
- * point in time with no guarantee that the session for which the id was
- * sampled still exist at that point.
- *
- * Return 0 when the session is not found,
- * Return 1 when the session is found and set `id`.
- */
-bool sample_session_id_by_name(const char *name, uint64_t *id);
-
-#endif /* _LTT_SESSION_H */
diff --git a/src/bin/lttng-sessiond/session.hpp b/src/bin/lttng-sessiond/session.hpp
new file mode 100644 (file)
index 0000000..345a389
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_SESSION_H
+#define _LTT_SESSION_H
+
+#include <limits.h>
+#include <stdbool.h>
+#include <urcu/list.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <common/dynamic-array.hpp>
+#include <lttng/rotation.h>
+#include <lttng/location.h>
+#include <lttng/lttng-error.h>
+
+#include "snapshot.hpp"
+#include "trace-kernel.hpp"
+#include "consumer.hpp"
+
+struct ltt_ust_session;
+
+typedef void (*ltt_session_destroy_notifier)(const struct ltt_session *session,
+               void *user_data);
+typedef void (*ltt_session_clear_notifier)(const struct ltt_session *session,
+               void *user_data);
+
+/*
+ * Tracing session list
+ *
+ * Statically declared in session.c and can be accessed by using
+ * session_get_list() function that returns the pointer to the list.
+ */
+struct ltt_session_list {
+       /*
+        * This lock protects any read/write access to the list and
+        * next_uuid. All public functions in session.c acquire this
+        * lock and release it before returning. If none of those
+        * functions are used, the lock MUST be acquired in order to
+        * iterate or/and do any actions on that list.
+        */
+       pthread_mutex_t lock;
+       /*
+        * This condition variable is signaled on every removal from
+        * the session list.
+        */
+       pthread_cond_t removal_cond;
+
+       /*
+        * Session unique ID generator. The session list lock MUST be
+        * upon update and read of this counter.
+        */
+       uint64_t next_uuid;
+
+       /* Linked list head */
+       struct cds_list_head head;
+};
+
+/*
+ * This data structure contains information needed to identify a tracing
+ * session for both LTTng and UST.
+ */
+struct ltt_session {
+       char name[NAME_MAX];
+       bool has_auto_generated_name;
+       bool name_contains_creation_time;
+       char hostname[LTTNG_HOST_NAME_MAX]; /* Local hostname. */
+       /* Path of the last closed chunk. */
+       char last_chunk_path[LTTNG_PATH_MAX];
+       time_t creation_time;
+       struct ltt_kernel_session *kernel_session;
+       struct ltt_ust_session *ust_session;
+       struct urcu_ref ref;
+       /*
+        * Protect any read/write on this session data structure. This lock must be
+        * acquired *before* using any public functions declared below. Use
+        * session_lock() and session_unlock() for that.
+        */
+       pthread_mutex_t lock;
+       struct cds_list_head list;
+       uint64_t id;            /* session unique identifier */
+       /* Indicates if the session has been added to the session list and ht.*/
+       bool published;
+       /* Indicates if a destroy command has been applied to this session. */
+       bool destroyed;
+       /* UID/GID of the user owning the session */
+       uid_t uid;
+       gid_t gid;
+       /*
+        * Network session handle. A value of 0 means that there is no remote
+        * session established.
+        */
+       uint64_t net_handle;
+       /*
+        * This consumer is only set when the create_session_uri call is made.
+        * This contains the temporary information for a consumer output. Upon
+        * creation of the UST or kernel session, this consumer, if available, is
+        * copied into those sessions.
+        */
+       struct consumer_output *consumer;
+       /*
+        * Indicates whether or not the user has specified an output directory
+        * or if it was configured using the default configuration.
+        */
+       bool has_user_specified_directory;
+       /* Did at least ONE start command has been triggered?. */
+       unsigned int has_been_started:1;
+       /*
+        * Is the session active? Start trace command sets this to 1 and the stop
+        * command reset it to 0.
+        */
+       unsigned int active:1;
+
+       /* Snapshot representation in a session. */
+       struct snapshot snapshot;
+       /* Indicate if the session has to output the traces or not. */
+       unsigned int output_traces;
+       /*
+        * This session is in snapshot mode. This means that channels enabled
+        * will be set in overwrite mode by default and must be in mmap
+        * output mode. Note that snapshots can be taken on a session that
+        * is not in "snapshot_mode". This parameter only affects channel
+        * creation defaults.
+        */
+       unsigned int snapshot_mode;
+       /*
+        * A session that has channels that don't use 'mmap' output can't be
+        * used to capture snapshots. This is set to true whenever a
+        * 'splice' kernel channel is enabled.
+        */
+       bool has_non_mmap_channel;
+       /*
+        * Timer set when the session is created for live reading.
+        */
+       unsigned int live_timer;
+       /*
+        * Path where to keep the shared memory files.
+        */
+       char shm_path[PATH_MAX];
+       /*
+        * Node in ltt_sessions_ht_by_id.
+        */
+       struct lttng_ht_node_u64 node;
+       /*
+        * Node in ltt_sessions_ht_by_name.
+        */
+       struct lttng_ht_node_str node_by_name;
+       /*
+        * Timer to check periodically if a relay and/or consumer has completed
+        * the last rotation.
+        */
+       bool rotation_pending_check_timer_enabled;
+       timer_t rotation_pending_check_timer;
+       /* Timer to periodically rotate a session. */
+       bool rotation_schedule_timer_enabled;
+       timer_t rotation_schedule_timer;
+       /* Value for periodic rotations, 0 if disabled. */
+       uint64_t rotate_timer_period;
+       /* Value for size-based rotations, 0 if disabled. */
+       uint64_t rotate_size;
+       /*
+        * Keep a state if this session was rotated after the last stop command.
+        * We only allow one rotation after a stop. At destroy, we also need to
+        * know if a rotation occurred since the last stop to rename the current
+        * chunk. After a stop followed by rotate, all subsequent clear
+        * (without prior start) will succeed, but will be effect-less.
+        */
+       bool rotated_after_last_stop;
+       /*
+        * Track whether the session was cleared after last stop. All subsequent
+        * clear (without prior start) will succeed, but will be effect-less. A
+        * subsequent rotate (without prior start) will return an error.
+        */
+       bool cleared_after_last_stop;
+       /*
+        * True if the session has had an explicit non-quiet rotation.
+        */
+       bool rotated;
+       /*
+        * Condition and trigger for size-based rotations.
+        */
+       struct lttng_condition *rotate_condition;
+       struct lttng_trigger *rotate_trigger;
+       LTTNG_OPTIONAL(uint64_t) most_recent_chunk_id;
+       struct lttng_trace_chunk *current_trace_chunk;
+       struct lttng_trace_chunk *chunk_being_archived;
+       /* Current state of a rotation. */
+       enum lttng_rotation_state rotation_state;
+       bool quiet_rotation;
+       char *last_archived_chunk_name;
+       LTTNG_OPTIONAL(uint64_t) last_archived_chunk_id;
+       struct lttng_dynamic_array destroy_notifiers;
+       struct lttng_dynamic_array clear_notifiers;
+       /* Session base path override. Set non-null. */
+       char *base_path;
+};
+
+enum lttng_error_code session_create(const char *name, uid_t uid, gid_t gid,
+               struct ltt_session **out_session);
+void session_lock(struct ltt_session *session);
+void session_unlock(struct ltt_session *session);
+
+/*
+ * The session list lock covers more ground than its name implies. While
+ * it does protect against concurent mutations of the session list, it is
+ * also used as a multi-session lock when synchronizing newly-registered
+ * 'user space tracer' and 'agent' applications.
+ *
+ * In other words, it prevents tracer configurations from changing while they
+ * are being transmitted to the various applications.
+ */
+void session_lock_list(void);
+int session_trylock_list(void);
+void session_unlock_list(void);
+
+void session_destroy(struct ltt_session *session);
+int session_add_destroy_notifier(struct ltt_session *session,
+               ltt_session_destroy_notifier notifier, void *user_data);
+
+int session_add_clear_notifier(struct ltt_session *session,
+               ltt_session_clear_notifier notifier, void *user_data);
+void session_notify_clear(struct ltt_session *session);
+
+bool session_get(struct ltt_session *session);
+void session_put(struct ltt_session *session);
+
+enum consumer_dst_type session_get_consumer_destination_type(
+               const struct ltt_session *session);
+const char *session_get_net_consumer_hostname(
+               const struct ltt_session *session);
+void session_get_net_consumer_ports(
+               const struct ltt_session *session,
+               uint16_t *control_port, uint16_t *data_port);
+struct lttng_trace_archive_location *session_get_trace_archive_location(
+               const struct ltt_session *session);
+
+struct ltt_session *session_find_by_name(const char *name);
+struct ltt_session *session_find_by_id(uint64_t id);
+
+struct ltt_session_list *session_get_list(void);
+void session_list_wait_empty(void);
+
+bool session_access_ok(struct ltt_session *session, uid_t uid);
+
+int session_reset_rotation_state(struct ltt_session *session,
+               enum lttng_rotation_state result);
+
+/* Create a new trace chunk object from the session's configuration. */
+struct lttng_trace_chunk *session_create_new_trace_chunk(
+               const struct ltt_session *session,
+               const struct consumer_output *consumer_output_override,
+               const char *session_base_path_override,
+               const char *chunk_name_override);
+
+/*
+ * Set `new_trace_chunk` as the session's current trace chunk. A reference
+ * to `new_trace_chunk` is acquired by the session. The chunk is created
+ * on remote peers (consumer and relay daemons).
+ *
+ * A reference to the session's current trace chunk is returned through
+ * `current_session_trace_chunk` on success.
+ */
+int session_set_trace_chunk(struct ltt_session *session,
+               struct lttng_trace_chunk *new_trace_chunk,
+               struct lttng_trace_chunk **current_session_trace_chunk);
+
+/*
+ * Close a chunk on the remote peers of a session. Has no effect on the
+ * ltt_session itself.
+ */
+int session_close_trace_chunk(struct ltt_session *session,
+               struct lttng_trace_chunk *trace_chunk,
+               enum lttng_trace_chunk_command_type close_command,
+               char *path);
+
+/* Open a packet in all channels of a given session. */
+enum lttng_error_code session_open_packets(struct ltt_session *session);
+
+bool session_output_supports_trace_chunks(const struct ltt_session *session);
+
+/*
+ * Sample the id of a session looked up via its name.
+ * Here the term "sampling" hint the caller that this return the id at a given
+ * point in time with no guarantee that the session for which the id was
+ * sampled still exist at that point.
+ *
+ * Return 0 when the session is not found,
+ * Return 1 when the session is found and set `id`.
+ */
+bool sample_session_id_by_name(const char *name, uint64_t *id);
+
+#endif /* _LTT_SESSION_H */
index 05b77e69c44bece4d6f85ac06d6de8c28ee10fd1..bf0a9924002ee955b8572274abd4540187f60b84 100644 (file)
@@ -5,16 +5,16 @@
  *
  */
 
-#include "version.h"
-#include "sessiond-config.h"
-#include "lttng-ust-ctl.h"
-#include <common/defaults.h>
+#include "version.hpp"
+#include "sessiond-config.hpp"
+#include "lttng-ust-ctl.hpp"
+#include <common/defaults.hpp>
 #include <limits.h>
 #include <ctype.h>
-#include <common/error.h>
-#include <common/utils.h>
-#include <common/compat/errno.h>
-#include <common/compat/getenv.h>
+#include <common/error.hpp>
+#include <common/utils.hpp>
+#include <common/compat/errno.hpp>
+#include <common/compat/getenv.hpp>
 
 static
 struct sessiond_config sessiond_config_build_defaults = {
diff --git a/src/bin/lttng-sessiond/sessiond-config.h b/src/bin/lttng-sessiond/sessiond-config.h
deleted file mode 100644 (file)
index 136ca95..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_SESSIOND_CONFIG_H
-#define LTTNG_SESSIOND_CONFIG_H
-
-#include <common/macros.h>
-#include <stdbool.h>
-
-struct config_string {
-       char *value;
-       bool should_free;
-};
-
-struct config_int_range {
-       int begin, end;
-};
-
-/* Config string takes ownership of value. */
-void config_string_set(struct config_string *string, char *value);
-
-struct sessiond_config {
-       int verbose;
-       int verbose_consumer;
-       /* Agent TCP port range for registration. Used by the agent thread. */
-       struct config_int_range agent_tcp_port;
-
-       int event_notifier_buffer_size_kernel;
-       int event_notifier_buffer_size_userspace;
-       /* Socket timeout for receiving and sending (in seconds). */
-       int app_socket_timeout;
-
-       bool quiet;
-       bool no_kernel;
-       bool background;
-       bool daemonize;
-       bool sig_parent;
-
-       struct config_string tracing_group_name;
-
-       struct config_string kmod_probes_list;
-       struct config_string kmod_extra_probes_list;
-
-       struct config_string rundir;
-
-       /* Global application Unix socket path */
-       struct config_string apps_unix_sock_path;
-       /* Global client Unix socket path */
-       struct config_string client_unix_sock_path;
-       /* Global wait shm path for UST */
-       struct config_string wait_shm_path;
-       /* Global health check unix path */
-       struct config_string health_unix_sock_path;
-       /*
-        * LTTNG_UST_CLOCK_PLUGIN environment variable to be passed to spawned
-        * consumer daemons.
-        */
-       struct config_string lttng_ust_clock_plugin;
-       struct config_string pid_file_path;
-       struct config_string lock_file_path;
-       struct config_string load_session_path;
-       struct config_string agent_port_file_path;
-
-       struct config_string consumerd32_path;
-       struct config_string consumerd32_bin_path;
-       struct config_string consumerd32_lib_dir;
-       struct config_string consumerd32_err_unix_sock_path;
-       struct config_string consumerd32_cmd_unix_sock_path;
-
-       struct config_string consumerd64_path;
-       struct config_string consumerd64_bin_path;
-       struct config_string consumerd64_lib_dir;
-       struct config_string consumerd64_err_unix_sock_path;
-       struct config_string consumerd64_cmd_unix_sock_path;
-
-       struct config_string kconsumerd_path;
-       struct config_string kconsumerd_err_unix_sock_path;
-       struct config_string kconsumerd_cmd_unix_sock_path;
-};
-
-/* Initialize the sessiond_config values to build-defaults. */
-int sessiond_config_init(struct sessiond_config *config);
-
-/* Override sessiond_config values with values specified by the environment. */
-int sessiond_config_apply_env_config(struct sessiond_config *config);
-
-void sessiond_config_fini(struct sessiond_config *config);
-
-int sessiond_config_resolve_paths(struct sessiond_config *config);
-
-void sessiond_config_log(struct sessiond_config *config);
-
-#endif /* LTTNG_SESSIOND_CONFIG_H */
diff --git a/src/bin/lttng-sessiond/sessiond-config.hpp b/src/bin/lttng-sessiond/sessiond-config.hpp
new file mode 100644 (file)
index 0000000..fa0bfeb
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_SESSIOND_CONFIG_H
+#define LTTNG_SESSIOND_CONFIG_H
+
+#include <common/macros.hpp>
+#include <stdbool.h>
+
+struct config_string {
+       char *value;
+       bool should_free;
+};
+
+struct config_int_range {
+       int begin, end;
+};
+
+/* Config string takes ownership of value. */
+void config_string_set(struct config_string *string, char *value);
+
+struct sessiond_config {
+       int verbose;
+       int verbose_consumer;
+       /* Agent TCP port range for registration. Used by the agent thread. */
+       struct config_int_range agent_tcp_port;
+
+       int event_notifier_buffer_size_kernel;
+       int event_notifier_buffer_size_userspace;
+       /* Socket timeout for receiving and sending (in seconds). */
+       int app_socket_timeout;
+
+       bool quiet;
+       bool no_kernel;
+       bool background;
+       bool daemonize;
+       bool sig_parent;
+
+       struct config_string tracing_group_name;
+
+       struct config_string kmod_probes_list;
+       struct config_string kmod_extra_probes_list;
+
+       struct config_string rundir;
+
+       /* Global application Unix socket path */
+       struct config_string apps_unix_sock_path;
+       /* Global client Unix socket path */
+       struct config_string client_unix_sock_path;
+       /* Global wait shm path for UST */
+       struct config_string wait_shm_path;
+       /* Global health check unix path */
+       struct config_string health_unix_sock_path;
+       /*
+        * LTTNG_UST_CLOCK_PLUGIN environment variable to be passed to spawned
+        * consumer daemons.
+        */
+       struct config_string lttng_ust_clock_plugin;
+       struct config_string pid_file_path;
+       struct config_string lock_file_path;
+       struct config_string load_session_path;
+       struct config_string agent_port_file_path;
+
+       struct config_string consumerd32_path;
+       struct config_string consumerd32_bin_path;
+       struct config_string consumerd32_lib_dir;
+       struct config_string consumerd32_err_unix_sock_path;
+       struct config_string consumerd32_cmd_unix_sock_path;
+
+       struct config_string consumerd64_path;
+       struct config_string consumerd64_bin_path;
+       struct config_string consumerd64_lib_dir;
+       struct config_string consumerd64_err_unix_sock_path;
+       struct config_string consumerd64_cmd_unix_sock_path;
+
+       struct config_string kconsumerd_path;
+       struct config_string kconsumerd_err_unix_sock_path;
+       struct config_string kconsumerd_cmd_unix_sock_path;
+};
+
+/* Initialize the sessiond_config values to build-defaults. */
+int sessiond_config_init(struct sessiond_config *config);
+
+/* Override sessiond_config values with values specified by the environment. */
+int sessiond_config_apply_env_config(struct sessiond_config *config);
+
+void sessiond_config_fini(struct sessiond_config *config);
+
+int sessiond_config_resolve_paths(struct sessiond_config *config);
+
+void sessiond_config_log(struct sessiond_config *config);
+
+#endif /* LTTNG_SESSIOND_CONFIG_H */
index 03472201acfd3c68a4cdad1937b6b69095248801..4fc36a58d05bc98e60855b0d6dd2dc3aedfb2d11 100644 (file)
 #include <string.h>
 #include <urcu/uatomic.h>
 
-#include <common/defaults.h>
+#include <common/defaults.hpp>
 
-#include "snapshot.h"
-#include "utils.h"
+#include "snapshot.hpp"
+#include "utils.hpp"
 
 /*
  * Return the atomically incremented value of next_output_id.
diff --git a/src/bin/lttng-sessiond/snapshot.h b/src/bin/lttng-sessiond/snapshot.h
deleted file mode 100644 (file)
index 027b098..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SNAPSHOT_H
-#define SNAPSHOT_H
-
-#include <limits.h>
-#include <stdint.h>
-
-#include <common/common.h>
-#include <common/hashtable/hashtable.h>
-#include <common/uri.h>
-
-#include "consumer.h"
-
-struct consumer_output;
-struct ltt_session;
-
-struct snapshot_output {
-       uint32_t id;
-       uint64_t max_size;
-       /* Number of snapshot taken with that output. */
-       uint64_t nb_snapshot;
-       char name[NAME_MAX];
-       struct consumer_output *consumer;
-       int kernel_sockets_copied;
-       int ust_sockets_copied;
-       /*
-        * Contains the string with "<date>-<time>" for when the snapshot command
-        * is triggered. This is to make sure every streams will use the same time
-        * for the directory output.
-        */
-       char datetime[16];
-
-       /* Indexed by ID. */
-       struct lttng_ht_node_ulong node;
-};
-
-struct snapshot {
-       unsigned long next_output_id;
-       size_t nb_output;
-       /*
-        * Number of snapshot taken for that object. This value is used with a
-        * temporary output of a snapshot record.
-        */
-       uint64_t nb_snapshot;
-       struct lttng_ht *output_ht;
-};
-
-/* Snapshot object. */
-struct snapshot *snapshot_alloc(void);
-void snapshot_destroy(struct snapshot *obj);
-int snapshot_init(struct snapshot *obj);
-void snapshot_delete_output(struct snapshot *snapshot,
-               struct snapshot_output *output);
-void snapshot_add_output(struct snapshot *snapshot,
-               struct snapshot_output *output);
-
-/* Snapshot output object. */
-struct snapshot_output *snapshot_output_alloc(void);
-void snapshot_output_destroy(struct snapshot_output *obj);
-int snapshot_output_init(const struct ltt_session *session,
-               uint64_t max_size, const char *name,
-               const char *ctrl_url, const char *data_url,
-               struct consumer_output *consumer, struct snapshot_output *output,
-               struct snapshot *snapshot);
-int snapshot_output_init_with_uri(const struct ltt_session *session,
-               uint64_t max_size, const char *name,
-               struct lttng_uri *uris, size_t nb_uri,
-               struct consumer_output *consumer, struct snapshot_output *output,
-               struct snapshot *snapshot);
-struct snapshot_output *snapshot_find_output_by_id(uint32_t id,
-               struct snapshot *snapshot);
-struct snapshot_output *snapshot_find_output_by_name(const char *name,
-               struct snapshot *snapshot);
-
-#endif /* SNAPSHOT_H */
diff --git a/src/bin/lttng-sessiond/snapshot.hpp b/src/bin/lttng-sessiond/snapshot.hpp
new file mode 100644 (file)
index 0000000..6aa06dd
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SNAPSHOT_H
+#define SNAPSHOT_H
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <common/common.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/uri.hpp>
+
+#include "consumer.hpp"
+
+struct consumer_output;
+struct ltt_session;
+
+struct snapshot_output {
+       uint32_t id;
+       uint64_t max_size;
+       /* Number of snapshot taken with that output. */
+       uint64_t nb_snapshot;
+       char name[NAME_MAX];
+       struct consumer_output *consumer;
+       int kernel_sockets_copied;
+       int ust_sockets_copied;
+       /*
+        * Contains the string with "<date>-<time>" for when the snapshot command
+        * is triggered. This is to make sure every streams will use the same time
+        * for the directory output.
+        */
+       char datetime[16];
+
+       /* Indexed by ID. */
+       struct lttng_ht_node_ulong node;
+};
+
+struct snapshot {
+       unsigned long next_output_id;
+       size_t nb_output;
+       /*
+        * Number of snapshot taken for that object. This value is used with a
+        * temporary output of a snapshot record.
+        */
+       uint64_t nb_snapshot;
+       struct lttng_ht *output_ht;
+};
+
+/* Snapshot object. */
+struct snapshot *snapshot_alloc(void);
+void snapshot_destroy(struct snapshot *obj);
+int snapshot_init(struct snapshot *obj);
+void snapshot_delete_output(struct snapshot *snapshot,
+               struct snapshot_output *output);
+void snapshot_add_output(struct snapshot *snapshot,
+               struct snapshot_output *output);
+
+/* Snapshot output object. */
+struct snapshot_output *snapshot_output_alloc(void);
+void snapshot_output_destroy(struct snapshot_output *obj);
+int snapshot_output_init(const struct ltt_session *session,
+               uint64_t max_size, const char *name,
+               const char *ctrl_url, const char *data_url,
+               struct consumer_output *consumer, struct snapshot_output *output,
+               struct snapshot *snapshot);
+int snapshot_output_init_with_uri(const struct ltt_session *session,
+               uint64_t max_size, const char *name,
+               struct lttng_uri *uris, size_t nb_uri,
+               struct consumer_output *consumer, struct snapshot_output *output,
+               struct snapshot *snapshot);
+struct snapshot_output *snapshot_find_output_by_id(uint32_t id,
+               struct snapshot *snapshot);
+struct snapshot_output *snapshot_find_output_by_name(const char *name,
+               struct snapshot *snapshot);
+
+#endif /* SNAPSHOT_H */
diff --git a/src/bin/lttng-sessiond/testpoint.h b/src/bin/lttng-sessiond/testpoint.h
deleted file mode 100644 (file)
index 2ddd662..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2012 Christian Babeux <christian.babeux@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SESSIOND_TESTPOINT_H
-#define SESSIOND_TESTPOINT_H
-
-#include <common/testpoint/testpoint.h>
-
-/* Testpoints, internal use only */
-TESTPOINT_DECL(sessiond_thread_manage_clients);
-TESTPOINT_DECL(sessiond_thread_manage_clients_before_loop);
-TESTPOINT_DECL(sessiond_thread_registration_apps);
-TESTPOINT_DECL(sessiond_thread_manage_apps);
-TESTPOINT_DECL(sessiond_thread_manage_apps_before_loop);
-TESTPOINT_DECL(sessiond_thread_manage_kernel);
-TESTPOINT_DECL(sessiond_thread_manage_kernel_before_loop);
-TESTPOINT_DECL(sessiond_thread_manage_consumer);
-TESTPOINT_DECL(sessiond_thread_ht_cleanup);
-TESTPOINT_DECL(sessiond_thread_app_manage_notify);
-TESTPOINT_DECL(sessiond_thread_app_reg_dispatch);
-TESTPOINT_DECL(sessiond_thread_notification);
-TESTPOINT_DECL(sessiond_handle_notifier_event_pipe);
-
-#endif /* SESSIOND_TESTPOINT_H */
diff --git a/src/bin/lttng-sessiond/testpoint.hpp b/src/bin/lttng-sessiond/testpoint.hpp
new file mode 100644 (file)
index 0000000..b1ef8be
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Christian Babeux <christian.babeux@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SESSIOND_TESTPOINT_H
+#define SESSIOND_TESTPOINT_H
+
+#include <common/testpoint/testpoint.hpp>
+
+/* Testpoints, internal use only */
+TESTPOINT_DECL(sessiond_thread_manage_clients);
+TESTPOINT_DECL(sessiond_thread_manage_clients_before_loop);
+TESTPOINT_DECL(sessiond_thread_registration_apps);
+TESTPOINT_DECL(sessiond_thread_manage_apps);
+TESTPOINT_DECL(sessiond_thread_manage_apps_before_loop);
+TESTPOINT_DECL(sessiond_thread_manage_kernel);
+TESTPOINT_DECL(sessiond_thread_manage_kernel_before_loop);
+TESTPOINT_DECL(sessiond_thread_manage_consumer);
+TESTPOINT_DECL(sessiond_thread_ht_cleanup);
+TESTPOINT_DECL(sessiond_thread_app_manage_notify);
+TESTPOINT_DECL(sessiond_thread_app_reg_dispatch);
+TESTPOINT_DECL(sessiond_thread_notification);
+TESTPOINT_DECL(sessiond_handle_notifier_event_pipe);
+
+#endif /* SESSIOND_TESTPOINT_H */
index 1eb25eabe6e09cf753413ad17c9a79e1e2fa9d3b..50c19c78282e454c4f7ac3eae242df1ce6766e94 100644 (file)
@@ -7,9 +7,9 @@
  *
  */
 
-#include "lttng-sessiond.h"
-#include "utils.h"
-#include <common/utils.h>
+#include "lttng-sessiond.hpp"
+#include "utils.hpp"
+#include <common/utils.hpp>
 #include <pthread.h>
 
 /*
index 446a8c9d2e52276dd5972cf869884c57ec22bb78..9ce539b816a99732cf0a6c3ed5c3901584e8e44a 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include "thread.h"
+#include "thread.hpp"
 #include <urcu/list.h>
 #include <urcu/ref.h>
 #include <pthread.h>
-#include <common/macros.h>
-#include <common/error.h>
-#include <common/defaults.h>
+#include <common/macros.hpp>
+#include <common/error.hpp>
+#include <common/defaults.hpp>
 
 static struct thread_list {
        struct cds_list_head head;
diff --git a/src/bin/lttng-sessiond/thread.h b/src/bin/lttng-sessiond/thread.h
deleted file mode 100644 (file)
index 530f72a..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <stdbool.h>
-
-#ifndef THREAD_H
-#define THREAD_H
-
-struct lttng_thread;
-
-/* Main function of the new thread. */
-typedef void *(*lttng_thread_entry_point)(void *);
-
-/* Callback invoked to initiate the shutdown a thread. */
-typedef bool (*lttng_thread_shutdown_cb)(void *);
-
-/*
- * Callback invoked to clean-up the thread data.
- * Invoked when the thread is destroyed to ensure there is no
- * race between a use by the "thread shutdown callback" and
- * a use by the thread itself.
- */
-typedef void (*lttng_thread_cleanup_cb)(void *);
-
-/*
- * Returns a reference to the newly-created thread.
- * The shutdown and cleanup callbacks are optional.
- */
-struct lttng_thread *lttng_thread_create(const char *name,
-               lttng_thread_entry_point entry,
-               lttng_thread_shutdown_cb shutdown,
-               lttng_thread_cleanup_cb cleanup,
-               void *thread_data);
-
-bool lttng_thread_get(struct lttng_thread *thread);
-void lttng_thread_put(struct lttng_thread *thread);
-
-const char *lttng_thread_get_name(const struct lttng_thread *thread);
-
-/*
- * Explicitly shutdown a thread. This function returns once the
- * thread has returned and been joined.
- *
- * It is invalid to call this function more than once on a thread.
- *
- * Returns true on success, false on error.
- */
-bool lttng_thread_shutdown(struct lttng_thread *thread);
-
-/*
- * Shutdown all orphaned threads (threads to which no external reference
- * exist).
- *
- * Returns once all orphaned threads have been joined.
- */
-void lttng_thread_list_shutdown_orphans(void);
-
-#endif /* THREAD_H */
diff --git a/src/bin/lttng-sessiond/thread.hpp b/src/bin/lttng-sessiond/thread.hpp
new file mode 100644 (file)
index 0000000..530f72a
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <stdbool.h>
+
+#ifndef THREAD_H
+#define THREAD_H
+
+struct lttng_thread;
+
+/* Main function of the new thread. */
+typedef void *(*lttng_thread_entry_point)(void *);
+
+/* Callback invoked to initiate the shutdown a thread. */
+typedef bool (*lttng_thread_shutdown_cb)(void *);
+
+/*
+ * Callback invoked to clean-up the thread data.
+ * Invoked when the thread is destroyed to ensure there is no
+ * race between a use by the "thread shutdown callback" and
+ * a use by the thread itself.
+ */
+typedef void (*lttng_thread_cleanup_cb)(void *);
+
+/*
+ * Returns a reference to the newly-created thread.
+ * The shutdown and cleanup callbacks are optional.
+ */
+struct lttng_thread *lttng_thread_create(const char *name,
+               lttng_thread_entry_point entry,
+               lttng_thread_shutdown_cb shutdown,
+               lttng_thread_cleanup_cb cleanup,
+               void *thread_data);
+
+bool lttng_thread_get(struct lttng_thread *thread);
+void lttng_thread_put(struct lttng_thread *thread);
+
+const char *lttng_thread_get_name(const struct lttng_thread *thread);
+
+/*
+ * Explicitly shutdown a thread. This function returns once the
+ * thread has returned and been joined.
+ *
+ * It is invalid to call this function more than once on a thread.
+ *
+ * Returns true on success, false on error.
+ */
+bool lttng_thread_shutdown(struct lttng_thread *thread);
+
+/*
+ * Shutdown all orphaned threads (threads to which no external reference
+ * exist).
+ *
+ * Returns once all orphaned threads have been joined.
+ */
+void lttng_thread_list_shutdown_orphans(void);
+
+#endif /* THREAD_H */
index 5a1f35dfa936904f236e7dac108cdf044789f067..f2121c0d65f0a540f4f0f181bb6dd42bb15e656f 100644 (file)
 #include <inttypes.h>
 #include <signal.h>
 
-#include "timer.h"
-#include "health-sessiond.h"
-#include "rotation-thread.h"
-#include "thread.h"
+#include "timer.hpp"
+#include "health-sessiond.hpp"
+#include "rotation-thread.hpp"
+#include "thread.hpp"
 
 #define LTTNG_SESSIOND_SIG_QS                          SIGRTMIN + 10
 #define LTTNG_SESSIOND_SIG_EXIT                                SIGRTMIN + 11
diff --git a/src/bin/lttng-sessiond/timer.h b/src/bin/lttng-sessiond/timer.h
deleted file mode 100644 (file)
index c958794..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SESSIOND_TIMER_H
-#define SESSIOND_TIMER_H
-
-#include <pthread.h>
-#include <stdbool.h>
-
-#include "session.h"
-
-struct timer_thread_parameters {
-       struct rotation_thread_timer_queue *rotation_thread_job_queue;
-};
-
-int timer_signal_init(void);
-
-/* Start a session's rotation pending check timer (one-shot mode). */
-int timer_session_rotation_pending_check_start(struct ltt_session *session,
-               unsigned int interval_us);
-/* Stop a session's rotation pending check timer. */
-int timer_session_rotation_pending_check_stop(struct ltt_session *session);
-
-/* Start a session's rotation schedule timer. */
-int timer_session_rotation_schedule_timer_start(struct ltt_session *session,
-               unsigned int interval_us);
-/* Stop a session's rotation schedule timer. */
-int timer_session_rotation_schedule_timer_stop(struct ltt_session *session);
-
-bool launch_timer_thread(
-               struct timer_thread_parameters *timer_thread_parameters);
-
-#endif /* SESSIOND_TIMER_H */
diff --git a/src/bin/lttng-sessiond/timer.hpp b/src/bin/lttng-sessiond/timer.hpp
new file mode 100644 (file)
index 0000000..f746f0e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SESSIOND_TIMER_H
+#define SESSIOND_TIMER_H
+
+#include <pthread.h>
+#include <stdbool.h>
+
+#include "session.hpp"
+
+struct timer_thread_parameters {
+       struct rotation_thread_timer_queue *rotation_thread_job_queue;
+};
+
+int timer_signal_init(void);
+
+/* Start a session's rotation pending check timer (one-shot mode). */
+int timer_session_rotation_pending_check_start(struct ltt_session *session,
+               unsigned int interval_us);
+/* Stop a session's rotation pending check timer. */
+int timer_session_rotation_pending_check_stop(struct ltt_session *session);
+
+/* Start a session's rotation schedule timer. */
+int timer_session_rotation_schedule_timer_start(struct ltt_session *session,
+               unsigned int interval_us);
+/* Stop a session's rotation schedule timer. */
+int timer_session_rotation_schedule_timer_stop(struct ltt_session *session);
+
+bool launch_timer_thread(
+               struct timer_thread_parameters *timer_thread_parameters);
+
+#endif /* SESSIOND_TIMER_H */
index cf1455ee6a64e368a24bb4cff6a15b821f6c52e2..e266f8b3cb0eccc71940cee8389cb7ece1f60014 100644 (file)
 #include <lttng/lttng-error.h>
 #include <lttng/kernel-probe.h>
 #include <lttng/userspace-probe.h>
-#include <lttng/userspace-probe-internal.h>
+#include <lttng/userspace-probe-internal.hpp>
 #include <lttng/event-rule/event-rule.h>
-#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/event-rule-internal.hpp>
 #include <lttng/event-rule/kernel-kprobe.h>
-#include <lttng/event-rule/kernel-kprobe-internal.h>
+#include <lttng/event-rule/kernel-kprobe-internal.hpp>
 #include <lttng/event-rule/kernel-syscall.h>
-#include <lttng/event-rule/kernel-syscall-internal.h>
+#include <lttng/event-rule/kernel-syscall-internal.hpp>
 #include <lttng/event-rule/kernel-tracepoint.h>
-#include <lttng/event-rule/kernel-tracepoint-internal.h>
+#include <lttng/event-rule/kernel-tracepoint-internal.hpp>
 #include <lttng/event-rule/kernel-uprobe.h>
-#include <lttng/event-rule/kernel-uprobe-internal.h>
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/trace-chunk.h>
-#include <common/macros.h>
-
-#include "consumer.h"
-#include "trace-kernel.h"
-#include "lttng-sessiond.h"
-#include "notification-thread-commands.h"
+#include <lttng/event-rule/kernel-uprobe-internal.hpp>
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/macros.hpp>
+
+#include "consumer.hpp"
+#include "trace-kernel.hpp"
+#include "lttng-sessiond.hpp"
+#include "notification-thread-commands.hpp"
 
 /*
  * Find the channel name for the given kernel session.
diff --git a/src/bin/lttng-sessiond/trace-kernel.h b/src/bin/lttng-sessiond/trace-kernel.h
deleted file mode 100644 (file)
index f6ad56c..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_TRACE_KERNEL_H
-#define _LTT_TRACE_KERNEL_H
-
-#include <urcu/list.h>
-
-#include <lttng/lttng.h>
-#include <common/lttng-kernel.h>
-#include <common/lttng-kernel-old.h>
-#include <common/defaults.h>
-
-#include "consumer.h"
-#include "tracker.h"
-
-/* Kernel event list */
-struct ltt_kernel_event_list {
-       struct cds_list_head head;
-};
-
-/* Channel stream list */
-struct ltt_kernel_stream_list {
-       struct cds_list_head head;
-};
-
-/* Channel list */
-struct ltt_kernel_channel_list {
-       struct cds_list_head head;
-};
-
-struct ltt_kernel_context {
-       struct lttng_kernel_abi_context ctx;
-       struct cds_list_head list;
-       /* Indicates whether or not the context is in a list. */
-       bool in_list;
-};
-
-/* Kernel event */
-struct ltt_kernel_event {
-       int fd;
-       int enabled;
-       enum lttng_event_type type;
-       struct lttng_kernel_abi_event *event;
-       struct cds_list_head list;
-       char *filter_expression;
-       struct lttng_bytecode *filter;
-       struct lttng_userspace_probe_location *userspace_probe_location;
-};
-
-/* Kernel event */
-struct ltt_kernel_event_notifier_rule {
-       int fd;
-       uint64_t error_counter_index;
-       int enabled;
-       enum lttng_event_type type;
-       struct lttng_trigger *trigger;
-       uint64_t token;
-       const struct lttng_bytecode *filter;
-       struct lttng_userspace_probe_location *userspace_probe_location;
-       struct cds_lfht_node ht_node;
-       /* call_rcu delayed reclaim. */
-       struct rcu_head rcu_node;
-};
-
-/* Kernel channel */
-struct ltt_kernel_channel {
-       int fd;
-       uint64_t key; /* Key to reference this channel with the consumer. */
-       int enabled;
-       unsigned int stream_count;
-       unsigned int event_count;
-       bool published_to_notification_thread;
-       struct cds_list_head ctx_list;
-       struct lttng_channel *channel;
-       struct ltt_kernel_event_list events_list;
-       struct ltt_kernel_stream_list stream_list;
-       struct cds_list_head list;
-       /* Session pointer which has a reference to this object. */
-       struct ltt_kernel_session *session;
-       bool sent_to_consumer;
-};
-
-/* Metadata */
-struct ltt_kernel_metadata {
-       int fd;
-       uint64_t key; /* Key to reference this channel with the consumer. */
-       struct lttng_channel *conf;
-};
-
-/* Channel stream */
-struct ltt_kernel_stream {
-       int fd;
-       int state;
-       int cpu;
-       bool sent_to_consumer;
-       /* Format is %s_%d respectively channel name and CPU number. */
-       char name[DEFAULT_STREAM_NAME_LEN];
-       uint64_t tracefile_size;
-       uint64_t tracefile_count;
-       struct cds_list_head list;
-};
-
-/* Kernel session */
-struct ltt_kernel_session {
-       int fd;
-       int metadata_stream_fd;
-       int consumer_fds_sent;
-       unsigned int channel_count;
-       unsigned int stream_count_global;
-       struct ltt_kernel_metadata *metadata;
-       struct ltt_kernel_channel_list channel_list;
-       /* UID/GID of the user owning the session */
-       uid_t uid;
-       gid_t gid;
-       struct consumer_output *consumer;
-       /* Tracing session id */
-       uint64_t id;
-       /* Session is active or not meaning it has been started or stopped. */
-       unsigned int active:1;
-       /* Tell or not if the session has to output the traces. */
-       unsigned int output_traces;
-       unsigned int snapshot_mode;
-       unsigned int has_non_default_channel;
-       bool is_live_session;
-       /* Current trace chunk of the ltt_session. */
-       struct lttng_trace_chunk *current_trace_chunk;
-       /* Tracker lists */
-       struct process_attr_tracker *tracker_pid;
-       struct process_attr_tracker *tracker_vpid;
-       struct process_attr_tracker *tracker_uid;
-       struct process_attr_tracker *tracker_vuid;
-       struct process_attr_tracker *tracker_gid;
-       struct process_attr_tracker *tracker_vgid;
-};
-
-/*
- * Lookup functions. NULL is returned if not found.
- */
-struct ltt_kernel_event *trace_kernel_get_event_by_name(
-               char *name, struct ltt_kernel_channel *channel,
-               enum lttng_event_type type);
-struct ltt_kernel_event *trace_kernel_find_event(
-               char *name, struct ltt_kernel_channel *channel,
-               enum lttng_event_type type,
-               struct lttng_bytecode *filter);
-struct ltt_kernel_channel *trace_kernel_get_channel_by_name(
-               const char *name, struct ltt_kernel_session *session);
-
-/*
- * Create functions malloc() the data structure.
- */
-struct ltt_kernel_session *trace_kernel_create_session(void);
-struct ltt_kernel_channel *trace_kernel_create_channel(
-               struct lttng_channel *chan);
-enum lttng_error_code trace_kernel_create_event(struct lttng_event *ev,
-               char *filter_expression, struct lttng_bytecode *filter,
-               struct ltt_kernel_event **kernel_event);
-struct ltt_kernel_metadata *trace_kernel_create_metadata(void);
-struct ltt_kernel_stream *trace_kernel_create_stream(const char *name,
-               unsigned int count);
-struct ltt_kernel_context *trace_kernel_create_context(
-               struct lttng_kernel_abi_context *ctx);
-/* Trigger is only non-const to acquire a reference. */
-enum lttng_error_code trace_kernel_create_event_notifier_rule(
-               struct lttng_trigger *trigger,
-               uint64_t token,
-               uint64_t error_counter_index,
-               struct ltt_kernel_event_notifier_rule **event_notifier_rule);
-struct ltt_kernel_context *trace_kernel_copy_context(
-               struct ltt_kernel_context *ctx);
-enum lttng_error_code trace_kernel_init_event_notifier_from_event_rule(
-               const struct lttng_event_rule *rule,
-               struct lttng_kernel_abi_event_notifier *kernel_event_notifier);
-
-/*
- * Destroy functions free() the data structure and remove from linked list if
- * it's applies.
- */
-void trace_kernel_destroy_session(struct ltt_kernel_session *session);
-void trace_kernel_destroy_metadata(struct ltt_kernel_metadata *metadata);
-void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel);
-void trace_kernel_destroy_event(struct ltt_kernel_event *event);
-void trace_kernel_destroy_stream(struct ltt_kernel_stream *stream);
-void trace_kernel_destroy_context(struct ltt_kernel_context *ctx);
-void trace_kernel_destroy_event_notifier_rule(struct ltt_kernel_event_notifier_rule *rule);
-void trace_kernel_free_session(struct ltt_kernel_session *session);
-
-#endif /* _LTT_TRACE_KERNEL_H */
diff --git a/src/bin/lttng-sessiond/trace-kernel.hpp b/src/bin/lttng-sessiond/trace-kernel.hpp
new file mode 100644 (file)
index 0000000..84a1dcb
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_TRACE_KERNEL_H
+#define _LTT_TRACE_KERNEL_H
+
+#include <urcu/list.h>
+
+#include <lttng/lttng.h>
+#include <common/lttng-kernel.hpp>
+#include <common/lttng-kernel-old.hpp>
+#include <common/defaults.hpp>
+
+#include "consumer.hpp"
+#include "tracker.hpp"
+
+/* Kernel event list */
+struct ltt_kernel_event_list {
+       struct cds_list_head head;
+};
+
+/* Channel stream list */
+struct ltt_kernel_stream_list {
+       struct cds_list_head head;
+};
+
+/* Channel list */
+struct ltt_kernel_channel_list {
+       struct cds_list_head head;
+};
+
+struct ltt_kernel_context {
+       struct lttng_kernel_abi_context ctx;
+       struct cds_list_head list;
+       /* Indicates whether or not the context is in a list. */
+       bool in_list;
+};
+
+/* Kernel event */
+struct ltt_kernel_event {
+       int fd;
+       int enabled;
+       enum lttng_event_type type;
+       struct lttng_kernel_abi_event *event;
+       struct cds_list_head list;
+       char *filter_expression;
+       struct lttng_bytecode *filter;
+       struct lttng_userspace_probe_location *userspace_probe_location;
+};
+
+/* Kernel event */
+struct ltt_kernel_event_notifier_rule {
+       int fd;
+       uint64_t error_counter_index;
+       int enabled;
+       enum lttng_event_type type;
+       struct lttng_trigger *trigger;
+       uint64_t token;
+       const struct lttng_bytecode *filter;
+       struct lttng_userspace_probe_location *userspace_probe_location;
+       struct cds_lfht_node ht_node;
+       /* call_rcu delayed reclaim. */
+       struct rcu_head rcu_node;
+};
+
+/* Kernel channel */
+struct ltt_kernel_channel {
+       int fd;
+       uint64_t key; /* Key to reference this channel with the consumer. */
+       int enabled;
+       unsigned int stream_count;
+       unsigned int event_count;
+       bool published_to_notification_thread;
+       struct cds_list_head ctx_list;
+       struct lttng_channel *channel;
+       struct ltt_kernel_event_list events_list;
+       struct ltt_kernel_stream_list stream_list;
+       struct cds_list_head list;
+       /* Session pointer which has a reference to this object. */
+       struct ltt_kernel_session *session;
+       bool sent_to_consumer;
+};
+
+/* Metadata */
+struct ltt_kernel_metadata {
+       int fd;
+       uint64_t key; /* Key to reference this channel with the consumer. */
+       struct lttng_channel *conf;
+};
+
+/* Channel stream */
+struct ltt_kernel_stream {
+       int fd;
+       int state;
+       int cpu;
+       bool sent_to_consumer;
+       /* Format is %s_%d respectively channel name and CPU number. */
+       char name[DEFAULT_STREAM_NAME_LEN];
+       uint64_t tracefile_size;
+       uint64_t tracefile_count;
+       struct cds_list_head list;
+};
+
+/* Kernel session */
+struct ltt_kernel_session {
+       int fd;
+       int metadata_stream_fd;
+       int consumer_fds_sent;
+       unsigned int channel_count;
+       unsigned int stream_count_global;
+       struct ltt_kernel_metadata *metadata;
+       struct ltt_kernel_channel_list channel_list;
+       /* UID/GID of the user owning the session */
+       uid_t uid;
+       gid_t gid;
+       struct consumer_output *consumer;
+       /* Tracing session id */
+       uint64_t id;
+       /* Session is active or not meaning it has been started or stopped. */
+       unsigned int active:1;
+       /* Tell or not if the session has to output the traces. */
+       unsigned int output_traces;
+       unsigned int snapshot_mode;
+       unsigned int has_non_default_channel;
+       bool is_live_session;
+       /* Current trace chunk of the ltt_session. */
+       struct lttng_trace_chunk *current_trace_chunk;
+       /* Tracker lists */
+       struct process_attr_tracker *tracker_pid;
+       struct process_attr_tracker *tracker_vpid;
+       struct process_attr_tracker *tracker_uid;
+       struct process_attr_tracker *tracker_vuid;
+       struct process_attr_tracker *tracker_gid;
+       struct process_attr_tracker *tracker_vgid;
+};
+
+/*
+ * Lookup functions. NULL is returned if not found.
+ */
+struct ltt_kernel_event *trace_kernel_get_event_by_name(
+               char *name, struct ltt_kernel_channel *channel,
+               enum lttng_event_type type);
+struct ltt_kernel_event *trace_kernel_find_event(
+               char *name, struct ltt_kernel_channel *channel,
+               enum lttng_event_type type,
+               struct lttng_bytecode *filter);
+struct ltt_kernel_channel *trace_kernel_get_channel_by_name(
+               const char *name, struct ltt_kernel_session *session);
+
+/*
+ * Create functions malloc() the data structure.
+ */
+struct ltt_kernel_session *trace_kernel_create_session(void);
+struct ltt_kernel_channel *trace_kernel_create_channel(
+               struct lttng_channel *chan);
+enum lttng_error_code trace_kernel_create_event(struct lttng_event *ev,
+               char *filter_expression, struct lttng_bytecode *filter,
+               struct ltt_kernel_event **kernel_event);
+struct ltt_kernel_metadata *trace_kernel_create_metadata(void);
+struct ltt_kernel_stream *trace_kernel_create_stream(const char *name,
+               unsigned int count);
+struct ltt_kernel_context *trace_kernel_create_context(
+               struct lttng_kernel_abi_context *ctx);
+/* Trigger is only non-const to acquire a reference. */
+enum lttng_error_code trace_kernel_create_event_notifier_rule(
+               struct lttng_trigger *trigger,
+               uint64_t token,
+               uint64_t error_counter_index,
+               struct ltt_kernel_event_notifier_rule **event_notifier_rule);
+struct ltt_kernel_context *trace_kernel_copy_context(
+               struct ltt_kernel_context *ctx);
+enum lttng_error_code trace_kernel_init_event_notifier_from_event_rule(
+               const struct lttng_event_rule *rule,
+               struct lttng_kernel_abi_event_notifier *kernel_event_notifier);
+
+/*
+ * Destroy functions free() the data structure and remove from linked list if
+ * it's applies.
+ */
+void trace_kernel_destroy_session(struct ltt_kernel_session *session);
+void trace_kernel_destroy_metadata(struct ltt_kernel_metadata *metadata);
+void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel);
+void trace_kernel_destroy_event(struct ltt_kernel_event *event);
+void trace_kernel_destroy_stream(struct ltt_kernel_stream *stream);
+void trace_kernel_destroy_context(struct ltt_kernel_context *ctx);
+void trace_kernel_destroy_event_notifier_rule(struct ltt_kernel_event_notifier_rule *rule);
+void trace_kernel_free_session(struct ltt_kernel_session *session);
+
+#endif /* _LTT_TRACE_KERNEL_H */
index 0f303bf035a5db4e80c3bf8953aedc08174d31e8..53ba66f11b4046f6fb1428ab958993c1d5af7f21 100644 (file)
 #include <unistd.h>
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/trace-chunk.h>
-#include <common/utils.h>
-
-#include "buffer-registry.h"
-#include "trace-ust.h"
-#include "utils.h"
-#include "ust-app.h"
-#include "agent.h"
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/utils.hpp>
+
+#include "buffer-registry.hpp"
+#include "trace-ust.hpp"
+#include "utils.hpp"
+#include "ust-app.hpp"
+#include "agent.hpp"
 
 /*
  * Match function for the events hash table lookup.
diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h
deleted file mode 100644 (file)
index cc7cd33..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_TRACE_UST_H
-#define _LTT_TRACE_UST_H
-
-#include <limits.h>
-#include <urcu/list.h>
-
-#include <common/defaults.h>
-#include <common/hashtable/hashtable.h>
-#include <common/tracker.h>
-#include <lttng/lttng.h>
-
-#include "consumer.h"
-#include "lttng-ust-ctl.h"
-
-struct agent;
-
-struct ltt_ust_ht_key {
-       const char *name;
-       const struct lttng_bytecode *filter;
-       enum lttng_ust_abi_loglevel_type loglevel_type;
-       int loglevel_value;
-       const struct lttng_event_exclusion *exclusion;
-};
-
-/* Context hash table nodes */
-struct ltt_ust_context {
-       struct lttng_ust_context_attr ctx;
-       struct lttng_ht_node_ulong node;
-       struct cds_list_head list;
-};
-
-/* UST event */
-struct ltt_ust_event {
-       unsigned int enabled;
-       struct lttng_ust_abi_event attr;
-       struct lttng_ht_node_str node;
-       char *filter_expression;
-       struct lttng_bytecode *filter;
-       struct lttng_event_exclusion *exclusion;
-       /*
-        * An internal event is an event which was created by the session daemon
-        * through which, for example, events emitted in Agent domains are
-        * "funelled". This is used to hide internal events from external
-        * clients as they should never be modified by the external world.
-        */
-       bool internal;
-};
-
-/* UST channel */
-struct ltt_ust_channel {
-       uint64_t id;    /* unique id per session. */
-       unsigned int enabled;
-       /*
-        * A UST channel can be part of a userspace sub-domain such as JUL,
-        * Log4j, Python.
-        */
-       enum lttng_domain_type domain;
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-       struct lttng_ust_abi_channel_attr attr;
-       struct lttng_ht *ctx;
-       struct cds_list_head ctx_list;
-       struct lttng_ht *events;
-       struct lttng_ht_node_str node;
-       uint64_t tracefile_size;
-       uint64_t tracefile_count;
-       uint64_t per_pid_closed_app_discarded;
-       uint64_t per_pid_closed_app_lost;
-       uint64_t monitor_timer_interval;
-};
-
-/* UST domain global (LTTNG_DOMAIN_UST) */
-struct ltt_ust_domain_global {
-       struct lttng_ht *channels;
-       struct cds_list_head registry_buffer_uid_list;
-};
-
-struct ust_id_tracker_node {
-       struct lttng_ht_node_ulong node;
-};
-
-struct ust_id_tracker {
-       struct lttng_ht *ht;
-};
-
-/* UST session */
-struct ltt_ust_session {
-       uint64_t id;    /* Unique identifier of session */
-       struct ltt_ust_domain_global domain_global;
-       /* Hash table of agent indexed by agent domain. */
-       struct lttng_ht *agents;
-       /* UID/GID of the user owning the session */
-       uid_t uid;
-       gid_t gid;
-       /* Is the session active meaning has is been started or stopped. */
-       unsigned int active:1;
-       struct consumer_output *consumer;
-       /* Sequence number for filters so the tracer knows the ordering. */
-       uint64_t filter_seq_num;
-       /* This indicates which type of buffer this session is set for. */
-       enum lttng_buffer_type buffer_type;
-       /* If set to 1, the buffer_type can not be changed anymore. */
-       int buffer_type_changed;
-       /* For per UID buffer, every buffer reg object is kept of this session */
-       struct cds_list_head buffer_reg_uid_list;
-       /* Next channel ID available for a newly registered channel. */
-       uint64_t next_channel_id;
-       /* Once this value reaches UINT32_MAX, no more id can be allocated. */
-       uint64_t used_channel_id;
-       /* Tell or not if the session has to output the traces. */
-       unsigned int output_traces;
-       unsigned int snapshot_mode;
-       unsigned int has_non_default_channel;
-       unsigned int live_timer_interval;       /* usec */
-
-       /* Metadata channel attributes. */
-       struct lttng_ust_abi_channel_attr metadata_attr;
-
-       /*
-        * Path where to keep the shared memory files.
-        */
-       char root_shm_path[PATH_MAX];
-       char shm_path[PATH_MAX];
-
-       /* Current trace chunk of the ltt_session. */
-       struct lttng_trace_chunk *current_trace_chunk;
-
-       /* Trackers used for actual lookup on app registration. */
-       struct ust_id_tracker vpid_tracker;
-       struct ust_id_tracker vuid_tracker;
-       struct ust_id_tracker vgid_tracker;
-
-       /* Tracker list of keys requested by users. */
-       struct process_attr_tracker *tracker_vpid;
-       struct process_attr_tracker *tracker_vuid;
-       struct process_attr_tracker *tracker_vgid;
-};
-
-/*
- * Validate that the id has reached the maximum allowed or not.
- *
- * Return 0 if NOT else 1.
- */
-static inline int trace_ust_is_max_id(uint64_t id)
-{
-       return (id == UINT64_MAX) ? 1 : 0;
-}
-
-/*
- * Return next available channel id and increment the used counter. The
- * trace_ust_is_max_id function MUST be called before in order to validate if
- * the maximum number of IDs have been reached. If not, it is safe to call this
- * function.
- *
- * Return a unique channel ID. If max is reached, the used_channel_id counter
- * is returned.
- */
-static inline uint64_t trace_ust_get_next_chan_id(struct ltt_ust_session *s)
-{
-       if (trace_ust_is_max_id(s->used_channel_id)) {
-               return s->used_channel_id;
-       }
-
-       s->used_channel_id++;
-       return s->next_channel_id++;
-}
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-int trace_ust_ht_match_event(struct cds_lfht_node *node, const void *_key);
-int trace_ust_ht_match_event_by_name(struct cds_lfht_node *node,
-               const void *_key);
-
-/*
- * Lookup functions. NULL is returned if not found.
- */
-struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht,
-               char *name, struct lttng_bytecode *filter,
-               enum lttng_ust_abi_loglevel_type loglevel_type, int loglevel_value,
-               struct lttng_event_exclusion *exclusion);
-struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht,
-               const char *name);
-struct agent *trace_ust_find_agent(struct ltt_ust_session *session,
-               enum lttng_domain_type domain_type);
-
-/*
- * Create functions malloc() the data structure.
- */
-struct ltt_ust_session *trace_ust_create_session(uint64_t session_id);
-struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr,
-               enum lttng_domain_type domain);
-enum lttng_error_code trace_ust_create_event(struct lttng_event *ev,
-               char *filter_expression,
-               struct lttng_bytecode *filter,
-               struct lttng_event_exclusion *exclusion,
-               bool internal_event, struct ltt_ust_event **ust_event);
-struct ltt_ust_context *trace_ust_create_context(
-               const struct lttng_event_context *ctx);
-int trace_ust_match_context(const struct ltt_ust_context *uctx,
-               const struct lttng_event_context *ctx);
-void trace_ust_delete_channel(struct lttng_ht *ht,
-               struct ltt_ust_channel *channel);
-
-/*
- * Destroy functions free() the data structure and remove from linked list if
- * it's applies.
- */
-void trace_ust_destroy_session(struct ltt_ust_session *session);
-void trace_ust_destroy_channel(struct ltt_ust_channel *channel);
-void trace_ust_destroy_event(struct ltt_ust_event *event);
-void trace_ust_destroy_context(struct ltt_ust_context *ctx);
-void trace_ust_free_session(struct ltt_ust_session *session);
-
-int trace_ust_id_tracker_lookup(enum lttng_process_attr process_attr,
-               struct ltt_ust_session *session,
-               int id);
-enum lttng_error_code trace_ust_process_attr_tracker_set_tracking_policy(
-               struct ltt_ust_session *session,
-               enum lttng_process_attr process_attr,
-               enum lttng_tracking_policy policy);
-enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_add_value(
-               struct ltt_ust_session *session,
-               enum lttng_process_attr process_attr,
-               const struct process_attr_value *value);
-enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_remove_value(
-               struct ltt_ust_session *session,
-               enum lttng_process_attr process_attr,
-               const struct process_attr_value *value);
-const struct process_attr_tracker *trace_ust_get_process_attr_tracker(
-               struct ltt_ust_session *session,
-               enum lttng_process_attr process_attr);
-
-#else /* HAVE_LIBLTTNG_UST_CTL */
-
-static inline int trace_ust_ht_match_event(struct cds_lfht_node *node,
-               const void *_key)
-{
-       return 0;
-}
-static inline int trace_ust_ht_match_event_by_name(struct cds_lfht_node *node,
-               const void *_key)
-{
-       return 0;
-}
-static inline
-struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht,
-               const char *name)
-{
-       return NULL;
-}
-
-static inline
-struct ltt_ust_session *trace_ust_create_session(unsigned int session_id)
-{
-       return NULL;
-}
-static inline
-struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr,
-               enum lttng_domain_type domain)
-{
-       return NULL;
-}
-static inline
-enum lttng_error_code trace_ust_create_event(struct lttng_event *ev,
-               const char *filter_expression,
-               struct lttng_bytecode *filter,
-               struct lttng_event_exclusion *exclusion,
-               bool internal_event, struct ltt_ust_event **ust_event)
-{
-       return LTTNG_ERR_NO_UST;
-}
-static inline
-void trace_ust_destroy_session(struct ltt_ust_session *session)
-{
-}
-
-static inline
-void trace_ust_destroy_channel(struct ltt_ust_channel *channel)
-{
-}
-
-static inline
-void trace_ust_destroy_event(struct ltt_ust_event *event)
-{
-}
-
-static inline
-void trace_ust_free_session(struct ltt_ust_session *session)
-{
-}
-
-static inline
-struct ltt_ust_context *trace_ust_create_context(
-               const struct lttng_event_context *ctx)
-{
-       return NULL;
-}
-static inline
-int trace_ust_match_context(const struct ltt_ust_context *uctx,
-               const struct lttng_event_context *ctx)
-{
-       return 0;
-}
-static inline
-struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht,
-               char *name, struct lttng_bytecode *filter,
-               enum lttng_ust_abi_loglevel_type loglevel_type, int loglevel_value,
-               struct lttng_event_exclusion *exclusion)
-{
-       return NULL;
-}
-static inline
-void trace_ust_delete_channel(struct lttng_ht *ht,
-               struct ltt_ust_channel *channel)
-{
-       return;
-}
-static inline
-struct agent *trace_ust_find_agent(struct ltt_ust_session *session,
-               enum lttng_domain_type domain_type)
-{
-       return NULL;
-}
-static inline int trace_ust_id_tracker_lookup(
-               enum lttng_process_attr process_attr,
-               struct ltt_ust_session *session,
-               int id)
-{
-       return 0;
-}
-static inline enum lttng_error_code
-trace_ust_process_attr_tracker_set_tracking_policy(
-               struct ltt_ust_session *session,
-               enum lttng_process_attr process_attr,
-               enum lttng_tracking_policy policy)
-{
-       return LTTNG_OK;
-}
-static inline enum lttng_error_code
-trace_ust_process_attr_tracker_inclusion_set_add_value(
-               struct ltt_ust_session *session,
-               enum lttng_process_attr process_attr,
-               const struct process_attr_value *value)
-{
-       return LTTNG_OK;
-}
-static inline enum lttng_error_code
-trace_ust_process_attr_tracker_inclusion_set_remove_value(
-               struct ltt_ust_session *session,
-               enum lttng_process_attr process_attr,
-               const struct process_attr_value *value)
-{
-       return LTTNG_OK;
-}
-static inline const struct process_attr_tracker *
-trace_ust_get_process_attr_tracker(struct ltt_ust_session *session,
-               enum lttng_process_attr process_attr)
-{
-       return NULL;
-}
-
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* _LTT_TRACE_UST_H */
diff --git a/src/bin/lttng-sessiond/trace-ust.hpp b/src/bin/lttng-sessiond/trace-ust.hpp
new file mode 100644 (file)
index 0000000..57e7a63
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_TRACE_UST_H
+#define _LTT_TRACE_UST_H
+
+#include <limits.h>
+#include <urcu/list.h>
+
+#include <common/defaults.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/tracker.hpp>
+#include <lttng/lttng.h>
+
+#include "consumer.hpp"
+#include "lttng-ust-ctl.hpp"
+
+struct agent;
+
+struct ltt_ust_ht_key {
+       const char *name;
+       const struct lttng_bytecode *filter;
+       enum lttng_ust_abi_loglevel_type loglevel_type;
+       int loglevel_value;
+       const struct lttng_event_exclusion *exclusion;
+};
+
+/* Context hash table nodes */
+struct ltt_ust_context {
+       struct lttng_ust_context_attr ctx;
+       struct lttng_ht_node_ulong node;
+       struct cds_list_head list;
+};
+
+/* UST event */
+struct ltt_ust_event {
+       unsigned int enabled;
+       struct lttng_ust_abi_event attr;
+       struct lttng_ht_node_str node;
+       char *filter_expression;
+       struct lttng_bytecode *filter;
+       struct lttng_event_exclusion *exclusion;
+       /*
+        * An internal event is an event which was created by the session daemon
+        * through which, for example, events emitted in Agent domains are
+        * "funelled". This is used to hide internal events from external
+        * clients as they should never be modified by the external world.
+        */
+       bool internal;
+};
+
+/* UST channel */
+struct ltt_ust_channel {
+       uint64_t id;    /* unique id per session. */
+       unsigned int enabled;
+       /*
+        * A UST channel can be part of a userspace sub-domain such as JUL,
+        * Log4j, Python.
+        */
+       enum lttng_domain_type domain;
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+       struct lttng_ust_abi_channel_attr attr;
+       struct lttng_ht *ctx;
+       struct cds_list_head ctx_list;
+       struct lttng_ht *events;
+       struct lttng_ht_node_str node;
+       uint64_t tracefile_size;
+       uint64_t tracefile_count;
+       uint64_t per_pid_closed_app_discarded;
+       uint64_t per_pid_closed_app_lost;
+       uint64_t monitor_timer_interval;
+};
+
+/* UST domain global (LTTNG_DOMAIN_UST) */
+struct ltt_ust_domain_global {
+       struct lttng_ht *channels;
+       struct cds_list_head registry_buffer_uid_list;
+};
+
+struct ust_id_tracker_node {
+       struct lttng_ht_node_ulong node;
+};
+
+struct ust_id_tracker {
+       struct lttng_ht *ht;
+};
+
+/* UST session */
+struct ltt_ust_session {
+       uint64_t id;    /* Unique identifier of session */
+       struct ltt_ust_domain_global domain_global;
+       /* Hash table of agent indexed by agent domain. */
+       struct lttng_ht *agents;
+       /* UID/GID of the user owning the session */
+       uid_t uid;
+       gid_t gid;
+       /* Is the session active meaning has is been started or stopped. */
+       unsigned int active:1;
+       struct consumer_output *consumer;
+       /* Sequence number for filters so the tracer knows the ordering. */
+       uint64_t filter_seq_num;
+       /* This indicates which type of buffer this session is set for. */
+       enum lttng_buffer_type buffer_type;
+       /* If set to 1, the buffer_type can not be changed anymore. */
+       int buffer_type_changed;
+       /* For per UID buffer, every buffer reg object is kept of this session */
+       struct cds_list_head buffer_reg_uid_list;
+       /* Next channel ID available for a newly registered channel. */
+       uint64_t next_channel_id;
+       /* Once this value reaches UINT32_MAX, no more id can be allocated. */
+       uint64_t used_channel_id;
+       /* Tell or not if the session has to output the traces. */
+       unsigned int output_traces;
+       unsigned int snapshot_mode;
+       unsigned int has_non_default_channel;
+       unsigned int live_timer_interval;       /* usec */
+
+       /* Metadata channel attributes. */
+       struct lttng_ust_abi_channel_attr metadata_attr;
+
+       /*
+        * Path where to keep the shared memory files.
+        */
+       char root_shm_path[PATH_MAX];
+       char shm_path[PATH_MAX];
+
+       /* Current trace chunk of the ltt_session. */
+       struct lttng_trace_chunk *current_trace_chunk;
+
+       /* Trackers used for actual lookup on app registration. */
+       struct ust_id_tracker vpid_tracker;
+       struct ust_id_tracker vuid_tracker;
+       struct ust_id_tracker vgid_tracker;
+
+       /* Tracker list of keys requested by users. */
+       struct process_attr_tracker *tracker_vpid;
+       struct process_attr_tracker *tracker_vuid;
+       struct process_attr_tracker *tracker_vgid;
+};
+
+/*
+ * Validate that the id has reached the maximum allowed or not.
+ *
+ * Return 0 if NOT else 1.
+ */
+static inline int trace_ust_is_max_id(uint64_t id)
+{
+       return (id == UINT64_MAX) ? 1 : 0;
+}
+
+/*
+ * Return next available channel id and increment the used counter. The
+ * trace_ust_is_max_id function MUST be called before in order to validate if
+ * the maximum number of IDs have been reached. If not, it is safe to call this
+ * function.
+ *
+ * Return a unique channel ID. If max is reached, the used_channel_id counter
+ * is returned.
+ */
+static inline uint64_t trace_ust_get_next_chan_id(struct ltt_ust_session *s)
+{
+       if (trace_ust_is_max_id(s->used_channel_id)) {
+               return s->used_channel_id;
+       }
+
+       s->used_channel_id++;
+       return s->next_channel_id++;
+}
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+int trace_ust_ht_match_event(struct cds_lfht_node *node, const void *_key);
+int trace_ust_ht_match_event_by_name(struct cds_lfht_node *node,
+               const void *_key);
+
+/*
+ * Lookup functions. NULL is returned if not found.
+ */
+struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht,
+               char *name, struct lttng_bytecode *filter,
+               enum lttng_ust_abi_loglevel_type loglevel_type, int loglevel_value,
+               struct lttng_event_exclusion *exclusion);
+struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht,
+               const char *name);
+struct agent *trace_ust_find_agent(struct ltt_ust_session *session,
+               enum lttng_domain_type domain_type);
+
+/*
+ * Create functions malloc() the data structure.
+ */
+struct ltt_ust_session *trace_ust_create_session(uint64_t session_id);
+struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr,
+               enum lttng_domain_type domain);
+enum lttng_error_code trace_ust_create_event(struct lttng_event *ev,
+               char *filter_expression,
+               struct lttng_bytecode *filter,
+               struct lttng_event_exclusion *exclusion,
+               bool internal_event, struct ltt_ust_event **ust_event);
+struct ltt_ust_context *trace_ust_create_context(
+               const struct lttng_event_context *ctx);
+int trace_ust_match_context(const struct ltt_ust_context *uctx,
+               const struct lttng_event_context *ctx);
+void trace_ust_delete_channel(struct lttng_ht *ht,
+               struct ltt_ust_channel *channel);
+
+/*
+ * Destroy functions free() the data structure and remove from linked list if
+ * it's applies.
+ */
+void trace_ust_destroy_session(struct ltt_ust_session *session);
+void trace_ust_destroy_channel(struct ltt_ust_channel *channel);
+void trace_ust_destroy_event(struct ltt_ust_event *event);
+void trace_ust_destroy_context(struct ltt_ust_context *ctx);
+void trace_ust_free_session(struct ltt_ust_session *session);
+
+int trace_ust_id_tracker_lookup(enum lttng_process_attr process_attr,
+               struct ltt_ust_session *session,
+               int id);
+enum lttng_error_code trace_ust_process_attr_tracker_set_tracking_policy(
+               struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr,
+               enum lttng_tracking_policy policy);
+enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_add_value(
+               struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value);
+enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_remove_value(
+               struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value);
+const struct process_attr_tracker *trace_ust_get_process_attr_tracker(
+               struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+static inline int trace_ust_ht_match_event(struct cds_lfht_node *node,
+               const void *_key)
+{
+       return 0;
+}
+static inline int trace_ust_ht_match_event_by_name(struct cds_lfht_node *node,
+               const void *_key)
+{
+       return 0;
+}
+static inline
+struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht,
+               const char *name)
+{
+       return NULL;
+}
+
+static inline
+struct ltt_ust_session *trace_ust_create_session(unsigned int session_id)
+{
+       return NULL;
+}
+static inline
+struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr,
+               enum lttng_domain_type domain)
+{
+       return NULL;
+}
+static inline
+enum lttng_error_code trace_ust_create_event(struct lttng_event *ev,
+               const char *filter_expression,
+               struct lttng_bytecode *filter,
+               struct lttng_event_exclusion *exclusion,
+               bool internal_event, struct ltt_ust_event **ust_event)
+{
+       return LTTNG_ERR_NO_UST;
+}
+static inline
+void trace_ust_destroy_session(struct ltt_ust_session *session)
+{
+}
+
+static inline
+void trace_ust_destroy_channel(struct ltt_ust_channel *channel)
+{
+}
+
+static inline
+void trace_ust_destroy_event(struct ltt_ust_event *event)
+{
+}
+
+static inline
+void trace_ust_free_session(struct ltt_ust_session *session)
+{
+}
+
+static inline
+struct ltt_ust_context *trace_ust_create_context(
+               const struct lttng_event_context *ctx)
+{
+       return NULL;
+}
+static inline
+int trace_ust_match_context(const struct ltt_ust_context *uctx,
+               const struct lttng_event_context *ctx)
+{
+       return 0;
+}
+static inline
+struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht,
+               char *name, struct lttng_bytecode *filter,
+               enum lttng_ust_abi_loglevel_type loglevel_type, int loglevel_value,
+               struct lttng_event_exclusion *exclusion)
+{
+       return NULL;
+}
+static inline
+void trace_ust_delete_channel(struct lttng_ht *ht,
+               struct ltt_ust_channel *channel)
+{
+       return;
+}
+static inline
+struct agent *trace_ust_find_agent(struct ltt_ust_session *session,
+               enum lttng_domain_type domain_type)
+{
+       return NULL;
+}
+static inline int trace_ust_id_tracker_lookup(
+               enum lttng_process_attr process_attr,
+               struct ltt_ust_session *session,
+               int id)
+{
+       return 0;
+}
+static inline enum lttng_error_code
+trace_ust_process_attr_tracker_set_tracking_policy(
+               struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr,
+               enum lttng_tracking_policy policy)
+{
+       return LTTNG_OK;
+}
+static inline enum lttng_error_code
+trace_ust_process_attr_tracker_inclusion_set_add_value(
+               struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value)
+{
+       return LTTNG_OK;
+}
+static inline enum lttng_error_code
+trace_ust_process_attr_tracker_inclusion_set_remove_value(
+               struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value)
+{
+       return LTTNG_OK;
+}
+static inline const struct process_attr_tracker *
+trace_ust_get_process_attr_tracker(struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr)
+{
+       return NULL;
+}
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* _LTT_TRACE_UST_H */
index 1cae40350cbcd8c6466ce628fa6a00944539491c..204ade426316b288afd6e59d1ceade61f82a706f 100644 (file)
@@ -7,8 +7,8 @@
  */
 
 #include "lttng/tracker.h"
-#include "common/dynamic-array.h"
-#include "common/macros.h"
+#include "common/dynamic-array.hpp"
+#include "common/macros.hpp"
 #define _LGPL_SOURCE
 #include <grp.h>
 #include <pwd.h>
 #include <urcu/list.h>
 #include <urcu/rculfhash.h>
 
-#include "tracker.h"
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/tracker.h>
+#include "tracker.hpp"
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/tracker.hpp>
 #include <lttng/lttng-error.h>
 
 struct process_attr_tracker_value_node {
diff --git a/src/bin/lttng-sessiond/tracker.h b/src/bin/lttng-sessiond/tracker.h
deleted file mode 100644 (file)
index a45a250..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_TRACKER_H
-#define _LTT_TRACKER_H
-
-#include <common/tracker.h>
-#include <lttng/tracker.h>
-
-struct process_attr_tracker;
-
-enum process_attr_tracker_status {
-       PROCESS_ATTR_TRACKER_STATUS_OK,
-       PROCESS_ATTR_TRACKER_STATUS_ERROR,
-       PROCESS_ATTR_TRACKER_STATUS_EXISTS,
-       PROCESS_ATTR_TRACKER_STATUS_MISSING,
-       PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY,
-};
-
-struct process_attr_tracker *process_attr_tracker_create(void);
-void process_attr_tracker_destroy(struct process_attr_tracker *tracker);
-
-enum lttng_tracking_policy process_attr_tracker_get_tracking_policy(
-               const struct process_attr_tracker *tracker);
-int process_attr_tracker_set_tracking_policy(
-               struct process_attr_tracker *tracker,
-               enum lttng_tracking_policy tracking_policy);
-
-enum process_attr_tracker_status process_attr_tracker_inclusion_set_add_value(
-               struct process_attr_tracker *tracker,
-               const struct process_attr_value *value);
-enum process_attr_tracker_status
-process_attr_tracker_inclusion_set_remove_value(
-               struct process_attr_tracker *tracker,
-               const struct process_attr_value *value);
-
-enum process_attr_tracker_status process_attr_tracker_get_inclusion_set(
-               const struct process_attr_tracker *tracker,
-               struct lttng_process_attr_values **values);
-
-#endif /* _LTT_TRACKER_H */
diff --git a/src/bin/lttng-sessiond/tracker.hpp b/src/bin/lttng-sessiond/tracker.hpp
new file mode 100644 (file)
index 0000000..c3f6b96
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_TRACKER_H
+#define _LTT_TRACKER_H
+
+#include <common/tracker.hpp>
+#include <lttng/tracker.h>
+
+struct process_attr_tracker;
+
+enum process_attr_tracker_status {
+       PROCESS_ATTR_TRACKER_STATUS_OK,
+       PROCESS_ATTR_TRACKER_STATUS_ERROR,
+       PROCESS_ATTR_TRACKER_STATUS_EXISTS,
+       PROCESS_ATTR_TRACKER_STATUS_MISSING,
+       PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY,
+};
+
+struct process_attr_tracker *process_attr_tracker_create(void);
+void process_attr_tracker_destroy(struct process_attr_tracker *tracker);
+
+enum lttng_tracking_policy process_attr_tracker_get_tracking_policy(
+               const struct process_attr_tracker *tracker);
+int process_attr_tracker_set_tracking_policy(
+               struct process_attr_tracker *tracker,
+               enum lttng_tracking_policy tracking_policy);
+
+enum process_attr_tracker_status process_attr_tracker_inclusion_set_add_value(
+               struct process_attr_tracker *tracker,
+               const struct process_attr_value *value);
+enum process_attr_tracker_status
+process_attr_tracker_inclusion_set_remove_value(
+               struct process_attr_tracker *tracker,
+               const struct process_attr_value *value);
+
+enum process_attr_tracker_status process_attr_tracker_get_inclusion_set(
+               const struct process_attr_tracker *tracker,
+               struct lttng_process_attr_values **values);
+
+#endif /* _LTT_TRACKER_H */
index 8c39e1b0655326bf83b587877c47fa17bf7f4d82..1fa2b7510effaa03501b4e1833e35920da28681c 100644 (file)
@@ -5,10 +5,10 @@
  *
  */
 
-#include "event-notifier-error-accounting.h"
-#include <lttng/error-query-internal.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/action/action-internal.h>
+#include "event-notifier-error-accounting.hpp"
+#include <lttng/error-query-internal.hpp>
+#include <lttng/trigger/trigger-internal.hpp>
+#include <lttng/action/action-internal.hpp>
 
 enum lttng_trigger_status lttng_trigger_add_error_results(
                const struct lttng_trigger *trigger,
diff --git a/src/bin/lttng-sessiond/ust-abi-internal.h b/src/bin/lttng-sessiond/ust-abi-internal.h
deleted file mode 100644 (file)
index 652e476..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- * Copied from LTTng-UST lttng/ust-abi.h
- *
- * LTTng-UST ABI header
- *
- */
-
-#ifndef LTTNG_UST_ABI_INTERNAL_H
-#define LTTNG_UST_ABI_INTERNAL_H
-
-#include <stdint.h>
-#include <common/macros.h>
-
-#ifndef LTTNG_PACKED
-#error "LTTNG_PACKED should be defined"
-#endif
-
-#ifndef __ust_stringify
-#define __ust_stringify1(x)    #x
-#define __ust_stringify(x)     __ust_stringify1(x)
-#endif /* __ust_stringify */
-
-#define LTTNG_UST_ABI_SYM_NAME_LEN             256
-#define LTTNG_UST_ABI_PROCNAME_LEN             16
-
-/* UST comm magic number, used to validate protocol and endianness. */
-#define LTTNG_UST_ABI_COMM_MAGIC                       0xC57C57C5
-
-/* Version for ABI between liblttng-ust, sessiond, consumerd */
-#define LTTNG_UST_ABI_MAJOR_VERSION                    9
-#define LTTNG_UST_ABI_MAJOR_VERSION_OLDEST_COMPATIBLE  8
-#define LTTNG_UST_ABI_MINOR_VERSION            0
-
-enum lttng_ust_abi_instrumentation {
-       LTTNG_UST_ABI_TRACEPOINT        = 0,
-       LTTNG_UST_ABI_PROBE             = 1,
-       LTTNG_UST_ABI_FUNCTION          = 2,
-};
-
-enum lttng_ust_abi_loglevel_type {
-       LTTNG_UST_ABI_LOGLEVEL_ALL      = 0,
-       LTTNG_UST_ABI_LOGLEVEL_RANGE    = 1,
-       LTTNG_UST_ABI_LOGLEVEL_SINGLE   = 2,
-};
-
-enum lttng_ust_abi_output {
-       LTTNG_UST_ABI_MMAP              = 0,
-};
-
-enum lttng_ust_abi_chan_type {
-       LTTNG_UST_ABI_CHAN_PER_CPU = 0,
-       LTTNG_UST_ABI_CHAN_METADATA = 1,
-};
-
-struct lttng_ust_abi_tracer_version {
-       uint32_t major;
-       uint32_t minor;
-       uint32_t patchlevel;
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_CHANNEL_PADDING  (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-/*
- * Given that the consumerd is limited to 64k file descriptors, we
- * cannot expect much more than 1MB channel structure size. This size is
- * depends on the number of streams within a channel, which depends on
- * the number of possible CPUs on the system.
- */
-#define LTTNG_UST_ABI_CHANNEL_DATA_MAX_LEN     1048576U
-struct lttng_ust_abi_channel {
-       uint64_t len;
-       int32_t type;   /* enum lttng_ust_abi_chan_type */
-       char padding[LTTNG_UST_ABI_CHANNEL_PADDING];
-       char data[];    /* variable sized data */
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_STREAM_PADDING1  (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-struct lttng_ust_abi_stream {
-       uint64_t len;           /* shm len */
-       uint32_t stream_nr;     /* stream number */
-       char padding[LTTNG_UST_ABI_STREAM_PADDING1];
-       /*
-        * shm_fd and wakeup_fd are send over unix socket as file
-        * descriptors after this structure.
-        */
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_COUNTER_DIMENSION_MAX 4
-
-enum lttng_ust_abi_counter_arithmetic {
-       LTTNG_UST_ABI_COUNTER_ARITHMETIC_MODULAR = 0,
-       LTTNG_UST_ABI_COUNTER_ARITHMETIC_SATURATION = 1,
-};
-
-enum lttng_ust_abi_counter_bitness {
-       LTTNG_UST_ABI_COUNTER_BITNESS_32 = 0,
-       LTTNG_UST_ABI_COUNTER_BITNESS_64 = 1,
-};
-
-struct lttng_ust_abi_counter_dimension {
-       uint64_t size;
-       uint64_t underflow_index;
-       uint64_t overflow_index;
-       uint8_t has_underflow;
-       uint8_t has_overflow;
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_COUNTER_CONF_PADDING1 67
-struct lttng_ust_abi_counter_conf {
-       uint32_t arithmetic;    /* enum lttng_ust_abi_counter_arithmetic */
-       uint32_t bitness;       /* enum lttng_ust_abi_counter_bitness */
-       uint32_t number_dimensions;
-       int64_t global_sum_step;
-       struct lttng_ust_abi_counter_dimension dimensions[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX];
-       uint8_t coalesce_hits;
-       char padding[LTTNG_UST_ABI_COUNTER_CONF_PADDING1];
-} LTTNG_PACKED;
-
-struct lttng_ust_abi_counter_value {
-       uint32_t number_dimensions;
-       uint64_t dimension_indexes[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX];
-       int64_t value;
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_EVENT_PADDING1   8
-#define LTTNG_UST_ABI_EVENT_PADDING2   (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-struct lttng_ust_abi_event {
-       int32_t instrumentation;                /* enum lttng_ust_abi_instrumentation */
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];  /* event name */
-
-       int32_t loglevel_type;                  /* enum lttng_ust_abi_loglevel_type */
-       int32_t loglevel;                       /* value, -1: all */
-       uint64_t token;                         /* User-provided token */
-       char padding[LTTNG_UST_ABI_EVENT_PADDING1];
-
-       /* Per instrumentation type configuration */
-       union {
-               char padding[LTTNG_UST_ABI_EVENT_PADDING2];
-       } u;
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_EVENT_NOTIFIER_PADDING   32
-struct lttng_ust_abi_event_notifier {
-       struct lttng_ust_abi_event event;
-       uint64_t error_counter_index;
-       char padding[LTTNG_UST_ABI_EVENT_NOTIFIER_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING 32
-struct lttng_ust_abi_event_notifier_notification {
-       uint64_t token;
-       uint16_t capture_buf_size;
-       char padding[LTTNG_UST_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_COUNTER_PADDING1         (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-#define LTTNG_UST_ABI_COUNTER_DATA_MAX_LEN     4096U
-struct lttng_ust_abi_counter {
-       uint64_t len;
-       char padding[LTTNG_UST_ABI_COUNTER_PADDING1];
-       char data[];    /* variable sized data */
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_COUNTER_GLOBAL_PADDING1  (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-struct lttng_ust_abi_counter_global {
-       uint64_t len;           /* shm len */
-       char padding[LTTNG_UST_ABI_COUNTER_GLOBAL_PADDING1];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_COUNTER_CPU_PADDING1     (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-struct lttng_ust_abi_counter_cpu {
-       uint64_t len;           /* shm len */
-       uint32_t cpu_nr;
-       char padding[LTTNG_UST_ABI_COUNTER_CPU_PADDING1];
-} LTTNG_PACKED;
-
-enum lttng_ust_abi_field_type {
-       LTTNG_UST_ABI_FIELD_OTHER                       = 0,
-       LTTNG_UST_ABI_FIELD_INTEGER                     = 1,
-       LTTNG_UST_ABI_FIELD_ENUM                        = 2,
-       LTTNG_UST_ABI_FIELD_FLOAT                       = 3,
-       LTTNG_UST_ABI_FIELD_STRING                      = 4,
-};
-
-#define LTTNG_UST_ABI_FIELD_ITER_PADDING       (LTTNG_UST_ABI_SYM_NAME_LEN + 28)
-struct lttng_ust_abi_field_iter {
-       char event_name[LTTNG_UST_ABI_SYM_NAME_LEN];
-       char field_name[LTTNG_UST_ABI_SYM_NAME_LEN];
-       int32_t type;                           /* enum lttng_ust_abi_field_type */
-       int loglevel;                           /* event loglevel */
-       int nowrite;
-       char padding[LTTNG_UST_ABI_FIELD_ITER_PADDING];
-} LTTNG_PACKED;
-
-enum lttng_ust_abi_context_type {
-       LTTNG_UST_ABI_CONTEXT_VTID                      = 0,
-       LTTNG_UST_ABI_CONTEXT_VPID                      = 1,
-       LTTNG_UST_ABI_CONTEXT_PTHREAD_ID                = 2,
-       LTTNG_UST_ABI_CONTEXT_PROCNAME                  = 3,
-       LTTNG_UST_ABI_CONTEXT_IP                        = 4,
-       LTTNG_UST_ABI_CONTEXT_PERF_THREAD_COUNTER       = 5,
-       LTTNG_UST_ABI_CONTEXT_CPU_ID                    = 6,
-       LTTNG_UST_ABI_CONTEXT_APP_CONTEXT               = 7,
-       LTTNG_UST_ABI_CONTEXT_CGROUP_NS                 = 8,
-       LTTNG_UST_ABI_CONTEXT_IPC_NS                    = 9,
-       LTTNG_UST_ABI_CONTEXT_MNT_NS                    = 10,
-       LTTNG_UST_ABI_CONTEXT_NET_NS                    = 11,
-       LTTNG_UST_ABI_CONTEXT_PID_NS                    = 12,
-       LTTNG_UST_ABI_CONTEXT_USER_NS                   = 13,
-       LTTNG_UST_ABI_CONTEXT_UTS_NS                    = 14,
-       LTTNG_UST_ABI_CONTEXT_VUID                      = 15,
-       LTTNG_UST_ABI_CONTEXT_VEUID                     = 16,
-       LTTNG_UST_ABI_CONTEXT_VSUID                     = 17,
-       LTTNG_UST_ABI_CONTEXT_VGID                      = 18,
-       LTTNG_UST_ABI_CONTEXT_VEGID                     = 19,
-       LTTNG_UST_ABI_CONTEXT_VSGID                     = 20,
-       LTTNG_UST_ABI_CONTEXT_TIME_NS                   = 21,
-};
-
-struct lttng_ust_abi_perf_counter_ctx {
-       uint32_t type;
-       uint64_t config;
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_CONTEXT_PADDING1 16
-#define LTTNG_UST_ABI_CONTEXT_PADDING2 (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-struct lttng_ust_abi_context {
-       int32_t ctx;     /* enum lttng_ust_abi_context_type */
-       char padding[LTTNG_UST_ABI_CONTEXT_PADDING1];
-
-       union {
-               struct lttng_ust_abi_perf_counter_ctx perf_counter;
-               struct {
-                       /* Includes trailing '\0'. */
-                       uint32_t provider_name_len;
-                       uint32_t ctx_name_len;
-               } app_ctx;
-               char padding[LTTNG_UST_ABI_CONTEXT_PADDING2];
-       } u;
-} LTTNG_PACKED;
-
-/*
- * Tracer channel attributes.
- */
-#define LTTNG_UST_ABI_CHANNEL_ATTR_PADDING     (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-struct lttng_ust_abi_channel_attr {
-       uint64_t subbuf_size;                   /* bytes */
-       uint64_t num_subbuf;                    /* power of 2 */
-       int overwrite;                          /* 1: overwrite, 0: discard */
-       unsigned int switch_timer_interval;     /* usec */
-       unsigned int read_timer_interval;       /* usec */
-       int32_t output;                         /* enum lttng_ust_abi_output */
-       union {
-               struct {
-                       int64_t blocking_timeout;       /* Blocking timeout (usec) */
-               } s;
-               char padding[LTTNG_UST_ABI_CHANNEL_ATTR_PADDING];
-       } u;
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_TRACEPOINT_ITER_PADDING  16
-struct lttng_ust_abi_tracepoint_iter {
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];  /* provider:name */
-       int loglevel;
-       char padding[LTTNG_UST_ABI_TRACEPOINT_ITER_PADDING];
-} LTTNG_PACKED;
-
-enum lttng_ust_abi_object_type {
-       LTTNG_UST_ABI_OBJECT_TYPE_UNKNOWN = -1,
-       LTTNG_UST_ABI_OBJECT_TYPE_CHANNEL = 0,
-       LTTNG_UST_ABI_OBJECT_TYPE_STREAM = 1,
-       LTTNG_UST_ABI_OBJECT_TYPE_EVENT = 2,
-       LTTNG_UST_ABI_OBJECT_TYPE_CONTEXT = 3,
-       LTTNG_UST_ABI_OBJECT_TYPE_EVENT_NOTIFIER_GROUP = 4,
-       LTTNG_UST_ABI_OBJECT_TYPE_EVENT_NOTIFIER = 5,
-       LTTNG_UST_ABI_OBJECT_TYPE_COUNTER = 6,
-       LTTNG_UST_ABI_OBJECT_TYPE_COUNTER_GLOBAL = 7,
-       LTTNG_UST_ABI_OBJECT_TYPE_COUNTER_CPU = 8,
-};
-
-#define LTTNG_UST_ABI_OBJECT_DATA_PADDING1     32
-#define LTTNG_UST_ABI_OBJECT_DATA_PADDING2     (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-
-struct lttng_ust_abi_object_data {
-       int32_t type;   /* enum lttng_ust_abi_object_type */
-       int handle;
-       uint64_t size;
-       char padding1[LTTNG_UST_ABI_OBJECT_DATA_PADDING1];
-       union {
-               struct {
-                       void *data;
-                       int32_t type;   /* enum lttng_ust_abi_chan_type */
-                       int wakeup_fd;
-               } channel;
-               struct {
-                       int shm_fd;
-                       int wakeup_fd;
-                       uint32_t stream_nr;
-               } stream;
-               struct {
-                       void *data;
-               } counter;
-               struct {
-                       int shm_fd;
-               } counter_global;
-               struct {
-                       int shm_fd;
-                       uint32_t cpu_nr;
-               } counter_cpu;
-               char padding2[LTTNG_UST_ABI_OBJECT_DATA_PADDING2];
-       } u;
-} LTTNG_PACKED;
-
-enum lttng_ust_abi_calibrate_type {
-       LTTNG_UST_ABI_CALIBRATE_TRACEPOINT,
-};
-
-#define LTTNG_UST_ABI_CALIBRATE_PADDING1       16
-#define LTTNG_UST_ABI_CALIBRATE_PADDING2       (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
-struct lttng_ust_abi_calibrate {
-       enum lttng_ust_abi_calibrate_type type;         /* type (input) */
-       char padding[LTTNG_UST_ABI_CALIBRATE_PADDING1];
-
-       union {
-               char padding[LTTNG_UST_ABI_CALIBRATE_PADDING2];
-       } u;
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_FILTER_BYTECODE_MAX_LEN  65536
-#define LTTNG_UST_ABI_FILTER_PADDING           32
-struct lttng_ust_abi_filter_bytecode {
-       uint32_t len;
-       uint32_t reloc_offset;
-       uint64_t seqnum;
-       char padding[LTTNG_UST_ABI_FILTER_PADDING];
-       char data[0];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_CAPTURE_BYTECODE_MAX_LEN 65536
-#define LTTNG_UST_ABI_CAPTURE_PADDING          32
-struct lttng_ust_abi_capture_bytecode {
-       uint32_t len;
-       uint32_t reloc_offset;
-       uint64_t seqnum;
-       char padding[LTTNG_UST_ABI_CAPTURE_PADDING];
-       char data[0];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_EXCLUSION_PADDING        32
-struct lttng_ust_abi_event_exclusion {
-       uint32_t count;
-       char padding[LTTNG_UST_ABI_EXCLUSION_PADDING];
-       char names[LTTNG_UST_ABI_SYM_NAME_LEN][0];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_ABI_CMD(minor)               (minor)
-#define LTTNG_UST_ABI_CMDR(minor, type)                (minor)
-#define LTTNG_UST_ABI_CMDW(minor, type)                (minor)
-
-/* Handled by object descriptor */
-#define LTTNG_UST_ABI_RELEASE                  LTTNG_UST_ABI_CMD(0x1)
-
-/* Handled by object cmd */
-
-/* LTTng-UST commands */
-#define LTTNG_UST_ABI_SESSION                  LTTNG_UST_ABI_CMD(0x40)
-#define LTTNG_UST_ABI_TRACER_VERSION           \
-       LTTNG_UST_ABI_CMDR(0x41, struct lttng_ust_abi_tracer_version)
-#define LTTNG_UST_ABI_TRACEPOINT_LIST          LTTNG_UST_ABI_CMD(0x42)
-#define LTTNG_UST_ABI_WAIT_QUIESCENT           LTTNG_UST_ABI_CMD(0x43)
-#define LTTNG_UST_ABI_REGISTER_DONE            LTTNG_UST_ABI_CMD(0x44)
-#define LTTNG_UST_ABI_TRACEPOINT_FIELD_LIST    LTTNG_UST_ABI_CMD(0x45)
-#define LTTNG_UST_ABI_EVENT_NOTIFIER_GROUP_CREATE \
-       LTTNG_UST_ABI_CMD(0x46)
-
-/* Session commands */
-#define LTTNG_UST_ABI_CHANNEL                  \
-       LTTNG_UST_ABI_CMDW(0x51, struct lttng_ust_abi_channel)
-#define LTTNG_UST_ABI_SESSION_START            LTTNG_UST_ABI_CMD(0x52)
-#define LTTNG_UST_ABI_SESSION_STOP             LTTNG_UST_ABI_CMD(0x53)
-#define LTTNG_UST_ABI_SESSION_STATEDUMP                LTTNG_UST_ABI_CMD(0x54)
-
-/* Channel commands */
-#define LTTNG_UST_ABI_STREAM                   LTTNG_UST_ABI_CMD(0x60)
-#define LTTNG_UST_ABI_EVENT                    \
-       LTTNG_UST_ABI_CMDW(0x61, struct lttng_ust_abi_event)
-
-/* Event and channel commands */
-#define LTTNG_UST_ABI_CONTEXT                  \
-       LTTNG_UST_ABI_CMDW(0x70, struct lttng_ust_abi_context)
-#define LTTNG_UST_ABI_FLUSH_BUFFER             \
-       LTTNG_UST_ABI_CMD(0x71)
-
-/* Event, event notifier, channel and session commands */
-#define LTTNG_UST_ABI_ENABLE                   LTTNG_UST_ABI_CMD(0x80)
-#define LTTNG_UST_ABI_DISABLE                  LTTNG_UST_ABI_CMD(0x81)
-
-/* Tracepoint list commands */
-#define LTTNG_UST_ABI_TRACEPOINT_LIST_GET      LTTNG_UST_ABI_CMD(0x90)
-#define LTTNG_UST_ABI_TRACEPOINT_FIELD_LIST_GET        LTTNG_UST_ABI_CMD(0x91)
-
-/* Event and event notifier commands */
-#define LTTNG_UST_ABI_FILTER                   LTTNG_UST_ABI_CMD(0xA0)
-#define LTTNG_UST_ABI_EXCLUSION                        LTTNG_UST_ABI_CMD(0xA1)
-
-/* Event notifier group commands */
-#define LTTNG_UST_ABI_EVENT_NOTIFIER_CREATE    \
-       LTTNG_UST_ABI_CMDW(0xB0, struct lttng_ust_abi_event_notifier)
-
-/* Event notifier commands */
-#define LTTNG_UST_ABI_CAPTURE                  LTTNG_UST_ABI_CMD(0xB6)
-
-/* Session and event notifier group commands */
-#define LTTNG_UST_ABI_COUNTER                  \
-       LTTNG_UST_ABI_CMDW(0xC0, struct lttng_ust_abi_counter)
-
-/* Counter commands */
-#define LTTNG_UST_ABI_COUNTER_GLOBAL           \
-       LTTNG_UST_ABI_CMDW(0xD0, struct lttng_ust_abi_counter_global)
-#define LTTNG_UST_ABI_COUNTER_CPU              \
-       LTTNG_UST_ABI_CMDW(0xD1, struct lttng_ust_abi_counter_cpu)
-
-#define LTTNG_UST_ABI_ROOT_HANDLE      0
-
-#endif /* LTTNG_UST_ABI_INTERNAL_H */
diff --git a/src/bin/lttng-sessiond/ust-abi-internal.hpp b/src/bin/lttng-sessiond/ust-abi-internal.hpp
new file mode 100644 (file)
index 0000000..343be56
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * Copyright 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Copied from LTTng-UST lttng/ust-abi.h
+ *
+ * LTTng-UST ABI header
+ *
+ */
+
+#ifndef LTTNG_UST_ABI_INTERNAL_H
+#define LTTNG_UST_ABI_INTERNAL_H
+
+#include <stdint.h>
+#include <common/macros.hpp>
+
+#ifndef LTTNG_PACKED
+#error "LTTNG_PACKED should be defined"
+#endif
+
+#ifndef __ust_stringify
+#define __ust_stringify1(x)    #x
+#define __ust_stringify(x)     __ust_stringify1(x)
+#endif /* __ust_stringify */
+
+#define LTTNG_UST_ABI_SYM_NAME_LEN             256
+#define LTTNG_UST_ABI_PROCNAME_LEN             16
+
+/* UST comm magic number, used to validate protocol and endianness. */
+#define LTTNG_UST_ABI_COMM_MAGIC                       0xC57C57C5
+
+/* Version for ABI between liblttng-ust, sessiond, consumerd */
+#define LTTNG_UST_ABI_MAJOR_VERSION                    9
+#define LTTNG_UST_ABI_MAJOR_VERSION_OLDEST_COMPATIBLE  8
+#define LTTNG_UST_ABI_MINOR_VERSION            0
+
+enum lttng_ust_abi_instrumentation {
+       LTTNG_UST_ABI_TRACEPOINT        = 0,
+       LTTNG_UST_ABI_PROBE             = 1,
+       LTTNG_UST_ABI_FUNCTION          = 2,
+};
+
+enum lttng_ust_abi_loglevel_type {
+       LTTNG_UST_ABI_LOGLEVEL_ALL      = 0,
+       LTTNG_UST_ABI_LOGLEVEL_RANGE    = 1,
+       LTTNG_UST_ABI_LOGLEVEL_SINGLE   = 2,
+};
+
+enum lttng_ust_abi_output {
+       LTTNG_UST_ABI_MMAP              = 0,
+};
+
+enum lttng_ust_abi_chan_type {
+       LTTNG_UST_ABI_CHAN_PER_CPU = 0,
+       LTTNG_UST_ABI_CHAN_METADATA = 1,
+};
+
+struct lttng_ust_abi_tracer_version {
+       uint32_t major;
+       uint32_t minor;
+       uint32_t patchlevel;
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_CHANNEL_PADDING  (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+/*
+ * Given that the consumerd is limited to 64k file descriptors, we
+ * cannot expect much more than 1MB channel structure size. This size is
+ * depends on the number of streams within a channel, which depends on
+ * the number of possible CPUs on the system.
+ */
+#define LTTNG_UST_ABI_CHANNEL_DATA_MAX_LEN     1048576U
+struct lttng_ust_abi_channel {
+       uint64_t len;
+       int32_t type;   /* enum lttng_ust_abi_chan_type */
+       char padding[LTTNG_UST_ABI_CHANNEL_PADDING];
+       char data[];    /* variable sized data */
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_STREAM_PADDING1  (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+struct lttng_ust_abi_stream {
+       uint64_t len;           /* shm len */
+       uint32_t stream_nr;     /* stream number */
+       char padding[LTTNG_UST_ABI_STREAM_PADDING1];
+       /*
+        * shm_fd and wakeup_fd are send over unix socket as file
+        * descriptors after this structure.
+        */
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_COUNTER_DIMENSION_MAX 4
+
+enum lttng_ust_abi_counter_arithmetic {
+       LTTNG_UST_ABI_COUNTER_ARITHMETIC_MODULAR = 0,
+       LTTNG_UST_ABI_COUNTER_ARITHMETIC_SATURATION = 1,
+};
+
+enum lttng_ust_abi_counter_bitness {
+       LTTNG_UST_ABI_COUNTER_BITNESS_32 = 0,
+       LTTNG_UST_ABI_COUNTER_BITNESS_64 = 1,
+};
+
+struct lttng_ust_abi_counter_dimension {
+       uint64_t size;
+       uint64_t underflow_index;
+       uint64_t overflow_index;
+       uint8_t has_underflow;
+       uint8_t has_overflow;
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_COUNTER_CONF_PADDING1 67
+struct lttng_ust_abi_counter_conf {
+       uint32_t arithmetic;    /* enum lttng_ust_abi_counter_arithmetic */
+       uint32_t bitness;       /* enum lttng_ust_abi_counter_bitness */
+       uint32_t number_dimensions;
+       int64_t global_sum_step;
+       struct lttng_ust_abi_counter_dimension dimensions[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX];
+       uint8_t coalesce_hits;
+       char padding[LTTNG_UST_ABI_COUNTER_CONF_PADDING1];
+} LTTNG_PACKED;
+
+struct lttng_ust_abi_counter_value {
+       uint32_t number_dimensions;
+       uint64_t dimension_indexes[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX];
+       int64_t value;
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_EVENT_PADDING1   8
+#define LTTNG_UST_ABI_EVENT_PADDING2   (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+struct lttng_ust_abi_event {
+       int32_t instrumentation;                /* enum lttng_ust_abi_instrumentation */
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];  /* event name */
+
+       int32_t loglevel_type;                  /* enum lttng_ust_abi_loglevel_type */
+       int32_t loglevel;                       /* value, -1: all */
+       uint64_t token;                         /* User-provided token */
+       char padding[LTTNG_UST_ABI_EVENT_PADDING1];
+
+       /* Per instrumentation type configuration */
+       union {
+               char padding[LTTNG_UST_ABI_EVENT_PADDING2];
+       } u;
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_EVENT_NOTIFIER_PADDING   32
+struct lttng_ust_abi_event_notifier {
+       struct lttng_ust_abi_event event;
+       uint64_t error_counter_index;
+       char padding[LTTNG_UST_ABI_EVENT_NOTIFIER_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING 32
+struct lttng_ust_abi_event_notifier_notification {
+       uint64_t token;
+       uint16_t capture_buf_size;
+       char padding[LTTNG_UST_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_COUNTER_PADDING1         (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+#define LTTNG_UST_ABI_COUNTER_DATA_MAX_LEN     4096U
+struct lttng_ust_abi_counter {
+       uint64_t len;
+       char padding[LTTNG_UST_ABI_COUNTER_PADDING1];
+       char data[];    /* variable sized data */
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_COUNTER_GLOBAL_PADDING1  (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+struct lttng_ust_abi_counter_global {
+       uint64_t len;           /* shm len */
+       char padding[LTTNG_UST_ABI_COUNTER_GLOBAL_PADDING1];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_COUNTER_CPU_PADDING1     (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+struct lttng_ust_abi_counter_cpu {
+       uint64_t len;           /* shm len */
+       uint32_t cpu_nr;
+       char padding[LTTNG_UST_ABI_COUNTER_CPU_PADDING1];
+} LTTNG_PACKED;
+
+enum lttng_ust_abi_field_type {
+       LTTNG_UST_ABI_FIELD_OTHER                       = 0,
+       LTTNG_UST_ABI_FIELD_INTEGER                     = 1,
+       LTTNG_UST_ABI_FIELD_ENUM                        = 2,
+       LTTNG_UST_ABI_FIELD_FLOAT                       = 3,
+       LTTNG_UST_ABI_FIELD_STRING                      = 4,
+};
+
+#define LTTNG_UST_ABI_FIELD_ITER_PADDING       (LTTNG_UST_ABI_SYM_NAME_LEN + 28)
+struct lttng_ust_abi_field_iter {
+       char event_name[LTTNG_UST_ABI_SYM_NAME_LEN];
+       char field_name[LTTNG_UST_ABI_SYM_NAME_LEN];
+       int32_t type;                           /* enum lttng_ust_abi_field_type */
+       int loglevel;                           /* event loglevel */
+       int nowrite;
+       char padding[LTTNG_UST_ABI_FIELD_ITER_PADDING];
+} LTTNG_PACKED;
+
+enum lttng_ust_abi_context_type {
+       LTTNG_UST_ABI_CONTEXT_VTID                      = 0,
+       LTTNG_UST_ABI_CONTEXT_VPID                      = 1,
+       LTTNG_UST_ABI_CONTEXT_PTHREAD_ID                = 2,
+       LTTNG_UST_ABI_CONTEXT_PROCNAME                  = 3,
+       LTTNG_UST_ABI_CONTEXT_IP                        = 4,
+       LTTNG_UST_ABI_CONTEXT_PERF_THREAD_COUNTER       = 5,
+       LTTNG_UST_ABI_CONTEXT_CPU_ID                    = 6,
+       LTTNG_UST_ABI_CONTEXT_APP_CONTEXT               = 7,
+       LTTNG_UST_ABI_CONTEXT_CGROUP_NS                 = 8,
+       LTTNG_UST_ABI_CONTEXT_IPC_NS                    = 9,
+       LTTNG_UST_ABI_CONTEXT_MNT_NS                    = 10,
+       LTTNG_UST_ABI_CONTEXT_NET_NS                    = 11,
+       LTTNG_UST_ABI_CONTEXT_PID_NS                    = 12,
+       LTTNG_UST_ABI_CONTEXT_USER_NS                   = 13,
+       LTTNG_UST_ABI_CONTEXT_UTS_NS                    = 14,
+       LTTNG_UST_ABI_CONTEXT_VUID                      = 15,
+       LTTNG_UST_ABI_CONTEXT_VEUID                     = 16,
+       LTTNG_UST_ABI_CONTEXT_VSUID                     = 17,
+       LTTNG_UST_ABI_CONTEXT_VGID                      = 18,
+       LTTNG_UST_ABI_CONTEXT_VEGID                     = 19,
+       LTTNG_UST_ABI_CONTEXT_VSGID                     = 20,
+       LTTNG_UST_ABI_CONTEXT_TIME_NS                   = 21,
+};
+
+struct lttng_ust_abi_perf_counter_ctx {
+       uint32_t type;
+       uint64_t config;
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_CONTEXT_PADDING1 16
+#define LTTNG_UST_ABI_CONTEXT_PADDING2 (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+struct lttng_ust_abi_context {
+       int32_t ctx;     /* enum lttng_ust_abi_context_type */
+       char padding[LTTNG_UST_ABI_CONTEXT_PADDING1];
+
+       union {
+               struct lttng_ust_abi_perf_counter_ctx perf_counter;
+               struct {
+                       /* Includes trailing '\0'. */
+                       uint32_t provider_name_len;
+                       uint32_t ctx_name_len;
+               } app_ctx;
+               char padding[LTTNG_UST_ABI_CONTEXT_PADDING2];
+       } u;
+} LTTNG_PACKED;
+
+/*
+ * Tracer channel attributes.
+ */
+#define LTTNG_UST_ABI_CHANNEL_ATTR_PADDING     (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+struct lttng_ust_abi_channel_attr {
+       uint64_t subbuf_size;                   /* bytes */
+       uint64_t num_subbuf;                    /* power of 2 */
+       int overwrite;                          /* 1: overwrite, 0: discard */
+       unsigned int switch_timer_interval;     /* usec */
+       unsigned int read_timer_interval;       /* usec */
+       int32_t output;                         /* enum lttng_ust_abi_output */
+       union {
+               struct {
+                       int64_t blocking_timeout;       /* Blocking timeout (usec) */
+               } s;
+               char padding[LTTNG_UST_ABI_CHANNEL_ATTR_PADDING];
+       } u;
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_TRACEPOINT_ITER_PADDING  16
+struct lttng_ust_abi_tracepoint_iter {
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];  /* provider:name */
+       int loglevel;
+       char padding[LTTNG_UST_ABI_TRACEPOINT_ITER_PADDING];
+} LTTNG_PACKED;
+
+enum lttng_ust_abi_object_type {
+       LTTNG_UST_ABI_OBJECT_TYPE_UNKNOWN = -1,
+       LTTNG_UST_ABI_OBJECT_TYPE_CHANNEL = 0,
+       LTTNG_UST_ABI_OBJECT_TYPE_STREAM = 1,
+       LTTNG_UST_ABI_OBJECT_TYPE_EVENT = 2,
+       LTTNG_UST_ABI_OBJECT_TYPE_CONTEXT = 3,
+       LTTNG_UST_ABI_OBJECT_TYPE_EVENT_NOTIFIER_GROUP = 4,
+       LTTNG_UST_ABI_OBJECT_TYPE_EVENT_NOTIFIER = 5,
+       LTTNG_UST_ABI_OBJECT_TYPE_COUNTER = 6,
+       LTTNG_UST_ABI_OBJECT_TYPE_COUNTER_GLOBAL = 7,
+       LTTNG_UST_ABI_OBJECT_TYPE_COUNTER_CPU = 8,
+};
+
+#define LTTNG_UST_ABI_OBJECT_DATA_PADDING1     32
+#define LTTNG_UST_ABI_OBJECT_DATA_PADDING2     (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+
+struct lttng_ust_abi_object_data {
+       int32_t type;   /* enum lttng_ust_abi_object_type */
+       int handle;
+       uint64_t size;
+       char padding1[LTTNG_UST_ABI_OBJECT_DATA_PADDING1];
+       union {
+               struct {
+                       void *data;
+                       int32_t type;   /* enum lttng_ust_abi_chan_type */
+                       int wakeup_fd;
+               } channel;
+               struct {
+                       int shm_fd;
+                       int wakeup_fd;
+                       uint32_t stream_nr;
+               } stream;
+               struct {
+                       void *data;
+               } counter;
+               struct {
+                       int shm_fd;
+               } counter_global;
+               struct {
+                       int shm_fd;
+                       uint32_t cpu_nr;
+               } counter_cpu;
+               char padding2[LTTNG_UST_ABI_OBJECT_DATA_PADDING2];
+       } u;
+} LTTNG_PACKED;
+
+enum lttng_ust_abi_calibrate_type {
+       LTTNG_UST_ABI_CALIBRATE_TRACEPOINT,
+};
+
+#define LTTNG_UST_ABI_CALIBRATE_PADDING1       16
+#define LTTNG_UST_ABI_CALIBRATE_PADDING2       (LTTNG_UST_ABI_SYM_NAME_LEN + 32)
+struct lttng_ust_abi_calibrate {
+       enum lttng_ust_abi_calibrate_type type;         /* type (input) */
+       char padding[LTTNG_UST_ABI_CALIBRATE_PADDING1];
+
+       union {
+               char padding[LTTNG_UST_ABI_CALIBRATE_PADDING2];
+       } u;
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_FILTER_BYTECODE_MAX_LEN  65536
+#define LTTNG_UST_ABI_FILTER_PADDING           32
+struct lttng_ust_abi_filter_bytecode {
+       uint32_t len;
+       uint32_t reloc_offset;
+       uint64_t seqnum;
+       char padding[LTTNG_UST_ABI_FILTER_PADDING];
+       char data[0];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_CAPTURE_BYTECODE_MAX_LEN 65536
+#define LTTNG_UST_ABI_CAPTURE_PADDING          32
+struct lttng_ust_abi_capture_bytecode {
+       uint32_t len;
+       uint32_t reloc_offset;
+       uint64_t seqnum;
+       char padding[LTTNG_UST_ABI_CAPTURE_PADDING];
+       char data[0];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_EXCLUSION_PADDING        32
+struct lttng_ust_abi_event_exclusion {
+       uint32_t count;
+       char padding[LTTNG_UST_ABI_EXCLUSION_PADDING];
+       char names[LTTNG_UST_ABI_SYM_NAME_LEN][0];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_ABI_CMD(minor)               (minor)
+#define LTTNG_UST_ABI_CMDR(minor, type)                (minor)
+#define LTTNG_UST_ABI_CMDW(minor, type)                (minor)
+
+/* Handled by object descriptor */
+#define LTTNG_UST_ABI_RELEASE                  LTTNG_UST_ABI_CMD(0x1)
+
+/* Handled by object cmd */
+
+/* LTTng-UST commands */
+#define LTTNG_UST_ABI_SESSION                  LTTNG_UST_ABI_CMD(0x40)
+#define LTTNG_UST_ABI_TRACER_VERSION           \
+       LTTNG_UST_ABI_CMDR(0x41, struct lttng_ust_abi_tracer_version)
+#define LTTNG_UST_ABI_TRACEPOINT_LIST          LTTNG_UST_ABI_CMD(0x42)
+#define LTTNG_UST_ABI_WAIT_QUIESCENT           LTTNG_UST_ABI_CMD(0x43)
+#define LTTNG_UST_ABI_REGISTER_DONE            LTTNG_UST_ABI_CMD(0x44)
+#define LTTNG_UST_ABI_TRACEPOINT_FIELD_LIST    LTTNG_UST_ABI_CMD(0x45)
+#define LTTNG_UST_ABI_EVENT_NOTIFIER_GROUP_CREATE \
+       LTTNG_UST_ABI_CMD(0x46)
+
+/* Session commands */
+#define LTTNG_UST_ABI_CHANNEL                  \
+       LTTNG_UST_ABI_CMDW(0x51, struct lttng_ust_abi_channel)
+#define LTTNG_UST_ABI_SESSION_START            LTTNG_UST_ABI_CMD(0x52)
+#define LTTNG_UST_ABI_SESSION_STOP             LTTNG_UST_ABI_CMD(0x53)
+#define LTTNG_UST_ABI_SESSION_STATEDUMP                LTTNG_UST_ABI_CMD(0x54)
+
+/* Channel commands */
+#define LTTNG_UST_ABI_STREAM                   LTTNG_UST_ABI_CMD(0x60)
+#define LTTNG_UST_ABI_EVENT                    \
+       LTTNG_UST_ABI_CMDW(0x61, struct lttng_ust_abi_event)
+
+/* Event and channel commands */
+#define LTTNG_UST_ABI_CONTEXT                  \
+       LTTNG_UST_ABI_CMDW(0x70, struct lttng_ust_abi_context)
+#define LTTNG_UST_ABI_FLUSH_BUFFER             \
+       LTTNG_UST_ABI_CMD(0x71)
+
+/* Event, event notifier, channel and session commands */
+#define LTTNG_UST_ABI_ENABLE                   LTTNG_UST_ABI_CMD(0x80)
+#define LTTNG_UST_ABI_DISABLE                  LTTNG_UST_ABI_CMD(0x81)
+
+/* Tracepoint list commands */
+#define LTTNG_UST_ABI_TRACEPOINT_LIST_GET      LTTNG_UST_ABI_CMD(0x90)
+#define LTTNG_UST_ABI_TRACEPOINT_FIELD_LIST_GET        LTTNG_UST_ABI_CMD(0x91)
+
+/* Event and event notifier commands */
+#define LTTNG_UST_ABI_FILTER                   LTTNG_UST_ABI_CMD(0xA0)
+#define LTTNG_UST_ABI_EXCLUSION                        LTTNG_UST_ABI_CMD(0xA1)
+
+/* Event notifier group commands */
+#define LTTNG_UST_ABI_EVENT_NOTIFIER_CREATE    \
+       LTTNG_UST_ABI_CMDW(0xB0, struct lttng_ust_abi_event_notifier)
+
+/* Event notifier commands */
+#define LTTNG_UST_ABI_CAPTURE                  LTTNG_UST_ABI_CMD(0xB6)
+
+/* Session and event notifier group commands */
+#define LTTNG_UST_ABI_COUNTER                  \
+       LTTNG_UST_ABI_CMDW(0xC0, struct lttng_ust_abi_counter)
+
+/* Counter commands */
+#define LTTNG_UST_ABI_COUNTER_GLOBAL           \
+       LTTNG_UST_ABI_CMDW(0xD0, struct lttng_ust_abi_counter_global)
+#define LTTNG_UST_ABI_COUNTER_CPU              \
+       LTTNG_UST_ABI_CMDW(0xD1, struct lttng_ust_abi_counter_cpu)
+
+#define LTTNG_UST_ABI_ROOT_HANDLE      0
+
+#endif /* LTTNG_UST_ABI_INTERNAL_H */
index 54cd4dea645b7e1b30edf06822156bdc3781ed37..fc629d56a961cfb8a27045a3933edda55aeff77e 100644 (file)
 #include <urcu/compiler.h>
 #include <signal.h>
 
-#include <common/bytecode/bytecode.h>
-#include <common/compat/errno.h>
-#include <common/common.h>
-#include <common/hashtable/utils.h>
+#include <common/bytecode/bytecode.hpp>
+#include <common/compat/errno.hpp>
+#include <common/common.hpp>
+#include <common/hashtable/utils.hpp>
 #include <lttng/event-rule/event-rule.h>
-#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/event-rule-internal.hpp>
 #include <lttng/event-rule/user-tracepoint.h>
 #include <lttng/condition/condition.h>
-#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/condition/event-rule-matches-internal.hpp>
 #include <lttng/condition/event-rule-matches.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-
-#include "buffer-registry.h"
-#include "condition-internal.h"
-#include "fd-limit.h"
-#include "health-sessiond.h"
-#include "ust-app.h"
-#include "ust-consumer.h"
-#include "lttng-ust-ctl.h"
-#include "lttng-ust-error.h"
-#include "utils.h"
-#include "session.h"
-#include "lttng-sessiond.h"
-#include "notification-thread-commands.h"
-#include "rotate.h"
-#include "event.h"
-#include "event-notifier-error-accounting.h"
-#include "ust-field-utils.h"
+#include <lttng/trigger/trigger-internal.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+
+#include "buffer-registry.hpp"
+#include "condition-internal.hpp"
+#include "fd-limit.hpp"
+#include "health-sessiond.hpp"
+#include "ust-app.hpp"
+#include "ust-consumer.hpp"
+#include "lttng-ust-ctl.hpp"
+#include "lttng-ust-error.hpp"
+#include "utils.hpp"
+#include "session.hpp"
+#include "lttng-sessiond.hpp"
+#include "notification-thread-commands.hpp"
+#include "rotate.hpp"
+#include "event.hpp"
+#include "event-notifier-error-accounting.hpp"
+#include "ust-field-utils.hpp"
 
 struct lttng_ht *ust_app_ht;
 struct lttng_ht *ust_app_ht_by_sock;
diff --git a/src/bin/lttng-sessiond/ust-app.h b/src/bin/lttng-sessiond/ust-app.h
deleted file mode 100644 (file)
index 8d2d289..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_UST_APP_H
-#define _LTT_UST_APP_H
-
-#include <stdint.h>
-
-#include <common/index-allocator.h>
-#include <common/uuid.h>
-
-#include "trace-ust.h"
-#include "ust-registry.h"
-#include "session.h"
-
-#define UST_APP_EVENT_LIST_SIZE 32
-
-/* Process name (short). */
-#define UST_APP_PROCNAME_LEN   16
-
-struct lttng_bytecode;
-struct lttng_ust_filter_bytecode;
-
-extern int the_ust_consumerd64_fd, the_ust_consumerd32_fd;
-
-/*
- * Object used to close the notify socket in a call_rcu(). Since the
- * application might not be found, we need an independant object containing the
- * notify socket fd.
- */
-struct ust_app_notify_sock_obj {
-       int fd;
-       struct rcu_head head;
-};
-
-struct ust_app_ht_key {
-       const char *name;
-       const struct lttng_bytecode *filter;
-       enum lttng_ust_abi_loglevel_type loglevel_type;
-       const struct lttng_event_exclusion *exclusion;
-};
-
-/*
- * Application registration data structure.
- */
-struct ust_register_msg {
-       enum lttng_ust_ctl_socket_type type;
-       uint32_t major;
-       uint32_t minor;
-       uint32_t abi_major;
-       uint32_t abi_minor;
-       pid_t pid;
-       pid_t ppid;
-       uid_t uid;
-       gid_t gid;
-       uint32_t bits_per_long;
-       uint32_t uint8_t_alignment;
-       uint32_t uint16_t_alignment;
-       uint32_t uint32_t_alignment;
-       uint32_t uint64_t_alignment;
-       uint32_t long_alignment;
-       int byte_order;         /* BIG_ENDIAN or LITTLE_ENDIAN */
-       char name[LTTNG_UST_ABI_PROCNAME_LEN];
-};
-
-/*
- * Global applications HT used by the session daemon. This table is indexed by
- * PID using the pid_n node and pid value of an ust_app.
- */
-extern struct lttng_ht *ust_app_ht;
-
-/*
- * Global applications HT used by the session daemon. This table is indexed by
- * socket using the sock_n node and sock value of an ust_app.
- *
- * The 'sock' in question here is the 'command' socket.
- */
-extern struct lttng_ht *ust_app_ht_by_sock;
-
-/*
- * Global applications HT used by the session daemon. This table is indexed by
- * socket using the notify_sock_n node and notify_sock value of an ust_app.
- */
-extern struct lttng_ht *ust_app_ht_by_notify_sock;
-
-/* Stream list containing ust_app_stream. */
-struct ust_app_stream_list {
-       unsigned int count;
-       struct cds_list_head head;
-};
-
-struct ust_app_ctx {
-       int handle;
-       struct lttng_ust_context_attr ctx;
-       struct lttng_ust_abi_object_data *obj;
-       struct lttng_ht_node_ulong node;
-       struct cds_list_head list;
-};
-
-struct ust_app_event {
-       int enabled;
-       int handle;
-       struct lttng_ust_abi_object_data *obj;
-       struct lttng_ust_abi_event attr;
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-       struct lttng_ht_node_str node;
-       struct lttng_bytecode *filter;
-       struct lttng_event_exclusion *exclusion;
-};
-
-struct ust_app_event_notifier_rule {
-       int enabled;
-       uint64_t error_counter_index;
-       int handle;
-       struct lttng_ust_abi_object_data *obj;
-       /* Holds a strong reference. */
-       struct lttng_trigger *trigger;
-       /* Unique ID returned by the tracer to identify this event notifier. */
-       uint64_t token;
-       struct lttng_ht_node_u64 node;
-       /* The trigger object owns the filter. */
-       const struct lttng_bytecode *filter;
-       /* Owned by this. */
-       struct lttng_event_exclusion *exclusion;
-       /* For delayed reclaim. */
-       struct rcu_head rcu_head;
-};
-
-struct ust_app_stream {
-       int handle;
-       char pathname[PATH_MAX];
-       /* Format is %s_%d respectively channel name and CPU number. */
-       char name[DEFAULT_STREAM_NAME_LEN];
-       struct lttng_ust_abi_object_data *obj;
-       /* Using a list of streams to keep order. */
-       struct cds_list_head list;
-};
-
-struct ust_app_channel {
-       int enabled;
-       int handle;
-       /* Channel and streams were sent to the UST tracer. */
-       int is_sent;
-       /*
-        * Unique key used to identify the channel on the consumer side.
-        * 0 is a reserved 'invalid' value used to indicate that the consumer
-        * does not know about this channel (i.e. an error occurred).
-        */
-       uint64_t key;
-       /* Id of the tracing channel set on creation. */
-       uint64_t tracing_channel_id;
-       /* Number of stream that this channel is expected to receive. */
-       unsigned int expected_stream_count;
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-       struct lttng_ust_abi_object_data *obj;
-       struct lttng_ust_ctl_consumer_channel_attr attr;
-       struct ust_app_stream_list streams;
-       /* Session pointer that owns this object. */
-       struct ust_app_session *session;
-       /*
-        * Contexts are kept in a hash table for fast lookup and in an ordered list
-        * so we are able to enable them on the tracer side in the same order the
-        * user added them.
-        */
-       struct lttng_ht *ctx;
-       struct cds_list_head ctx_list;
-
-       struct lttng_ht *events;
-       uint64_t tracefile_size;
-       uint64_t tracefile_count;
-       uint64_t monitor_timer_interval;
-       /*
-        * Node indexed by channel name in the channels' hash table of a session.
-        */
-       struct lttng_ht_node_str node;
-       /*
-        * Node indexed by UST channel object descriptor (handle). Stored in the
-        * ust_objd hash table in the ust_app object.
-        */
-       struct lttng_ht_node_ulong ust_objd_node;
-       /* For delayed reclaim */
-       struct rcu_head rcu_head;
-};
-
-struct ust_app_session {
-       /*
-        * Lock protecting this session's ust app interaction. Held
-        * across command send/recv to/from app. Never nests within the
-        * session registry lock.
-        */
-       pthread_mutex_t lock;
-
-       int enabled;
-       /* started: has the session been in started state at any time ? */
-       int started;  /* allows detection of start vs restart. */
-       int handle;   /* used has unique identifier for app session */
-
-       bool deleted;   /* Session deleted flag. Check with lock held. */
-
-       /*
-        * Tracing session ID. Multiple ust app session can have the same tracing
-        * session id making this value NOT unique to the object.
-        */
-       uint64_t tracing_id;
-       uint64_t id;    /* Unique session identifier */
-       struct lttng_ht *channels; /* Registered channels */
-       struct lttng_ht_node_u64 node;
-       /*
-        * Node indexed by UST session object descriptor (handle). Stored in the
-        * ust_sessions_objd hash table in the ust_app object.
-        */
-       struct lttng_ht_node_ulong ust_objd_node;
-       /* Starts with 'ust'; no leading slash. */
-       char path[PATH_MAX];
-       /* UID/GID of the application owning the session */
-       struct lttng_credentials real_credentials;
-       /* Effective UID and GID. Same as the tracing session. */
-       struct lttng_credentials effective_credentials;
-       struct cds_list_head teardown_node;
-       /*
-        * Once at least *one* session is created onto the application, the
-        * corresponding consumer is set so we can use it on unregistration.
-        */
-       struct consumer_output *consumer;
-       enum lttng_buffer_type buffer_type;
-       /* ABI of the session. Same value as the application. */
-       uint32_t bits_per_long;
-       /* For delayed reclaim */
-       struct rcu_head rcu_head;
-       /* If the channel's streams have to be outputed or not. */
-       unsigned int output_traces;
-       unsigned int live_timer_interval;       /* usec */
-
-       /* Metadata channel attributes. */
-       struct lttng_ust_ctl_consumer_channel_attr metadata_attr;
-
-       char root_shm_path[PATH_MAX];
-       char shm_path[PATH_MAX];
-};
-
-/*
- * Registered traceable applications. Libust registers to the session daemon
- * and a linked list is kept of all running traceable app.
- */
-struct ust_app {
-       int sock;
-       pthread_mutex_t sock_lock;      /* Protects sock protocol. */
-
-       int notify_sock;
-       pid_t pid;
-       pid_t ppid;
-       uid_t uid;           /* User ID that owns the apps */
-       gid_t gid;           /* Group ID that owns the apps */
-
-       /* App ABI */
-       uint32_t bits_per_long;
-       uint32_t uint8_t_alignment;
-       uint32_t uint16_t_alignment;
-       uint32_t uint32_t_alignment;
-       uint32_t uint64_t_alignment;
-       uint32_t long_alignment;
-       int byte_order;         /* BIG_ENDIAN or LITTLE_ENDIAN */
-
-       int compatible; /* If the lttng-ust tracer version does not match the
-                                          supported version of the session daemon, this flag is
-                                          set to 0 (NOT compatible) else 1. */
-       struct lttng_ust_abi_tracer_version version;
-       uint32_t v_major;    /* Version major number */
-       uint32_t v_minor;    /* Version minor number */
-       /* Extra for the NULL byte. */
-       char name[UST_APP_PROCNAME_LEN + 1];
-       /* Type of buffer this application uses. */
-       enum lttng_buffer_type buffer_type;
-       struct lttng_ht *sessions;
-       struct lttng_ht_node_ulong pid_n;
-       struct lttng_ht_node_ulong sock_n;
-       struct lttng_ht_node_ulong notify_sock_n;
-       /*
-        * This is a list of ust app session that, once the app is going into
-        * teardown mode, in the RCU call, each node in this list is removed and
-        * deleted.
-        *
-        * Element of the list are added when an application unregisters after each
-        * ht_del of ust_app_session associated to this app. This list is NOT used
-        * when a session is destroyed.
-        */
-       struct cds_list_head teardown_head;
-       /*
-        * Hash table containing ust_app_channel indexed by channel objd.
-        */
-       struct lttng_ht *ust_objd;
-       /*
-        * Hash table containing ust_app_session indexed by objd.
-        */
-       struct lttng_ht *ust_sessions_objd;
-
-       /*
-        * If this application is of the agent domain and this is non negative then
-        * a lookup MUST be done to acquire a read side reference to the
-        * corresponding agent app object. If the lookup fails, this should be set
-        * to a negative value indicating that the agent application is gone.
-        */
-       int agent_app_sock;
-       /*
-        * Time at which the app is registred.
-        * Used for path creation
-        */
-       time_t registration_time;
-       /*
-        * Event notifier
-        */
-       struct {
-               /*
-                * Handle to the lttng_ust object representing the event
-                * notifier group.
-                */
-               struct lttng_ust_abi_object_data *object;
-               struct lttng_pipe *event_pipe;
-               struct lttng_ust_abi_object_data *counter;
-               struct lttng_ust_abi_object_data **counter_cpu;
-               int nr_counter_cpu;
-       } event_notifier_group;
-       /*
-        * Hashtable indexing the application's event notifier rule's
-        * (ust_app_event_notifier_rule) by their token's value.
-        */
-       struct lttng_ht *token_to_event_notifier_rule_ht;
-};
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-int ust_app_register(struct ust_register_msg *msg, int sock);
-int ust_app_register_done(struct ust_app *app);
-int ust_app_version(struct ust_app *app);
-void ust_app_unregister(int sock);
-int ust_app_start_trace_all(struct ltt_ust_session *usess);
-int ust_app_stop_trace_all(struct ltt_ust_session *usess);
-int ust_app_destroy_trace_all(struct ltt_ust_session *usess);
-int ust_app_list_events(struct lttng_event **events);
-int ust_app_list_event_fields(struct lttng_event_field **fields);
-int ust_app_create_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
-int ust_app_disable_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan);
-int ust_app_enable_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan);
-int ust_app_enable_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
-int ust_app_disable_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
-int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx);
-void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app);
-void ust_app_global_update_all(struct ltt_ust_session *usess);
-void ust_app_global_update_event_notifier_rules(struct ust_app *app);
-void ust_app_global_update_all_event_notifier_rules(void);
-
-void ust_app_clean_list(void);
-int ust_app_ht_alloc(void);
-struct ust_app *ust_app_find_by_pid(pid_t pid);
-struct ust_app_stream *ust_app_alloc_stream(void);
-int ust_app_recv_registration(int sock, struct ust_register_msg *msg);
-int ust_app_recv_notify(int sock);
-void ust_app_add(struct ust_app *app);
-struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock);
-void ust_app_notify_sock_unregister(int sock);
-ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
-               struct consumer_socket *socket, int send_zero_data);
-void ust_app_destroy(struct ust_app *app);
-enum lttng_error_code ust_app_snapshot_record(
-               const struct ltt_ust_session *usess,
-               const struct consumer_output *output, int wait,
-               uint64_t nb_packets_per_stream);
-uint64_t ust_app_get_size_one_more_packet_per_stream(
-               const struct ltt_ust_session *usess, uint64_t cur_nr_packets);
-struct ust_app *ust_app_find_by_sock(int sock);
-int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
-               struct cds_list_head *buffer_reg_uid_list,
-               struct consumer_output *consumer, uint64_t uchan_id,
-               int overwrite, uint64_t *discarded, uint64_t *lost);
-int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan,
-               struct consumer_output *consumer,
-               int overwrite, uint64_t *discarded, uint64_t *lost);
-int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess);
-enum lttng_error_code ust_app_rotate_session(struct ltt_session *session);
-enum lttng_error_code ust_app_create_channel_subdirectories(
-               const struct ltt_ust_session *session);
-int ust_app_release_object(struct ust_app *app,
-               struct lttng_ust_abi_object_data *data);
-enum lttng_error_code ust_app_clear_session(struct ltt_session *session);
-enum lttng_error_code ust_app_open_packets(struct ltt_session *session);
-
-int ust_app_setup_event_notifier_group(struct ust_app *app);
-
-static inline
-int ust_app_supported(void)
-{
-       return 1;
-}
-
-bool ust_app_supports_notifiers(const struct ust_app *app);
-bool ust_app_supports_counters(const struct ust_app *app);
-
-#else /* HAVE_LIBLTTNG_UST_CTL */
-
-static inline
-int ust_app_destroy_trace_all(struct ltt_ust_session *usess)
-{
-       return 0;
-}
-static inline
-int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
-{
-       return 0;
-}
-static inline
-int ust_app_start_trace_all(struct ltt_ust_session *usess)
-{
-       return 0;
-}
-static inline
-int ust_app_stop_trace_all(struct ltt_ust_session *usess)
-{
-       return 0;
-}
-static inline
-int ust_app_list_events(struct lttng_event **events)
-{
-       return -ENOSYS;
-}
-static inline
-int ust_app_list_event_fields(struct lttng_event_field **fields)
-{
-       return -ENOSYS;
-}
-static inline
-int ust_app_register(struct ust_register_msg *msg, int sock)
-{
-       return -ENOSYS;
-}
-static inline
-int ust_app_register_done(struct ust_app *app)
-{
-       return -ENOSYS;
-}
-static inline
-int ust_app_version(struct ust_app *app)
-{
-       return -ENOSYS;
-}
-static inline
-void ust_app_unregister(int sock)
-{
-}
-static inline
-void ust_app_clean_list(void)
-{
-}
-static inline
-struct ust_app_list *ust_app_get_list(void)
-{
-       return NULL;
-}
-static inline
-struct ust_app *ust_app_get_by_pid(pid_t pid)
-{
-       return NULL;
-}
-static inline
-int ust_app_ht_alloc(void)
-{
-       return 0;
-}
-static inline
-void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app)
-{}
-static inline
-void ust_app_global_update_event_notifier_rules(struct ust_app *app)
-{}
-static inline
-void ust_app_global_update_all_event_notifier_rules(void)
-{}
-static inline
-int ust_app_setup_event_notifier_group(struct ust_app *app)
-{
-       return 0;
-}
-static inline
-int ust_app_disable_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan)
-{
-       return 0;
-}
-static inline
-int ust_app_enable_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan)
-{
-       return 0;
-}
-static inline
-int ust_app_create_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
-{
-       return 0;
-}
-static inline
-int ust_app_disable_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
-{
-       return 0;
-}
-static inline
-int ust_app_enable_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
-{
-       return 0;
-}
-static inline
-int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx)
-{
-       return 0;
-}
-static inline
-int ust_app_enable_event_pid(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent,
-               pid_t pid)
-{
-       return 0;
-}
-static inline
-int ust_app_recv_registration(int sock, struct ust_register_msg *msg)
-{
-       return 0;
-}
-static inline
-int ust_app_recv_notify(int sock)
-{
-       return 0;
-}
-static inline
-struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
-{
-       return NULL;
-}
-static inline
-void ust_app_add(struct ust_app *app)
-{
-}
-static inline
-void ust_app_notify_sock_unregister(int sock)
-{
-}
-static inline
-ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
-               struct consumer_socket *socket, int send_zero_data)
-{
-       return 0;
-}
-static inline
-void ust_app_destroy(struct ust_app *app)
-{
-       return;
-}
-static inline
-enum lttng_error_code ust_app_snapshot_record(struct ltt_ust_session *usess,
-               const struct consumer_output *output, int wait, uint64_t max_stream_size)
-{
-       return LTTNG_ERR_UNK;
-}
-static inline
-unsigned int ust_app_get_nb_stream(struct ltt_ust_session *usess)
-{
-       return 0;
-}
-static inline
-void ust_app_update_event_notifier_error_count(
-               struct lttng_trigger *lttng_trigger)
-{
-       return;
-}
-static inline
-int ust_app_supported(void)
-{
-       return 0;
-}
-static inline
-bool ust_app_supports_notifiers(const struct ust_app *app)
-{
-       return false;
-}
-static inline
-bool ust_app_supports_counters(const struct ust_app *app)
-{
-       return false;
-}
-static inline
-struct ust_app *ust_app_find_by_sock(int sock)
-{
-       return NULL;
-}
-static inline
-struct ust_app *ust_app_find_by_pid(pid_t pid)
-{
-       return NULL;
-}
-static inline
-uint64_t ust_app_get_size_one_more_packet_per_stream(
-               const struct ltt_ust_session *usess, uint64_t cur_nr_packets) {
-       return 0;
-}
-static inline
-int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
-               struct cds_list_head *buffer_reg_uid_list,
-               struct consumer_output *consumer, int overwrite,
-               uint64_t uchan_id, uint64_t *discarded, uint64_t *lost)
-{
-       return 0;
-}
-
-static inline
-int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan,
-               struct consumer_output *consumer,
-               int overwrite, uint64_t *discarded, uint64_t *lost)
-{
-       return 0;
-}
-
-static inline
-int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess)
-{
-       return 0;
-}
-
-static inline
-enum lttng_error_code ust_app_rotate_session(struct ltt_session *session)
-{
-       return LTTNG_ERR_UNK;
-}
-
-static inline
-enum lttng_error_code ust_app_create_channel_subdirectories(
-               const struct ltt_ust_session *session)
-{
-       return LTTNG_ERR_UNK;
-}
-
-static inline
-int ust_app_release_object(struct ust_app *app, struct lttng_ust_abi_object_data *data)
-{
-       return 0;
-}
-
-static inline
-enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
-{
-       return LTTNG_ERR_UNK;
-}
-
-static inline
-enum lttng_error_code ust_app_open_packets(struct ltt_session *session)
-{
-       return LTTNG_ERR_UNK;
-}
-
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* _LTT_UST_APP_H */
diff --git a/src/bin/lttng-sessiond/ust-app.hpp b/src/bin/lttng-sessiond/ust-app.hpp
new file mode 100644 (file)
index 0000000..0fea4d9
--- /dev/null
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_UST_APP_H
+#define _LTT_UST_APP_H
+
+#include <stdint.h>
+
+#include <common/index-allocator.hpp>
+#include <common/uuid.hpp>
+
+#include "trace-ust.hpp"
+#include "ust-registry.hpp"
+#include "session.hpp"
+
+#define UST_APP_EVENT_LIST_SIZE 32
+
+/* Process name (short). */
+#define UST_APP_PROCNAME_LEN   16
+
+struct lttng_bytecode;
+struct lttng_ust_filter_bytecode;
+
+extern int the_ust_consumerd64_fd, the_ust_consumerd32_fd;
+
+/*
+ * Object used to close the notify socket in a call_rcu(). Since the
+ * application might not be found, we need an independant object containing the
+ * notify socket fd.
+ */
+struct ust_app_notify_sock_obj {
+       int fd;
+       struct rcu_head head;
+};
+
+struct ust_app_ht_key {
+       const char *name;
+       const struct lttng_bytecode *filter;
+       enum lttng_ust_abi_loglevel_type loglevel_type;
+       const struct lttng_event_exclusion *exclusion;
+};
+
+/*
+ * Application registration data structure.
+ */
+struct ust_register_msg {
+       enum lttng_ust_ctl_socket_type type;
+       uint32_t major;
+       uint32_t minor;
+       uint32_t abi_major;
+       uint32_t abi_minor;
+       pid_t pid;
+       pid_t ppid;
+       uid_t uid;
+       gid_t gid;
+       uint32_t bits_per_long;
+       uint32_t uint8_t_alignment;
+       uint32_t uint16_t_alignment;
+       uint32_t uint32_t_alignment;
+       uint32_t uint64_t_alignment;
+       uint32_t long_alignment;
+       int byte_order;         /* BIG_ENDIAN or LITTLE_ENDIAN */
+       char name[LTTNG_UST_ABI_PROCNAME_LEN];
+};
+
+/*
+ * Global applications HT used by the session daemon. This table is indexed by
+ * PID using the pid_n node and pid value of an ust_app.
+ */
+extern struct lttng_ht *ust_app_ht;
+
+/*
+ * Global applications HT used by the session daemon. This table is indexed by
+ * socket using the sock_n node and sock value of an ust_app.
+ *
+ * The 'sock' in question here is the 'command' socket.
+ */
+extern struct lttng_ht *ust_app_ht_by_sock;
+
+/*
+ * Global applications HT used by the session daemon. This table is indexed by
+ * socket using the notify_sock_n node and notify_sock value of an ust_app.
+ */
+extern struct lttng_ht *ust_app_ht_by_notify_sock;
+
+/* Stream list containing ust_app_stream. */
+struct ust_app_stream_list {
+       unsigned int count;
+       struct cds_list_head head;
+};
+
+struct ust_app_ctx {
+       int handle;
+       struct lttng_ust_context_attr ctx;
+       struct lttng_ust_abi_object_data *obj;
+       struct lttng_ht_node_ulong node;
+       struct cds_list_head list;
+};
+
+struct ust_app_event {
+       int enabled;
+       int handle;
+       struct lttng_ust_abi_object_data *obj;
+       struct lttng_ust_abi_event attr;
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+       struct lttng_ht_node_str node;
+       struct lttng_bytecode *filter;
+       struct lttng_event_exclusion *exclusion;
+};
+
+struct ust_app_event_notifier_rule {
+       int enabled;
+       uint64_t error_counter_index;
+       int handle;
+       struct lttng_ust_abi_object_data *obj;
+       /* Holds a strong reference. */
+       struct lttng_trigger *trigger;
+       /* Unique ID returned by the tracer to identify this event notifier. */
+       uint64_t token;
+       struct lttng_ht_node_u64 node;
+       /* The trigger object owns the filter. */
+       const struct lttng_bytecode *filter;
+       /* Owned by this. */
+       struct lttng_event_exclusion *exclusion;
+       /* For delayed reclaim. */
+       struct rcu_head rcu_head;
+};
+
+struct ust_app_stream {
+       int handle;
+       char pathname[PATH_MAX];
+       /* Format is %s_%d respectively channel name and CPU number. */
+       char name[DEFAULT_STREAM_NAME_LEN];
+       struct lttng_ust_abi_object_data *obj;
+       /* Using a list of streams to keep order. */
+       struct cds_list_head list;
+};
+
+struct ust_app_channel {
+       int enabled;
+       int handle;
+       /* Channel and streams were sent to the UST tracer. */
+       int is_sent;
+       /*
+        * Unique key used to identify the channel on the consumer side.
+        * 0 is a reserved 'invalid' value used to indicate that the consumer
+        * does not know about this channel (i.e. an error occurred).
+        */
+       uint64_t key;
+       /* Id of the tracing channel set on creation. */
+       uint64_t tracing_channel_id;
+       /* Number of stream that this channel is expected to receive. */
+       unsigned int expected_stream_count;
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+       struct lttng_ust_abi_object_data *obj;
+       struct lttng_ust_ctl_consumer_channel_attr attr;
+       struct ust_app_stream_list streams;
+       /* Session pointer that owns this object. */
+       struct ust_app_session *session;
+       /*
+        * Contexts are kept in a hash table for fast lookup and in an ordered list
+        * so we are able to enable them on the tracer side in the same order the
+        * user added them.
+        */
+       struct lttng_ht *ctx;
+       struct cds_list_head ctx_list;
+
+       struct lttng_ht *events;
+       uint64_t tracefile_size;
+       uint64_t tracefile_count;
+       uint64_t monitor_timer_interval;
+       /*
+        * Node indexed by channel name in the channels' hash table of a session.
+        */
+       struct lttng_ht_node_str node;
+       /*
+        * Node indexed by UST channel object descriptor (handle). Stored in the
+        * ust_objd hash table in the ust_app object.
+        */
+       struct lttng_ht_node_ulong ust_objd_node;
+       /* For delayed reclaim */
+       struct rcu_head rcu_head;
+};
+
+struct ust_app_session {
+       /*
+        * Lock protecting this session's ust app interaction. Held
+        * across command send/recv to/from app. Never nests within the
+        * session registry lock.
+        */
+       pthread_mutex_t lock;
+
+       int enabled;
+       /* started: has the session been in started state at any time ? */
+       int started;  /* allows detection of start vs restart. */
+       int handle;   /* used has unique identifier for app session */
+
+       bool deleted;   /* Session deleted flag. Check with lock held. */
+
+       /*
+        * Tracing session ID. Multiple ust app session can have the same tracing
+        * session id making this value NOT unique to the object.
+        */
+       uint64_t tracing_id;
+       uint64_t id;    /* Unique session identifier */
+       struct lttng_ht *channels; /* Registered channels */
+       struct lttng_ht_node_u64 node;
+       /*
+        * Node indexed by UST session object descriptor (handle). Stored in the
+        * ust_sessions_objd hash table in the ust_app object.
+        */
+       struct lttng_ht_node_ulong ust_objd_node;
+       /* Starts with 'ust'; no leading slash. */
+       char path[PATH_MAX];
+       /* UID/GID of the application owning the session */
+       struct lttng_credentials real_credentials;
+       /* Effective UID and GID. Same as the tracing session. */
+       struct lttng_credentials effective_credentials;
+       struct cds_list_head teardown_node;
+       /*
+        * Once at least *one* session is created onto the application, the
+        * corresponding consumer is set so we can use it on unregistration.
+        */
+       struct consumer_output *consumer;
+       enum lttng_buffer_type buffer_type;
+       /* ABI of the session. Same value as the application. */
+       uint32_t bits_per_long;
+       /* For delayed reclaim */
+       struct rcu_head rcu_head;
+       /* If the channel's streams have to be outputed or not. */
+       unsigned int output_traces;
+       unsigned int live_timer_interval;       /* usec */
+
+       /* Metadata channel attributes. */
+       struct lttng_ust_ctl_consumer_channel_attr metadata_attr;
+
+       char root_shm_path[PATH_MAX];
+       char shm_path[PATH_MAX];
+};
+
+/*
+ * Registered traceable applications. Libust registers to the session daemon
+ * and a linked list is kept of all running traceable app.
+ */
+struct ust_app {
+       int sock;
+       pthread_mutex_t sock_lock;      /* Protects sock protocol. */
+
+       int notify_sock;
+       pid_t pid;
+       pid_t ppid;
+       uid_t uid;           /* User ID that owns the apps */
+       gid_t gid;           /* Group ID that owns the apps */
+
+       /* App ABI */
+       uint32_t bits_per_long;
+       uint32_t uint8_t_alignment;
+       uint32_t uint16_t_alignment;
+       uint32_t uint32_t_alignment;
+       uint32_t uint64_t_alignment;
+       uint32_t long_alignment;
+       int byte_order;         /* BIG_ENDIAN or LITTLE_ENDIAN */
+
+       int compatible; /* If the lttng-ust tracer version does not match the
+                                          supported version of the session daemon, this flag is
+                                          set to 0 (NOT compatible) else 1. */
+       struct lttng_ust_abi_tracer_version version;
+       uint32_t v_major;    /* Version major number */
+       uint32_t v_minor;    /* Version minor number */
+       /* Extra for the NULL byte. */
+       char name[UST_APP_PROCNAME_LEN + 1];
+       /* Type of buffer this application uses. */
+       enum lttng_buffer_type buffer_type;
+       struct lttng_ht *sessions;
+       struct lttng_ht_node_ulong pid_n;
+       struct lttng_ht_node_ulong sock_n;
+       struct lttng_ht_node_ulong notify_sock_n;
+       /*
+        * This is a list of ust app session that, once the app is going into
+        * teardown mode, in the RCU call, each node in this list is removed and
+        * deleted.
+        *
+        * Element of the list are added when an application unregisters after each
+        * ht_del of ust_app_session associated to this app. This list is NOT used
+        * when a session is destroyed.
+        */
+       struct cds_list_head teardown_head;
+       /*
+        * Hash table containing ust_app_channel indexed by channel objd.
+        */
+       struct lttng_ht *ust_objd;
+       /*
+        * Hash table containing ust_app_session indexed by objd.
+        */
+       struct lttng_ht *ust_sessions_objd;
+
+       /*
+        * If this application is of the agent domain and this is non negative then
+        * a lookup MUST be done to acquire a read side reference to the
+        * corresponding agent app object. If the lookup fails, this should be set
+        * to a negative value indicating that the agent application is gone.
+        */
+       int agent_app_sock;
+       /*
+        * Time at which the app is registred.
+        * Used for path creation
+        */
+       time_t registration_time;
+       /*
+        * Event notifier
+        */
+       struct {
+               /*
+                * Handle to the lttng_ust object representing the event
+                * notifier group.
+                */
+               struct lttng_ust_abi_object_data *object;
+               struct lttng_pipe *event_pipe;
+               struct lttng_ust_abi_object_data *counter;
+               struct lttng_ust_abi_object_data **counter_cpu;
+               int nr_counter_cpu;
+       } event_notifier_group;
+       /*
+        * Hashtable indexing the application's event notifier rule's
+        * (ust_app_event_notifier_rule) by their token's value.
+        */
+       struct lttng_ht *token_to_event_notifier_rule_ht;
+};
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+int ust_app_register(struct ust_register_msg *msg, int sock);
+int ust_app_register_done(struct ust_app *app);
+int ust_app_version(struct ust_app *app);
+void ust_app_unregister(int sock);
+int ust_app_start_trace_all(struct ltt_ust_session *usess);
+int ust_app_stop_trace_all(struct ltt_ust_session *usess);
+int ust_app_destroy_trace_all(struct ltt_ust_session *usess);
+int ust_app_list_events(struct lttng_event **events);
+int ust_app_list_event_fields(struct lttng_event_field **fields);
+int ust_app_create_event_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
+int ust_app_disable_channel_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan);
+int ust_app_enable_channel_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan);
+int ust_app_enable_event_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
+int ust_app_disable_event_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
+int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx);
+void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app);
+void ust_app_global_update_all(struct ltt_ust_session *usess);
+void ust_app_global_update_event_notifier_rules(struct ust_app *app);
+void ust_app_global_update_all_event_notifier_rules(void);
+
+void ust_app_clean_list(void);
+int ust_app_ht_alloc(void);
+struct ust_app *ust_app_find_by_pid(pid_t pid);
+struct ust_app_stream *ust_app_alloc_stream(void);
+int ust_app_recv_registration(int sock, struct ust_register_msg *msg);
+int ust_app_recv_notify(int sock);
+void ust_app_add(struct ust_app *app);
+struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock);
+void ust_app_notify_sock_unregister(int sock);
+ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
+               struct consumer_socket *socket, int send_zero_data);
+void ust_app_destroy(struct ust_app *app);
+enum lttng_error_code ust_app_snapshot_record(
+               const struct ltt_ust_session *usess,
+               const struct consumer_output *output, int wait,
+               uint64_t nb_packets_per_stream);
+uint64_t ust_app_get_size_one_more_packet_per_stream(
+               const struct ltt_ust_session *usess, uint64_t cur_nr_packets);
+struct ust_app *ust_app_find_by_sock(int sock);
+int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
+               struct cds_list_head *buffer_reg_uid_list,
+               struct consumer_output *consumer, uint64_t uchan_id,
+               int overwrite, uint64_t *discarded, uint64_t *lost);
+int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan,
+               struct consumer_output *consumer,
+               int overwrite, uint64_t *discarded, uint64_t *lost);
+int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess);
+enum lttng_error_code ust_app_rotate_session(struct ltt_session *session);
+enum lttng_error_code ust_app_create_channel_subdirectories(
+               const struct ltt_ust_session *session);
+int ust_app_release_object(struct ust_app *app,
+               struct lttng_ust_abi_object_data *data);
+enum lttng_error_code ust_app_clear_session(struct ltt_session *session);
+enum lttng_error_code ust_app_open_packets(struct ltt_session *session);
+
+int ust_app_setup_event_notifier_group(struct ust_app *app);
+
+static inline
+int ust_app_supported(void)
+{
+       return 1;
+}
+
+bool ust_app_supports_notifiers(const struct ust_app *app);
+bool ust_app_supports_counters(const struct ust_app *app);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+static inline
+int ust_app_destroy_trace_all(struct ltt_ust_session *usess)
+{
+       return 0;
+}
+static inline
+int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
+{
+       return 0;
+}
+static inline
+int ust_app_start_trace_all(struct ltt_ust_session *usess)
+{
+       return 0;
+}
+static inline
+int ust_app_stop_trace_all(struct ltt_ust_session *usess)
+{
+       return 0;
+}
+static inline
+int ust_app_list_events(struct lttng_event **events)
+{
+       return -ENOSYS;
+}
+static inline
+int ust_app_list_event_fields(struct lttng_event_field **fields)
+{
+       return -ENOSYS;
+}
+static inline
+int ust_app_register(struct ust_register_msg *msg, int sock)
+{
+       return -ENOSYS;
+}
+static inline
+int ust_app_register_done(struct ust_app *app)
+{
+       return -ENOSYS;
+}
+static inline
+int ust_app_version(struct ust_app *app)
+{
+       return -ENOSYS;
+}
+static inline
+void ust_app_unregister(int sock)
+{
+}
+static inline
+void ust_app_clean_list(void)
+{
+}
+static inline
+struct ust_app_list *ust_app_get_list(void)
+{
+       return NULL;
+}
+static inline
+struct ust_app *ust_app_get_by_pid(pid_t pid)
+{
+       return NULL;
+}
+static inline
+int ust_app_ht_alloc(void)
+{
+       return 0;
+}
+static inline
+void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app)
+{}
+static inline
+void ust_app_global_update_event_notifier_rules(struct ust_app *app)
+{}
+static inline
+void ust_app_global_update_all_event_notifier_rules(void)
+{}
+static inline
+int ust_app_setup_event_notifier_group(struct ust_app *app)
+{
+       return 0;
+}
+static inline
+int ust_app_disable_channel_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan)
+{
+       return 0;
+}
+static inline
+int ust_app_enable_channel_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan)
+{
+       return 0;
+}
+static inline
+int ust_app_create_event_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
+{
+       return 0;
+}
+static inline
+int ust_app_disable_event_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
+{
+       return 0;
+}
+static inline
+int ust_app_enable_event_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
+{
+       return 0;
+}
+static inline
+int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx)
+{
+       return 0;
+}
+static inline
+int ust_app_enable_event_pid(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent,
+               pid_t pid)
+{
+       return 0;
+}
+static inline
+int ust_app_recv_registration(int sock, struct ust_register_msg *msg)
+{
+       return 0;
+}
+static inline
+int ust_app_recv_notify(int sock)
+{
+       return 0;
+}
+static inline
+struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
+{
+       return NULL;
+}
+static inline
+void ust_app_add(struct ust_app *app)
+{
+}
+static inline
+void ust_app_notify_sock_unregister(int sock)
+{
+}
+static inline
+ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
+               struct consumer_socket *socket, int send_zero_data)
+{
+       return 0;
+}
+static inline
+void ust_app_destroy(struct ust_app *app)
+{
+       return;
+}
+static inline
+enum lttng_error_code ust_app_snapshot_record(struct ltt_ust_session *usess,
+               const struct consumer_output *output, int wait, uint64_t max_stream_size)
+{
+       return LTTNG_ERR_UNK;
+}
+static inline
+unsigned int ust_app_get_nb_stream(struct ltt_ust_session *usess)
+{
+       return 0;
+}
+static inline
+void ust_app_update_event_notifier_error_count(
+               struct lttng_trigger *lttng_trigger)
+{
+       return;
+}
+static inline
+int ust_app_supported(void)
+{
+       return 0;
+}
+static inline
+bool ust_app_supports_notifiers(const struct ust_app *app)
+{
+       return false;
+}
+static inline
+bool ust_app_supports_counters(const struct ust_app *app)
+{
+       return false;
+}
+static inline
+struct ust_app *ust_app_find_by_sock(int sock)
+{
+       return NULL;
+}
+static inline
+struct ust_app *ust_app_find_by_pid(pid_t pid)
+{
+       return NULL;
+}
+static inline
+uint64_t ust_app_get_size_one_more_packet_per_stream(
+               const struct ltt_ust_session *usess, uint64_t cur_nr_packets) {
+       return 0;
+}
+static inline
+int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
+               struct cds_list_head *buffer_reg_uid_list,
+               struct consumer_output *consumer, int overwrite,
+               uint64_t uchan_id, uint64_t *discarded, uint64_t *lost)
+{
+       return 0;
+}
+
+static inline
+int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
+               struct ltt_ust_channel *uchan,
+               struct consumer_output *consumer,
+               int overwrite, uint64_t *discarded, uint64_t *lost)
+{
+       return 0;
+}
+
+static inline
+int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess)
+{
+       return 0;
+}
+
+static inline
+enum lttng_error_code ust_app_rotate_session(struct ltt_session *session)
+{
+       return LTTNG_ERR_UNK;
+}
+
+static inline
+enum lttng_error_code ust_app_create_channel_subdirectories(
+               const struct ltt_ust_session *session)
+{
+       return LTTNG_ERR_UNK;
+}
+
+static inline
+int ust_app_release_object(struct ust_app *app, struct lttng_ust_abi_object_data *data)
+{
+       return 0;
+}
+
+static inline
+enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
+{
+       return LTTNG_ERR_UNK;
+}
+
+static inline
+enum lttng_error_code ust_app_open_packets(struct ltt_session *session)
+{
+       return LTTNG_ERR_UNK;
+}
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* _LTT_UST_APP_H */
diff --git a/src/bin/lttng-sessiond/ust-clock.h b/src/bin/lttng-sessiond/ust-clock.h
deleted file mode 100644 (file)
index 91cbbe6..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2010 Pierre-Marc Fournier
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _UST_CLOCK_H
-#define _UST_CLOCK_H
-
-#include <common/compat/time.h>
-#include <sys/time.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <urcu/system.h>
-#include <urcu/arch.h>
-#include <lttng/ust-clock.h>
-
-#include <common/uuid.h>
-
-static __inline__
-uint64_t trace_clock_read64(void)
-{
-       uint64_t clock_value = 0;
-       lttng_ust_clock_read64_function read64_cb;
-
-       if (lttng_ust_trace_clock_get_read64_cb(&read64_cb)) {
-               goto end;
-       }
-
-       clock_value = read64_cb();
-end:
-       return clock_value;
-}
-
-static __inline__
-uint64_t trace_clock_freq(void)
-{
-       uint64_t frequency = 0;
-       lttng_ust_clock_freq_function get_freq_cb;
-
-       if (lttng_ust_trace_clock_get_freq_cb(&get_freq_cb)) {
-               goto end;
-       }
-
-       frequency = get_freq_cb();
-end:
-       return frequency;
-}
-
-static __inline__
-int trace_clock_uuid(char *uuid)
-{
-       int ret;
-       lttng_ust_clock_uuid_function get_uuid_cb;
-
-       if (lttng_ust_trace_clock_get_uuid_cb(&get_uuid_cb)) {
-               ret = -EINVAL;
-               goto end;
-       }
-
-       ret = get_uuid_cb(uuid);
-end:
-       return ret;
-
-}
-
-static __inline__
-const char *trace_clock_name(void)
-{
-       const char *name;
-       lttng_ust_clock_name_function get_name_cb;
-
-       if (lttng_ust_trace_clock_get_name_cb(&get_name_cb)) {
-               name = NULL;
-               goto end;
-       }
-
-       name = get_name_cb();
-end:
-       return name;
-}
-
-static __inline__
-const char *trace_clock_description(void)
-{
-       const char *description;
-       lttng_ust_clock_description_function get_description_cb;
-
-       if (lttng_ust_trace_clock_get_description_cb(&get_description_cb)) {
-               description = NULL;
-               goto end;
-       }
-
-       description = get_description_cb();
-end:
-       return description;
-}
-
-#endif /* _UST_CLOCK_H */
diff --git a/src/bin/lttng-sessiond/ust-clock.hpp b/src/bin/lttng-sessiond/ust-clock.hpp
new file mode 100644 (file)
index 0000000..3807f40
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 Pierre-Marc Fournier
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _UST_CLOCK_H
+#define _UST_CLOCK_H
+
+#include <common/compat/time.hpp>
+#include <sys/time.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <urcu/system.h>
+#include <urcu/arch.h>
+#include <lttng/ust-clock.h>
+
+#include <common/uuid.hpp>
+
+static __inline__
+uint64_t trace_clock_read64(void)
+{
+       uint64_t clock_value = 0;
+       lttng_ust_clock_read64_function read64_cb;
+
+       if (lttng_ust_trace_clock_get_read64_cb(&read64_cb)) {
+               goto end;
+       }
+
+       clock_value = read64_cb();
+end:
+       return clock_value;
+}
+
+static __inline__
+uint64_t trace_clock_freq(void)
+{
+       uint64_t frequency = 0;
+       lttng_ust_clock_freq_function get_freq_cb;
+
+       if (lttng_ust_trace_clock_get_freq_cb(&get_freq_cb)) {
+               goto end;
+       }
+
+       frequency = get_freq_cb();
+end:
+       return frequency;
+}
+
+static __inline__
+int trace_clock_uuid(char *uuid)
+{
+       int ret;
+       lttng_ust_clock_uuid_function get_uuid_cb;
+
+       if (lttng_ust_trace_clock_get_uuid_cb(&get_uuid_cb)) {
+               ret = -EINVAL;
+               goto end;
+       }
+
+       ret = get_uuid_cb(uuid);
+end:
+       return ret;
+
+}
+
+static __inline__
+const char *trace_clock_name(void)
+{
+       const char *name;
+       lttng_ust_clock_name_function get_name_cb;
+
+       if (lttng_ust_trace_clock_get_name_cb(&get_name_cb)) {
+               name = NULL;
+               goto end;
+       }
+
+       name = get_name_cb();
+end:
+       return name;
+}
+
+static __inline__
+const char *trace_clock_description(void)
+{
+       const char *description;
+       lttng_ust_clock_description_function get_description_cb;
+
+       if (lttng_ust_trace_clock_get_description_cb(&get_description_cb)) {
+               description = NULL;
+               goto end;
+       }
+
+       description = get_description_cb();
+end:
+       return description;
+}
+
+#endif /* _UST_CLOCK_H */
index a68c5d96dc99070304357d3a723b136191868ecc..1741ce169262566a751e722bd9b206448e01ea9a 100644 (file)
 #include <unistd.h>
 #include <inttypes.h>
 
-#include <common/compat/errno.h>
-#include <common/common.h>
-#include <common/consumer/consumer.h>
-#include <common/defaults.h>
-
-#include "consumer.h"
-#include "health-sessiond.h"
-#include "ust-consumer.h"
-#include "lttng-ust-error.h"
-#include "buffer-registry.h"
-#include "session.h"
-#include "lttng-sessiond.h"
+#include <common/compat/errno.hpp>
+#include <common/common.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/defaults.hpp>
+
+#include "consumer.hpp"
+#include "health-sessiond.hpp"
+#include "ust-consumer.hpp"
+#include "lttng-ust-error.hpp"
+#include "buffer-registry.hpp"
+#include "session.hpp"
+#include "lttng-sessiond.hpp"
 
 /*
  * Send a single channel to the consumer using command ASK_CHANNEL_CREATION.
diff --git a/src/bin/lttng-sessiond/ust-consumer.h b/src/bin/lttng-sessiond/ust-consumer.h
deleted file mode 100644 (file)
index d4213e4..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _UST_CONSUMER_H
-#define _UST_CONSUMER_H
-
-#include "consumer.h"
-#include "ust-app.h"
-#include <stdint.h>
-#include <common/trace-chunk.h>
-
-int ust_consumer_ask_channel(struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan,
-               struct consumer_output *consumer,
-               struct consumer_socket *socket,
-               struct ust_registry_session *registry,
-               struct lttng_trace_chunk *trace_chunk);
-
-int ust_consumer_get_channel(struct consumer_socket *socket,
-               struct ust_app_channel *ua_chan);
-
-int ust_consumer_destroy_channel(struct consumer_socket *socket,
-               struct ust_app_channel *ua_chan);
-
-int ust_consumer_send_stream_to_ust(struct ust_app *app,
-               struct ust_app_channel *channel, struct ust_app_stream *stream);
-
-int ust_consumer_send_channel_to_ust(struct ust_app *app,
-               struct ust_app_session *ua_sess, struct ust_app_channel *channel);
-
-#if HAVE_LIBLTTNG_UST_CTL
-int ust_consumer_metadata_request(struct consumer_socket *sock);
-#else
-static inline
-int ust_consumer_metadata_request(struct consumer_socket *sock)
-{
-       return -ENOSYS;
-}
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* _UST_CONSUMER_H */
diff --git a/src/bin/lttng-sessiond/ust-consumer.hpp b/src/bin/lttng-sessiond/ust-consumer.hpp
new file mode 100644 (file)
index 0000000..e0123cb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _UST_CONSUMER_H
+#define _UST_CONSUMER_H
+
+#include "consumer.hpp"
+#include "ust-app.hpp"
+#include <stdint.h>
+#include <common/trace-chunk.hpp>
+
+int ust_consumer_ask_channel(struct ust_app_session *ua_sess,
+               struct ust_app_channel *ua_chan,
+               struct consumer_output *consumer,
+               struct consumer_socket *socket,
+               struct ust_registry_session *registry,
+               struct lttng_trace_chunk *trace_chunk);
+
+int ust_consumer_get_channel(struct consumer_socket *socket,
+               struct ust_app_channel *ua_chan);
+
+int ust_consumer_destroy_channel(struct consumer_socket *socket,
+               struct ust_app_channel *ua_chan);
+
+int ust_consumer_send_stream_to_ust(struct ust_app *app,
+               struct ust_app_channel *channel, struct ust_app_stream *stream);
+
+int ust_consumer_send_channel_to_ust(struct ust_app *app,
+               struct ust_app_session *ua_sess, struct ust_app_channel *channel);
+
+#if HAVE_LIBLTTNG_UST_CTL
+int ust_consumer_metadata_request(struct consumer_socket *sock);
+#else
+static inline
+int ust_consumer_metadata_request(struct consumer_socket *sock)
+{
+       return -ENOSYS;
+}
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* _UST_CONSUMER_H */
diff --git a/src/bin/lttng-sessiond/ust-ctl-internal.h b/src/bin/lttng-sessiond/ust-ctl-internal.h
deleted file mode 100644 (file)
index 610aa7f..0000000
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_UST_CTL_INTERNAL_H
-#define LTTNG_UST_CTL_INTERNAL_H
-
-#include <sys/types.h>
-#include <limits.h>
-
-#include "lttng-ust-abi.h"
-
-#ifndef LTTNG_UST_UUID_LEN
-#define LTTNG_UST_UUID_LEN     16
-#endif
-
-/* Default unix socket path */
-#define LTTNG_UST_SOCK_FILENAME                                        \
-       "lttng-ust-sock-"                                       \
-       __ust_stringify(LTTNG_UST_ABI_MAJOR_VERSION_OLDEST_COMPATIBLE)
-
-/*
- * Shared memory files path are automatically related to shm root, e.g.
- * /dev/shm under linux.
- */
-#define LTTNG_UST_WAIT_FILENAME                                        \
-       "lttng-ust-wait-"                                       \
-       __ust_stringify(LTTNG_UST_ABI_MAJOR_VERSION_OLDEST_COMPATIBLE)
-
-struct lttng_ust_shm_handle;
-struct lttng_ust_lib_ring_buffer;
-
-struct lttng_ust_ctl_consumer_channel_attr {
-       enum lttng_ust_abi_chan_type type;
-       uint64_t subbuf_size;                   /* bytes */
-       uint64_t num_subbuf;                    /* power of 2 */
-       int overwrite;                          /* 1: overwrite, 0: discard */
-       unsigned int switch_timer_interval;     /* usec */
-       unsigned int read_timer_interval;       /* usec */
-       enum lttng_ust_abi_output output;       /* splice, mmap */
-       uint32_t chan_id;                       /* channel ID */
-       unsigned char uuid[LTTNG_UST_UUID_LEN]; /* Trace session unique ID */
-       int64_t blocking_timeout;                       /* Blocking timeout (usec) */
-} LTTNG_PACKED;
-
-/*
- * API used by sessiond.
- */
-
-struct lttng_ust_context_attr {
-       enum lttng_ust_abi_context_type ctx;
-       union {
-               struct lttng_ust_abi_perf_counter_ctx perf_counter;
-               struct {
-                       char *provider_name;
-                       char *ctx_name;
-               } app_ctx;
-       } u;
-};
-
-/*
- * Error values: all the following functions return:
- * >= 0: Success (LTTNG_UST_OK)
- * < 0: error code.
- */
-int lttng_ust_ctl_register_done(int sock);
-int lttng_ust_ctl_create_session(int sock);
-int lttng_ust_ctl_create_event(int sock, struct lttng_ust_abi_event *ev,
-               struct lttng_ust_abi_object_data *channel_data,
-               struct lttng_ust_abi_object_data **event_data);
-int lttng_ust_ctl_add_context(int sock, struct lttng_ust_context_attr *ctx,
-               struct lttng_ust_abi_object_data *obj_data,
-               struct lttng_ust_abi_object_data **context_data);
-int lttng_ust_ctl_set_filter(int sock, struct lttng_ust_abi_filter_bytecode *bytecode,
-               struct lttng_ust_abi_object_data *obj_data);
-int lttng_ust_ctl_set_capture(int sock, struct lttng_ust_abi_capture_bytecode *bytecode,
-               struct lttng_ust_abi_object_data *obj_data);
-int lttng_ust_ctl_set_exclusion(int sock, struct lttng_ust_abi_event_exclusion *exclusion,
-               struct lttng_ust_abi_object_data *obj_data);
-
-int lttng_ust_ctl_enable(int sock, struct lttng_ust_abi_object_data *object);
-int lttng_ust_ctl_disable(int sock, struct lttng_ust_abi_object_data *object);
-int lttng_ust_ctl_start_session(int sock, int handle);
-int lttng_ust_ctl_stop_session(int sock, int handle);
-
-/*
- * lttng_ust_ctl_create_event notifier_group creates a event notifier group. It
- * establishes the connection with the application by providing a file
- * descriptor of the pipe to be used by the application when a event notifier
- * of that group is fired. It returns a handle to be used when creating event
- * notifier in that group.
- */
-int lttng_ust_ctl_create_event_notifier_group(int sock, int pipe_fd,
-               struct lttng_ust_abi_object_data **event_notifier_group);
-
-/*
- * lttng_ust_ctl_create_event notifier creates a event notifier in a event notifier
- * group giving a event notifier description and a event notifier group handle.
- * It returns a event notifier handle to be used when enabling the event
- * notifier, attaching filter, attaching exclusion, and disabling the event
- * notifier.
- */
-int lttng_ust_ctl_create_event_notifier(int sock,
-               struct lttng_ust_abi_event_notifier *event_notifier,
-               struct lttng_ust_abi_object_data *event_notifier_group,
-               struct lttng_ust_abi_object_data **event_notifier_data);
-
-/*
- * lttng_ust_ctl_tracepoint_list returns a tracepoint list handle, or negative
- * error value.
- */
-int lttng_ust_ctl_tracepoint_list(int sock);
-
-/*
- * lttng_ust_ctl_tracepoint_list_get is used to iterate on the tp list
- * handle. End is iteration is reached when -LTTNG_UST_ERR_NOENT is
- * returned.
- */
-int lttng_ust_ctl_tracepoint_list_get(int sock, int tp_list_handle,
-               struct lttng_ust_abi_tracepoint_iter *iter);
-
-/*
- * lttng_ust_ctl_tracepoint_field_list returns a tracepoint field list handle,
- * or negative error value.
- */
-int lttng_ust_ctl_tracepoint_field_list(int sock);
-
-/*
- * lttng_ust_ctl_tracepoint_field_list_get is used to iterate on the tp field
- * list handle. End is iteration is reached when -LTTNG_UST_ERR_NOENT is
- * returned.
- */
-int lttng_ust_ctl_tracepoint_field_list_get(int sock, int tp_field_list_handle,
-               struct lttng_ust_abi_field_iter *iter);
-
-int lttng_ust_ctl_tracer_version(int sock, struct lttng_ust_abi_tracer_version *v);
-int lttng_ust_ctl_wait_quiescent(int sock);
-
-int lttng_ust_ctl_sock_flush_buffer(int sock, struct lttng_ust_abi_object_data *object);
-
-int lttng_ust_ctl_calibrate(int sock, struct lttng_ust_abi_calibrate *calibrate);
-
-/* Release object created by members of this API. */
-int lttng_ust_ctl_release_object(int sock, struct lttng_ust_abi_object_data *data);
-/* Release handle returned by create session. */
-int lttng_ust_ctl_release_handle(int sock, int handle);
-
-int lttng_ust_ctl_recv_channel_from_consumer(int sock,
-               struct lttng_ust_abi_object_data **channel_data);
-int lttng_ust_ctl_recv_stream_from_consumer(int sock,
-               struct lttng_ust_abi_object_data **stream_data);
-int lttng_ust_ctl_send_channel_to_ust(int sock, int session_handle,
-               struct lttng_ust_abi_object_data *channel_data);
-int lttng_ust_ctl_send_stream_to_ust(int sock,
-               struct lttng_ust_abi_object_data *channel_data,
-               struct lttng_ust_abi_object_data *stream_data);
-
-/*
- * lttng_ust_ctl_duplicate_ust_object_data allocated a new object in "dest" if
- * it succeeds (returns 0). It must be released using
- * lttng_ust_ctl_release_object() and then freed with free().
- */
-int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **dest,
-               struct lttng_ust_abi_object_data *src);
-
-/*
- * API used by consumer.
- */
-
-struct lttng_ust_ctl_consumer_channel;
-struct lttng_ust_ctl_consumer_stream;
-struct lttng_ust_ctl_consumer_channel_attr;
-
-int lttng_ust_ctl_get_nr_stream_per_channel(void);
-
-struct lttng_ust_ctl_consumer_channel *
-       lttng_ust_ctl_create_channel(struct lttng_ust_ctl_consumer_channel_attr *attr,
-               const int *stream_fds, int nr_stream_fds);
-/*
- * Each stream created needs to be destroyed before calling
- * lttng_ust_ctl_destroy_channel().
- */
-void lttng_ust_ctl_destroy_channel(struct lttng_ust_ctl_consumer_channel *chan);
-
-int lttng_ust_ctl_send_channel_to_sessiond(int sock,
-               struct lttng_ust_ctl_consumer_channel *channel);
-int lttng_ust_ctl_channel_close_wait_fd(struct lttng_ust_ctl_consumer_channel *consumer_chan);
-int lttng_ust_ctl_channel_close_wakeup_fd(struct lttng_ust_ctl_consumer_channel *consumer_chan);
-int lttng_ust_ctl_channel_get_wait_fd(struct lttng_ust_ctl_consumer_channel *consumer_chan);
-int lttng_ust_ctl_channel_get_wakeup_fd(struct lttng_ust_ctl_consumer_channel *consumer_chan);
-
-int lttng_ust_ctl_write_metadata_to_channel(
-               struct lttng_ust_ctl_consumer_channel *channel,
-               const char *metadata_str,       /* NOT null-terminated */
-               size_t len);                    /* metadata length */
-ssize_t lttng_ust_ctl_write_one_packet_to_channel(
-               struct lttng_ust_ctl_consumer_channel *channel,
-               const char *metadata_str,       /* NOT null-terminated */
-               size_t len);                    /* metadata length */
-
-/*
- * Send a NULL stream to finish iteration over all streams of a given
- * channel.
- */
-int lttng_ust_ctl_send_stream_to_sessiond(int sock,
-               struct lttng_ust_ctl_consumer_stream *stream);
-int lttng_ust_ctl_stream_close_wait_fd(struct lttng_ust_ctl_consumer_stream *stream);
-int lttng_ust_ctl_stream_close_wakeup_fd(struct lttng_ust_ctl_consumer_stream *stream);
-int lttng_ust_ctl_stream_get_wait_fd(struct lttng_ust_ctl_consumer_stream *stream);
-int lttng_ust_ctl_stream_get_wakeup_fd(struct lttng_ust_ctl_consumer_stream *stream);
-
-/* Create/destroy stream buffers for read */
-struct lttng_ust_ctl_consumer_stream *
-       lttng_ust_ctl_create_stream(struct lttng_ust_ctl_consumer_channel *channel,
-                       int cpu);
-void lttng_ust_ctl_destroy_stream(struct lttng_ust_ctl_consumer_stream *stream);
-
-/* For mmap mode, readable without "get" operation */
-int lttng_ust_ctl_get_mmap_len(struct lttng_ust_ctl_consumer_stream *stream,
-               unsigned long *len);
-int lttng_ust_ctl_get_max_subbuf_size(struct lttng_ust_ctl_consumer_stream *stream,
-               unsigned long *len);
-
-/*
- * For mmap mode, operate on the current packet (between get/put or
- * get_next/put_next).
- */
-void *lttng_ust_ctl_get_mmap_base(struct lttng_ust_ctl_consumer_stream *stream);
-int lttng_ust_ctl_get_mmap_read_offset(struct lttng_ust_ctl_consumer_stream *stream,
-               unsigned long *off);
-int lttng_ust_ctl_get_subbuf_size(struct lttng_ust_ctl_consumer_stream *stream,
-               unsigned long *len);
-int lttng_ust_ctl_get_padded_subbuf_size(struct lttng_ust_ctl_consumer_stream *stream,
-               unsigned long *len);
-int lttng_ust_ctl_get_next_subbuf(struct lttng_ust_ctl_consumer_stream *stream);
-int lttng_ust_ctl_put_next_subbuf(struct lttng_ust_ctl_consumer_stream *stream);
-
-/* snapshot */
-
-int lttng_ust_ctl_snapshot(struct lttng_ust_ctl_consumer_stream *stream);
-int lttng_ust_ctl_snapshot_sample_positions(struct lttng_ust_ctl_consumer_stream *stream);
-int lttng_ust_ctl_snapshot_get_consumed(struct lttng_ust_ctl_consumer_stream *stream,
-               unsigned long *pos);
-int lttng_ust_ctl_snapshot_get_produced(struct lttng_ust_ctl_consumer_stream *stream,
-               unsigned long *pos);
-int lttng_ust_ctl_get_subbuf(struct lttng_ust_ctl_consumer_stream *stream,
-               unsigned long *pos);
-int lttng_ust_ctl_put_subbuf(struct lttng_ust_ctl_consumer_stream *stream);
-
-int lttng_ust_ctl_flush_buffer(struct lttng_ust_ctl_consumer_stream *stream,
-               int producer_active);
-int lttng_ust_ctl_clear_buffer(struct lttng_ust_ctl_consumer_stream *stream);
-
-/* index */
-
-/*
- * Getters which need to be used on the current packet (between get/put
- * or get_next/put_next.
- */
-
-int lttng_ust_ctl_get_timestamp_begin(struct lttng_ust_ctl_consumer_stream *stream,
-               uint64_t *timestamp_begin);
-int lttng_ust_ctl_get_timestamp_end(struct lttng_ust_ctl_consumer_stream *stream,
-       uint64_t *timestamp_end);
-int lttng_ust_ctl_get_events_discarded(struct lttng_ust_ctl_consumer_stream *stream,
-       uint64_t *events_discarded);
-int lttng_ust_ctl_get_content_size(struct lttng_ust_ctl_consumer_stream *stream,
-       uint64_t *content_size);
-int lttng_ust_ctl_get_packet_size(struct lttng_ust_ctl_consumer_stream *stream,
-       uint64_t *packet_size);
-int lttng_ust_ctl_get_sequence_number(struct lttng_ust_ctl_consumer_stream *stream,
-               uint64_t *seq);
-
-/*
- * Getter returning state invariant for the stream, which can be used
- * without "get" operation.
- */
-
-int lttng_ust_ctl_get_stream_id(struct lttng_ust_ctl_consumer_stream *stream,
-               uint64_t *stream_id);
-int lttng_ust_ctl_get_instance_id(struct lttng_ust_ctl_consumer_stream *stream,
-               uint64_t *id);
-
-/*
- * Getter returning the current timestamp as perceived from the
- * tracer.
- */
-int lttng_ust_ctl_get_current_timestamp(struct lttng_ust_ctl_consumer_stream *stream,
-               uint64_t *ts);
-
-/* returns whether UST has perf counters support. */
-int lttng_ust_ctl_has_perf_counters(void);
-
-/* Regenerate the statedump. */
-int lttng_ust_ctl_regenerate_statedump(int sock, int handle);
-
-/* event registry management */
-
-enum lttng_ust_ctl_socket_type {
-       LTTNG_UST_CTL_SOCKET_CMD = 0,
-       LTTNG_UST_CTL_SOCKET_NOTIFY = 1,
-};
-
-enum lttng_ust_ctl_notify_cmd {
-       LTTNG_UST_CTL_NOTIFY_CMD_EVENT = 0,
-       LTTNG_UST_CTL_NOTIFY_CMD_CHANNEL = 1,
-       LTTNG_UST_CTL_NOTIFY_CMD_ENUM = 2,
-};
-
-enum lttng_ust_ctl_channel_header {
-       LTTNG_UST_CTL_CHANNEL_HEADER_UNKNOWN = 0,
-       LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT = 1,
-       LTTNG_UST_CTL_CHANNEL_HEADER_LARGE = 2,
-};
-
-/* event type structures */
-
-enum lttng_ust_ctl_abstract_types {
-       lttng_ust_ctl_atype_integer,
-       lttng_ust_ctl_atype_enum,       /* legacy */
-       lttng_ust_ctl_atype_array,      /* legacy */
-       lttng_ust_ctl_atype_sequence,   /* legacy */
-       lttng_ust_ctl_atype_string,
-       lttng_ust_ctl_atype_float,
-       lttng_ust_ctl_atype_variant,    /* legacy */
-       lttng_ust_ctl_atype_struct,     /* legacy */
-       lttng_ust_ctl_atype_enum_nestable,
-       lttng_ust_ctl_atype_array_nestable,
-       lttng_ust_ctl_atype_sequence_nestable,
-       lttng_ust_ctl_atype_struct_nestable,
-       lttng_ust_ctl_atype_variant_nestable,
-       NR_LTTNG_UST_CTL_ABSTRACT_TYPES,
-};
-
-enum lttng_ust_ctl_string_encodings {
-       lttng_ust_ctl_encode_none = 0,
-       lttng_ust_ctl_encode_UTF8 = 1,
-       lttng_ust_ctl_encode_ASCII = 2,
-       NR_LTTNG_UST_CTL_STRING_ENCODINGS,
-};
-
-#define LTTNG_UST_CTL_UST_INTEGER_TYPE_PADDING 24
-struct lttng_ust_ctl_integer_type {
-       uint32_t size;          /* in bits */
-       uint32_t signedness;
-       uint32_t reverse_byte_order;
-       uint32_t base;          /* 2, 8, 10, 16, for pretty print */
-       int32_t encoding;       /* enum lttng_ust_ctl_string_encodings */
-       uint16_t alignment;     /* in bits */
-       char padding[LTTNG_UST_CTL_UST_INTEGER_TYPE_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_CTL_UST_FLOAT_TYPE_PADDING   24
-struct lttng_ust_ctl_float_type {
-       uint32_t exp_dig;               /* exponent digits, in bits */
-       uint32_t mant_dig;              /* mantissa digits, in bits */
-       uint32_t reverse_byte_order;
-       uint16_t alignment;     /* in bits */
-       char padding[LTTNG_UST_CTL_UST_FLOAT_TYPE_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_UST_CTL_UST_ENUM_VALUE_PADDING   15
-struct lttng_ust_ctl_enum_value {
-       uint64_t value;
-       uint8_t signedness;
-       char padding[LTTNG_UST_CTL_UST_ENUM_VALUE_PADDING];
-} LTTNG_PACKED;
-
-enum lttng_ust_ctl_ust_enum_entry_options {
-       LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO = 1U << 0,
-};
-
-#define LTTNG_UST_CTL_UST_ENUM_ENTRY_PADDING   32
-struct lttng_ust_ctl_enum_entry {
-       struct lttng_ust_ctl_enum_value start, end; /* start and end are inclusive */
-       char string[LTTNG_UST_ABI_SYM_NAME_LEN];
-       union {
-               struct {
-                       uint32_t options;
-               } LTTNG_PACKED extra;
-               char padding[LTTNG_UST_CTL_UST_ENUM_ENTRY_PADDING];
-       } u;
-} LTTNG_PACKED;
-
-/* legacy */
-#define LTTNG_UST_CTL_UST_BASIC_TYPE_PADDING   296
-union _lttng_ust_ctl_basic_type {
-       struct lttng_ust_ctl_integer_type integer;
-       struct {
-               char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-               struct lttng_ust_ctl_integer_type container_type;
-               uint64_t id;    /* enum ID in sessiond. */
-       } enumeration;
-       struct {
-               int32_t encoding;       /* enum lttng_ust_ctl_string_encodings */
-       } string;
-       struct lttng_ust_ctl_float_type _float;
-       char padding[LTTNG_UST_CTL_UST_BASIC_TYPE_PADDING];
-} LTTNG_PACKED;
-
-/* legacy */
-struct lttng_ust_ctl_basic_type {
-       enum lttng_ust_ctl_abstract_types atype;
-       union {
-               union _lttng_ust_ctl_basic_type basic;
-       } u;
-} LTTNG_PACKED;
-
-/*
- * Padding is derived from largest member: u.legacy.sequence which
- * contains two basic types, each with LTTNG_UST_CTL_UST_BASIC_TYPE_PADDING.
- */
-#define LTTNG_UST_CTL_UST_TYPE_PADDING (2 * LTTNG_UST_CTL_UST_BASIC_TYPE_PADDING)
-struct lttng_ust_ctl_type {
-       enum lttng_ust_ctl_abstract_types atype;
-       union {
-               struct lttng_ust_ctl_integer_type integer;
-               struct lttng_ust_ctl_float_type _float;
-               struct {
-                       int32_t encoding;       /* enum lttng_ust_ctl_string_encodings */
-               } string;
-               struct {
-                       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-                       uint64_t id;    /* enum ID in sessiond. */
-                       /* container_type follows after this struct lttng_ust_ctl_field. */
-               } enum_nestable;
-               struct {
-                       uint32_t length;                /* num. elems. */
-                       uint32_t alignment;
-                       /* elem_type follows after this struct lttng_ust_ctl_field. */
-               } array_nestable;
-               struct {
-                       char length_name[LTTNG_UST_ABI_SYM_NAME_LEN];
-                       uint32_t alignment;             /* Alignment before elements. */
-                       /* elem_type follows after the length_type. */
-               } sequence_nestable;
-               struct {
-                       uint32_t nr_fields;
-                       uint32_t alignment;
-                       /* Followed by nr_fields struct lttng_ust_ctl_field. */
-               } struct_nestable;
-               struct {
-                       uint32_t nr_choices;
-                       char tag_name[LTTNG_UST_ABI_SYM_NAME_LEN];
-                       uint32_t alignment;
-                       /* Followed by nr_choices struct lttng_ust_ctl_field. */
-               } variant_nestable;
-
-               /* Legacy ABI */
-               union {
-                       union _lttng_ust_ctl_basic_type basic;
-                       struct {
-                               struct lttng_ust_ctl_basic_type elem_type;
-                               uint32_t length;                /* num. elems. */
-                       } array;
-                       struct {
-                               struct lttng_ust_ctl_basic_type length_type;
-                               struct lttng_ust_ctl_basic_type elem_type;
-                       } sequence;
-                       struct {
-                               uint32_t nr_fields;
-                               /* Followed by nr_fields struct lttng_ust_ctl_field. */
-                       } _struct;
-                       struct {
-                               uint32_t nr_choices;
-                               char tag_name[LTTNG_UST_ABI_SYM_NAME_LEN];
-                               /* Followed by nr_choices struct lttng_ust_ctl_field. */
-                       } variant;
-               } legacy;
-               char padding[LTTNG_UST_CTL_UST_TYPE_PADDING];
-       } u;
-} LTTNG_PACKED;
-
-#define LTTNG_UST_CTL_UST_FIELD_PADDING        28
-struct lttng_ust_ctl_field {
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-       struct lttng_ust_ctl_type type;
-       char padding[LTTNG_UST_CTL_UST_FIELD_PADDING];
-} LTTNG_PACKED;
-
-/*
- * Returns 0 on success, negative error value on error.
- * If an error other than -LTTNG_UST_ERR_UNSUP_MAJOR is returned,
- * the output fields are not populated.
- */
-int lttng_ust_ctl_recv_reg_msg(int sock,
-       enum lttng_ust_ctl_socket_type *type,
-       uint32_t *major,
-       uint32_t *minor,
-       uint32_t *pid,
-       uint32_t *ppid,
-       uint32_t *uid,
-       uint32_t *gid,
-       uint32_t *bits_per_long,
-       uint32_t *uint8_t_alignment,
-       uint32_t *uint16_t_alignment,
-       uint32_t *uint32_t_alignment,
-       uint32_t *uint64_t_alignment,
-       uint32_t *long_alignment,
-       int *byte_order,
-       char *name);    /* size LTTNG_UST_ABI_PROCNAME_LEN */
-
-/*
- * Returns 0 on success, negative UST or system error value on error.
- * Receive the notification command. The "notify_cmd" can then be used
- * by the caller to find out which lttng_ust_ctl_recv_* function should be
- * called to receive the notification, and which lttng_ust_ctl_reply_* is
- * appropriate.
- */
-int lttng_ust_ctl_recv_notify(int sock, enum lttng_ust_ctl_notify_cmd *notify_cmd);
-
-/*
- * Returns 0 on success, negative UST or system error value on error.
- */
-int lttng_ust_ctl_recv_register_event(int sock,
-       int *session_objd,              /* session descriptor (output) */
-       int *channel_objd,              /* channel descriptor (output) */
-       char *event_name,               /*
-                                        * event name (output,
-                                        * size LTTNG_UST_ABI_SYM_NAME_LEN)
-                                        */
-       int *loglevel,
-       char **signature,               /*
-                                        * event signature
-                                        * (output, dynamically
-                                        * allocated, must be free(3)'d
-                                        * by the caller if function
-                                        * returns success.)
-                                        */
-       size_t *nr_fields,
-       struct lttng_ust_ctl_field **fields,
-       char **model_emf_uri);
-
-/*
- * Returns 0 on success, negative error value on error.
- */
-int lttng_ust_ctl_reply_register_event(int sock,
-       uint32_t id,                    /* event id (input) */
-       int ret_code);                  /* return code. 0 ok, negative error */
-
-/*
- * Returns 0 on success, negative UST or system error value on error.
- */
-int lttng_ust_ctl_recv_register_enum(int sock,
-       int *session_objd,
-       char *enum_name,
-       struct lttng_ust_ctl_enum_entry **entries,
-       size_t *nr_entries);
-
-/*
- * Returns 0 on success, negative error value on error.
- */
-int lttng_ust_ctl_reply_register_enum(int sock,
-       uint64_t id,                    /* enum id (input) */
-       int ret_code);
-
-/*
- * Returns 0 on success, negative UST or system error value on error.
- */
-int lttng_ust_ctl_recv_register_channel(int sock,
-       int *session_objd,              /* session descriptor (output) */
-       int *channel_objd,              /* channel descriptor (output) */
-       size_t *nr_fields,              /* context fields */
-       struct lttng_ust_ctl_field **fields);
-
-/*
- * Returns 0 on success, negative error value on error.
- */
-int lttng_ust_ctl_reply_register_channel(int sock,
-       uint32_t chan_id,
-       enum lttng_ust_ctl_channel_header header_type,
-       int ret_code);                  /* return code. 0 ok, negative error */
-
-/*
- * Counter API.
- */
-
-enum lttng_ust_ctl_counter_bitness {
-       LTTNG_UST_CTL_COUNTER_BITNESS_32 = 0,
-       LTTNG_UST_CTL_COUNTER_BITNESS_64 = 1,
-};
-
-enum lttng_ust_ctl_counter_arithmetic {
-       LTTNG_UST_CTL_COUNTER_ARITHMETIC_MODULAR        = 0,
-       LTTNG_UST_CTL_COUNTER_ARITHMETIC_SATURATION     = 1,
-};
-
-/* Used as alloc flags. */
-enum lttng_ust_ctl_counter_alloc {
-       LTTNG_UST_CTL_COUNTER_ALLOC_PER_CPU = (1 << 0),
-       LTTNG_UST_CTL_COUNTER_ALLOC_GLOBAL = (1 << 1),
-};
-
-struct lttng_ust_ctl_daemon_counter;
-
-int lttng_ust_ctl_get_nr_cpu_per_counter(void);
-
-struct lttng_ust_ctl_counter_dimension {
-       uint64_t size;
-       uint64_t underflow_index;
-       uint64_t overflow_index;
-       uint8_t has_underflow;
-       uint8_t has_overflow;
-};
-
-struct lttng_ust_ctl_daemon_counter *
-       lttng_ust_ctl_create_counter(size_t nr_dimensions,
-               const struct lttng_ust_ctl_counter_dimension *dimensions,
-               int64_t global_sum_step,
-               int global_counter_fd,
-               int nr_counter_cpu_fds,
-               const int *counter_cpu_fds,
-               enum lttng_ust_ctl_counter_bitness bitness,
-               enum lttng_ust_ctl_counter_arithmetic arithmetic,
-               uint32_t alloc_flags,
-               bool coalesce_hits);
-
-int lttng_ust_ctl_create_counter_data(struct lttng_ust_ctl_daemon_counter *counter,
-               struct lttng_ust_abi_object_data **counter_data);
-
-int lttng_ust_ctl_create_counter_global_data(struct lttng_ust_ctl_daemon_counter *counter,
-               struct lttng_ust_abi_object_data **counter_global_data);
-int lttng_ust_ctl_create_counter_cpu_data(struct lttng_ust_ctl_daemon_counter *counter, int cpu,
-               struct lttng_ust_abi_object_data **counter_cpu_data);
-
-/*
- * Each counter data and counter cpu data created need to be destroyed
- * before calling lttng_ust_ctl_destroy_counter().
- */
-void lttng_ust_ctl_destroy_counter(struct lttng_ust_ctl_daemon_counter *counter);
-
-int lttng_ust_ctl_send_counter_data_to_ust(int sock, int parent_handle,
-               struct lttng_ust_abi_object_data *counter_data);
-int lttng_ust_ctl_send_counter_global_data_to_ust(int sock,
-               struct lttng_ust_abi_object_data *counter_data,
-               struct lttng_ust_abi_object_data *counter_global_data);
-int lttng_ust_ctl_send_counter_cpu_data_to_ust(int sock,
-               struct lttng_ust_abi_object_data *counter_data,
-               struct lttng_ust_abi_object_data *counter_cpu_data);
-
-int lttng_ust_ctl_counter_read(struct lttng_ust_ctl_daemon_counter *counter,
-               const size_t *dimension_indexes,
-               int cpu, int64_t *value,
-               bool *overflow, bool *underflow);
-int lttng_ust_ctl_counter_aggregate(struct lttng_ust_ctl_daemon_counter *counter,
-               const size_t *dimension_indexes,
-               int64_t *value,
-               bool *overflow, bool *underflow);
-int lttng_ust_ctl_counter_clear(struct lttng_ust_ctl_daemon_counter *counter,
-               const size_t *dimension_indexes);
-
-void lttng_ust_ctl_sigbus_handle(void *addr);
-
-#endif /* LTTNG_UST_CTL_INTERNAL_H */
diff --git a/src/bin/lttng-sessiond/ust-ctl-internal.hpp b/src/bin/lttng-sessiond/ust-ctl-internal.hpp
new file mode 100644 (file)
index 0000000..10bd656
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_UST_CTL_INTERNAL_H
+#define LTTNG_UST_CTL_INTERNAL_H
+
+#include <sys/types.h>
+#include <limits.h>
+
+#include "lttng-ust-abi.hpp"
+
+#ifndef LTTNG_UST_UUID_LEN
+#define LTTNG_UST_UUID_LEN     16
+#endif
+
+/* Default unix socket path */
+#define LTTNG_UST_SOCK_FILENAME                                        \
+       "lttng-ust-sock-"                                       \
+       __ust_stringify(LTTNG_UST_ABI_MAJOR_VERSION_OLDEST_COMPATIBLE)
+
+/*
+ * Shared memory files path are automatically related to shm root, e.g.
+ * /dev/shm under linux.
+ */
+#define LTTNG_UST_WAIT_FILENAME                                        \
+       "lttng-ust-wait-"                                       \
+       __ust_stringify(LTTNG_UST_ABI_MAJOR_VERSION_OLDEST_COMPATIBLE)
+
+struct lttng_ust_shm_handle;
+struct lttng_ust_lib_ring_buffer;
+
+struct lttng_ust_ctl_consumer_channel_attr {
+       enum lttng_ust_abi_chan_type type;
+       uint64_t subbuf_size;                   /* bytes */
+       uint64_t num_subbuf;                    /* power of 2 */
+       int overwrite;                          /* 1: overwrite, 0: discard */
+       unsigned int switch_timer_interval;     /* usec */
+       unsigned int read_timer_interval;       /* usec */
+       enum lttng_ust_abi_output output;       /* splice, mmap */
+       uint32_t chan_id;                       /* channel ID */
+       unsigned char uuid[LTTNG_UST_UUID_LEN]; /* Trace session unique ID */
+       int64_t blocking_timeout;                       /* Blocking timeout (usec) */
+} LTTNG_PACKED;
+
+/*
+ * API used by sessiond.
+ */
+
+struct lttng_ust_context_attr {
+       enum lttng_ust_abi_context_type ctx;
+       union {
+               struct lttng_ust_abi_perf_counter_ctx perf_counter;
+               struct {
+                       char *provider_name;
+                       char *ctx_name;
+               } app_ctx;
+       } u;
+};
+
+/*
+ * Error values: all the following functions return:
+ * >= 0: Success (LTTNG_UST_OK)
+ * < 0: error code.
+ */
+int lttng_ust_ctl_register_done(int sock);
+int lttng_ust_ctl_create_session(int sock);
+int lttng_ust_ctl_create_event(int sock, struct lttng_ust_abi_event *ev,
+               struct lttng_ust_abi_object_data *channel_data,
+               struct lttng_ust_abi_object_data **event_data);
+int lttng_ust_ctl_add_context(int sock, struct lttng_ust_context_attr *ctx,
+               struct lttng_ust_abi_object_data *obj_data,
+               struct lttng_ust_abi_object_data **context_data);
+int lttng_ust_ctl_set_filter(int sock, struct lttng_ust_abi_filter_bytecode *bytecode,
+               struct lttng_ust_abi_object_data *obj_data);
+int lttng_ust_ctl_set_capture(int sock, struct lttng_ust_abi_capture_bytecode *bytecode,
+               struct lttng_ust_abi_object_data *obj_data);
+int lttng_ust_ctl_set_exclusion(int sock, struct lttng_ust_abi_event_exclusion *exclusion,
+               struct lttng_ust_abi_object_data *obj_data);
+
+int lttng_ust_ctl_enable(int sock, struct lttng_ust_abi_object_data *object);
+int lttng_ust_ctl_disable(int sock, struct lttng_ust_abi_object_data *object);
+int lttng_ust_ctl_start_session(int sock, int handle);
+int lttng_ust_ctl_stop_session(int sock, int handle);
+
+/*
+ * lttng_ust_ctl_create_event notifier_group creates a event notifier group. It
+ * establishes the connection with the application by providing a file
+ * descriptor of the pipe to be used by the application when a event notifier
+ * of that group is fired. It returns a handle to be used when creating event
+ * notifier in that group.
+ */
+int lttng_ust_ctl_create_event_notifier_group(int sock, int pipe_fd,
+               struct lttng_ust_abi_object_data **event_notifier_group);
+
+/*
+ * lttng_ust_ctl_create_event notifier creates a event notifier in a event notifier
+ * group giving a event notifier description and a event notifier group handle.
+ * It returns a event notifier handle to be used when enabling the event
+ * notifier, attaching filter, attaching exclusion, and disabling the event
+ * notifier.
+ */
+int lttng_ust_ctl_create_event_notifier(int sock,
+               struct lttng_ust_abi_event_notifier *event_notifier,
+               struct lttng_ust_abi_object_data *event_notifier_group,
+               struct lttng_ust_abi_object_data **event_notifier_data);
+
+/*
+ * lttng_ust_ctl_tracepoint_list returns a tracepoint list handle, or negative
+ * error value.
+ */
+int lttng_ust_ctl_tracepoint_list(int sock);
+
+/*
+ * lttng_ust_ctl_tracepoint_list_get is used to iterate on the tp list
+ * handle. End is iteration is reached when -LTTNG_UST_ERR_NOENT is
+ * returned.
+ */
+int lttng_ust_ctl_tracepoint_list_get(int sock, int tp_list_handle,
+               struct lttng_ust_abi_tracepoint_iter *iter);
+
+/*
+ * lttng_ust_ctl_tracepoint_field_list returns a tracepoint field list handle,
+ * or negative error value.
+ */
+int lttng_ust_ctl_tracepoint_field_list(int sock);
+
+/*
+ * lttng_ust_ctl_tracepoint_field_list_get is used to iterate on the tp field
+ * list handle. End is iteration is reached when -LTTNG_UST_ERR_NOENT is
+ * returned.
+ */
+int lttng_ust_ctl_tracepoint_field_list_get(int sock, int tp_field_list_handle,
+               struct lttng_ust_abi_field_iter *iter);
+
+int lttng_ust_ctl_tracer_version(int sock, struct lttng_ust_abi_tracer_version *v);
+int lttng_ust_ctl_wait_quiescent(int sock);
+
+int lttng_ust_ctl_sock_flush_buffer(int sock, struct lttng_ust_abi_object_data *object);
+
+int lttng_ust_ctl_calibrate(int sock, struct lttng_ust_abi_calibrate *calibrate);
+
+/* Release object created by members of this API. */
+int lttng_ust_ctl_release_object(int sock, struct lttng_ust_abi_object_data *data);
+/* Release handle returned by create session. */
+int lttng_ust_ctl_release_handle(int sock, int handle);
+
+int lttng_ust_ctl_recv_channel_from_consumer(int sock,
+               struct lttng_ust_abi_object_data **channel_data);
+int lttng_ust_ctl_recv_stream_from_consumer(int sock,
+               struct lttng_ust_abi_object_data **stream_data);
+int lttng_ust_ctl_send_channel_to_ust(int sock, int session_handle,
+               struct lttng_ust_abi_object_data *channel_data);
+int lttng_ust_ctl_send_stream_to_ust(int sock,
+               struct lttng_ust_abi_object_data *channel_data,
+               struct lttng_ust_abi_object_data *stream_data);
+
+/*
+ * lttng_ust_ctl_duplicate_ust_object_data allocated a new object in "dest" if
+ * it succeeds (returns 0). It must be released using
+ * lttng_ust_ctl_release_object() and then freed with free().
+ */
+int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **dest,
+               struct lttng_ust_abi_object_data *src);
+
+/*
+ * API used by consumer.
+ */
+
+struct lttng_ust_ctl_consumer_channel;
+struct lttng_ust_ctl_consumer_stream;
+struct lttng_ust_ctl_consumer_channel_attr;
+
+int lttng_ust_ctl_get_nr_stream_per_channel(void);
+
+struct lttng_ust_ctl_consumer_channel *
+       lttng_ust_ctl_create_channel(struct lttng_ust_ctl_consumer_channel_attr *attr,
+               const int *stream_fds, int nr_stream_fds);
+/*
+ * Each stream created needs to be destroyed before calling
+ * lttng_ust_ctl_destroy_channel().
+ */
+void lttng_ust_ctl_destroy_channel(struct lttng_ust_ctl_consumer_channel *chan);
+
+int lttng_ust_ctl_send_channel_to_sessiond(int sock,
+               struct lttng_ust_ctl_consumer_channel *channel);
+int lttng_ust_ctl_channel_close_wait_fd(struct lttng_ust_ctl_consumer_channel *consumer_chan);
+int lttng_ust_ctl_channel_close_wakeup_fd(struct lttng_ust_ctl_consumer_channel *consumer_chan);
+int lttng_ust_ctl_channel_get_wait_fd(struct lttng_ust_ctl_consumer_channel *consumer_chan);
+int lttng_ust_ctl_channel_get_wakeup_fd(struct lttng_ust_ctl_consumer_channel *consumer_chan);
+
+int lttng_ust_ctl_write_metadata_to_channel(
+               struct lttng_ust_ctl_consumer_channel *channel,
+               const char *metadata_str,       /* NOT null-terminated */
+               size_t len);                    /* metadata length */
+ssize_t lttng_ust_ctl_write_one_packet_to_channel(
+               struct lttng_ust_ctl_consumer_channel *channel,
+               const char *metadata_str,       /* NOT null-terminated */
+               size_t len);                    /* metadata length */
+
+/*
+ * Send a NULL stream to finish iteration over all streams of a given
+ * channel.
+ */
+int lttng_ust_ctl_send_stream_to_sessiond(int sock,
+               struct lttng_ust_ctl_consumer_stream *stream);
+int lttng_ust_ctl_stream_close_wait_fd(struct lttng_ust_ctl_consumer_stream *stream);
+int lttng_ust_ctl_stream_close_wakeup_fd(struct lttng_ust_ctl_consumer_stream *stream);
+int lttng_ust_ctl_stream_get_wait_fd(struct lttng_ust_ctl_consumer_stream *stream);
+int lttng_ust_ctl_stream_get_wakeup_fd(struct lttng_ust_ctl_consumer_stream *stream);
+
+/* Create/destroy stream buffers for read */
+struct lttng_ust_ctl_consumer_stream *
+       lttng_ust_ctl_create_stream(struct lttng_ust_ctl_consumer_channel *channel,
+                       int cpu);
+void lttng_ust_ctl_destroy_stream(struct lttng_ust_ctl_consumer_stream *stream);
+
+/* For mmap mode, readable without "get" operation */
+int lttng_ust_ctl_get_mmap_len(struct lttng_ust_ctl_consumer_stream *stream,
+               unsigned long *len);
+int lttng_ust_ctl_get_max_subbuf_size(struct lttng_ust_ctl_consumer_stream *stream,
+               unsigned long *len);
+
+/*
+ * For mmap mode, operate on the current packet (between get/put or
+ * get_next/put_next).
+ */
+void *lttng_ust_ctl_get_mmap_base(struct lttng_ust_ctl_consumer_stream *stream);
+int lttng_ust_ctl_get_mmap_read_offset(struct lttng_ust_ctl_consumer_stream *stream,
+               unsigned long *off);
+int lttng_ust_ctl_get_subbuf_size(struct lttng_ust_ctl_consumer_stream *stream,
+               unsigned long *len);
+int lttng_ust_ctl_get_padded_subbuf_size(struct lttng_ust_ctl_consumer_stream *stream,
+               unsigned long *len);
+int lttng_ust_ctl_get_next_subbuf(struct lttng_ust_ctl_consumer_stream *stream);
+int lttng_ust_ctl_put_next_subbuf(struct lttng_ust_ctl_consumer_stream *stream);
+
+/* snapshot */
+
+int lttng_ust_ctl_snapshot(struct lttng_ust_ctl_consumer_stream *stream);
+int lttng_ust_ctl_snapshot_sample_positions(struct lttng_ust_ctl_consumer_stream *stream);
+int lttng_ust_ctl_snapshot_get_consumed(struct lttng_ust_ctl_consumer_stream *stream,
+               unsigned long *pos);
+int lttng_ust_ctl_snapshot_get_produced(struct lttng_ust_ctl_consumer_stream *stream,
+               unsigned long *pos);
+int lttng_ust_ctl_get_subbuf(struct lttng_ust_ctl_consumer_stream *stream,
+               unsigned long *pos);
+int lttng_ust_ctl_put_subbuf(struct lttng_ust_ctl_consumer_stream *stream);
+
+int lttng_ust_ctl_flush_buffer(struct lttng_ust_ctl_consumer_stream *stream,
+               int producer_active);
+int lttng_ust_ctl_clear_buffer(struct lttng_ust_ctl_consumer_stream *stream);
+
+/* index */
+
+/*
+ * Getters which need to be used on the current packet (between get/put
+ * or get_next/put_next.
+ */
+
+int lttng_ust_ctl_get_timestamp_begin(struct lttng_ust_ctl_consumer_stream *stream,
+               uint64_t *timestamp_begin);
+int lttng_ust_ctl_get_timestamp_end(struct lttng_ust_ctl_consumer_stream *stream,
+       uint64_t *timestamp_end);
+int lttng_ust_ctl_get_events_discarded(struct lttng_ust_ctl_consumer_stream *stream,
+       uint64_t *events_discarded);
+int lttng_ust_ctl_get_content_size(struct lttng_ust_ctl_consumer_stream *stream,
+       uint64_t *content_size);
+int lttng_ust_ctl_get_packet_size(struct lttng_ust_ctl_consumer_stream *stream,
+       uint64_t *packet_size);
+int lttng_ust_ctl_get_sequence_number(struct lttng_ust_ctl_consumer_stream *stream,
+               uint64_t *seq);
+
+/*
+ * Getter returning state invariant for the stream, which can be used
+ * without "get" operation.
+ */
+
+int lttng_ust_ctl_get_stream_id(struct lttng_ust_ctl_consumer_stream *stream,
+               uint64_t *stream_id);
+int lttng_ust_ctl_get_instance_id(struct lttng_ust_ctl_consumer_stream *stream,
+               uint64_t *id);
+
+/*
+ * Getter returning the current timestamp as perceived from the
+ * tracer.
+ */
+int lttng_ust_ctl_get_current_timestamp(struct lttng_ust_ctl_consumer_stream *stream,
+               uint64_t *ts);
+
+/* returns whether UST has perf counters support. */
+int lttng_ust_ctl_has_perf_counters(void);
+
+/* Regenerate the statedump. */
+int lttng_ust_ctl_regenerate_statedump(int sock, int handle);
+
+/* event registry management */
+
+enum lttng_ust_ctl_socket_type {
+       LTTNG_UST_CTL_SOCKET_CMD = 0,
+       LTTNG_UST_CTL_SOCKET_NOTIFY = 1,
+};
+
+enum lttng_ust_ctl_notify_cmd {
+       LTTNG_UST_CTL_NOTIFY_CMD_EVENT = 0,
+       LTTNG_UST_CTL_NOTIFY_CMD_CHANNEL = 1,
+       LTTNG_UST_CTL_NOTIFY_CMD_ENUM = 2,
+};
+
+enum lttng_ust_ctl_channel_header {
+       LTTNG_UST_CTL_CHANNEL_HEADER_UNKNOWN = 0,
+       LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT = 1,
+       LTTNG_UST_CTL_CHANNEL_HEADER_LARGE = 2,
+};
+
+/* event type structures */
+
+enum lttng_ust_ctl_abstract_types {
+       lttng_ust_ctl_atype_integer,
+       lttng_ust_ctl_atype_enum,       /* legacy */
+       lttng_ust_ctl_atype_array,      /* legacy */
+       lttng_ust_ctl_atype_sequence,   /* legacy */
+       lttng_ust_ctl_atype_string,
+       lttng_ust_ctl_atype_float,
+       lttng_ust_ctl_atype_variant,    /* legacy */
+       lttng_ust_ctl_atype_struct,     /* legacy */
+       lttng_ust_ctl_atype_enum_nestable,
+       lttng_ust_ctl_atype_array_nestable,
+       lttng_ust_ctl_atype_sequence_nestable,
+       lttng_ust_ctl_atype_struct_nestable,
+       lttng_ust_ctl_atype_variant_nestable,
+       NR_LTTNG_UST_CTL_ABSTRACT_TYPES,
+};
+
+enum lttng_ust_ctl_string_encodings {
+       lttng_ust_ctl_encode_none = 0,
+       lttng_ust_ctl_encode_UTF8 = 1,
+       lttng_ust_ctl_encode_ASCII = 2,
+       NR_LTTNG_UST_CTL_STRING_ENCODINGS,
+};
+
+#define LTTNG_UST_CTL_UST_INTEGER_TYPE_PADDING 24
+struct lttng_ust_ctl_integer_type {
+       uint32_t size;          /* in bits */
+       uint32_t signedness;
+       uint32_t reverse_byte_order;
+       uint32_t base;          /* 2, 8, 10, 16, for pretty print */
+       int32_t encoding;       /* enum lttng_ust_ctl_string_encodings */
+       uint16_t alignment;     /* in bits */
+       char padding[LTTNG_UST_CTL_UST_INTEGER_TYPE_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_CTL_UST_FLOAT_TYPE_PADDING   24
+struct lttng_ust_ctl_float_type {
+       uint32_t exp_dig;               /* exponent digits, in bits */
+       uint32_t mant_dig;              /* mantissa digits, in bits */
+       uint32_t reverse_byte_order;
+       uint16_t alignment;     /* in bits */
+       char padding[LTTNG_UST_CTL_UST_FLOAT_TYPE_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_CTL_UST_ENUM_VALUE_PADDING   15
+struct lttng_ust_ctl_enum_value {
+       uint64_t value;
+       uint8_t signedness;
+       char padding[LTTNG_UST_CTL_UST_ENUM_VALUE_PADDING];
+} LTTNG_PACKED;
+
+enum lttng_ust_ctl_ust_enum_entry_options {
+       LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO = 1U << 0,
+};
+
+#define LTTNG_UST_CTL_UST_ENUM_ENTRY_PADDING   32
+struct lttng_ust_ctl_enum_entry {
+       struct lttng_ust_ctl_enum_value start, end; /* start and end are inclusive */
+       char string[LTTNG_UST_ABI_SYM_NAME_LEN];
+       union {
+               struct {
+                       uint32_t options;
+               } LTTNG_PACKED extra;
+               char padding[LTTNG_UST_CTL_UST_ENUM_ENTRY_PADDING];
+       } u;
+} LTTNG_PACKED;
+
+/* legacy */
+#define LTTNG_UST_CTL_UST_BASIC_TYPE_PADDING   296
+union _lttng_ust_ctl_basic_type {
+       struct lttng_ust_ctl_integer_type integer;
+       struct {
+               char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+               struct lttng_ust_ctl_integer_type container_type;
+               uint64_t id;    /* enum ID in sessiond. */
+       } enumeration;
+       struct {
+               int32_t encoding;       /* enum lttng_ust_ctl_string_encodings */
+       } string;
+       struct lttng_ust_ctl_float_type _float;
+       char padding[LTTNG_UST_CTL_UST_BASIC_TYPE_PADDING];
+} LTTNG_PACKED;
+
+/* legacy */
+struct lttng_ust_ctl_basic_type {
+       enum lttng_ust_ctl_abstract_types atype;
+       union {
+               union _lttng_ust_ctl_basic_type basic;
+       } u;
+} LTTNG_PACKED;
+
+/*
+ * Padding is derived from largest member: u.legacy.sequence which
+ * contains two basic types, each with LTTNG_UST_CTL_UST_BASIC_TYPE_PADDING.
+ */
+#define LTTNG_UST_CTL_UST_TYPE_PADDING (2 * LTTNG_UST_CTL_UST_BASIC_TYPE_PADDING)
+struct lttng_ust_ctl_type {
+       enum lttng_ust_ctl_abstract_types atype;
+       union {
+               struct lttng_ust_ctl_integer_type integer;
+               struct lttng_ust_ctl_float_type _float;
+               struct {
+                       int32_t encoding;       /* enum lttng_ust_ctl_string_encodings */
+               } string;
+               struct {
+                       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+                       uint64_t id;    /* enum ID in sessiond. */
+                       /* container_type follows after this struct lttng_ust_ctl_field. */
+               } enum_nestable;
+               struct {
+                       uint32_t length;                /* num. elems. */
+                       uint32_t alignment;
+                       /* elem_type follows after this struct lttng_ust_ctl_field. */
+               } array_nestable;
+               struct {
+                       char length_name[LTTNG_UST_ABI_SYM_NAME_LEN];
+                       uint32_t alignment;             /* Alignment before elements. */
+                       /* elem_type follows after the length_type. */
+               } sequence_nestable;
+               struct {
+                       uint32_t nr_fields;
+                       uint32_t alignment;
+                       /* Followed by nr_fields struct lttng_ust_ctl_field. */
+               } struct_nestable;
+               struct {
+                       uint32_t nr_choices;
+                       char tag_name[LTTNG_UST_ABI_SYM_NAME_LEN];
+                       uint32_t alignment;
+                       /* Followed by nr_choices struct lttng_ust_ctl_field. */
+               } variant_nestable;
+
+               /* Legacy ABI */
+               union {
+                       union _lttng_ust_ctl_basic_type basic;
+                       struct {
+                               struct lttng_ust_ctl_basic_type elem_type;
+                               uint32_t length;                /* num. elems. */
+                       } array;
+                       struct {
+                               struct lttng_ust_ctl_basic_type length_type;
+                               struct lttng_ust_ctl_basic_type elem_type;
+                       } sequence;
+                       struct {
+                               uint32_t nr_fields;
+                               /* Followed by nr_fields struct lttng_ust_ctl_field. */
+                       } _struct;
+                       struct {
+                               uint32_t nr_choices;
+                               char tag_name[LTTNG_UST_ABI_SYM_NAME_LEN];
+                               /* Followed by nr_choices struct lttng_ust_ctl_field. */
+                       } variant;
+               } legacy;
+               char padding[LTTNG_UST_CTL_UST_TYPE_PADDING];
+       } u;
+} LTTNG_PACKED;
+
+#define LTTNG_UST_CTL_UST_FIELD_PADDING        28
+struct lttng_ust_ctl_field {
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+       struct lttng_ust_ctl_type type;
+       char padding[LTTNG_UST_CTL_UST_FIELD_PADDING];
+} LTTNG_PACKED;
+
+/*
+ * Returns 0 on success, negative error value on error.
+ * If an error other than -LTTNG_UST_ERR_UNSUP_MAJOR is returned,
+ * the output fields are not populated.
+ */
+int lttng_ust_ctl_recv_reg_msg(int sock,
+       enum lttng_ust_ctl_socket_type *type,
+       uint32_t *major,
+       uint32_t *minor,
+       uint32_t *pid,
+       uint32_t *ppid,
+       uint32_t *uid,
+       uint32_t *gid,
+       uint32_t *bits_per_long,
+       uint32_t *uint8_t_alignment,
+       uint32_t *uint16_t_alignment,
+       uint32_t *uint32_t_alignment,
+       uint32_t *uint64_t_alignment,
+       uint32_t *long_alignment,
+       int *byte_order,
+       char *name);    /* size LTTNG_UST_ABI_PROCNAME_LEN */
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ * Receive the notification command. The "notify_cmd" can then be used
+ * by the caller to find out which lttng_ust_ctl_recv_* function should be
+ * called to receive the notification, and which lttng_ust_ctl_reply_* is
+ * appropriate.
+ */
+int lttng_ust_ctl_recv_notify(int sock, enum lttng_ust_ctl_notify_cmd *notify_cmd);
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int lttng_ust_ctl_recv_register_event(int sock,
+       int *session_objd,              /* session descriptor (output) */
+       int *channel_objd,              /* channel descriptor (output) */
+       char *event_name,               /*
+                                        * event name (output,
+                                        * size LTTNG_UST_ABI_SYM_NAME_LEN)
+                                        */
+       int *loglevel,
+       char **signature,               /*
+                                        * event signature
+                                        * (output, dynamically
+                                        * allocated, must be free(3)'d
+                                        * by the caller if function
+                                        * returns success.)
+                                        */
+       size_t *nr_fields,
+       struct lttng_ust_ctl_field **fields,
+       char **model_emf_uri);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int lttng_ust_ctl_reply_register_event(int sock,
+       uint32_t id,                    /* event id (input) */
+       int ret_code);                  /* return code. 0 ok, negative error */
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int lttng_ust_ctl_recv_register_enum(int sock,
+       int *session_objd,
+       char *enum_name,
+       struct lttng_ust_ctl_enum_entry **entries,
+       size_t *nr_entries);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int lttng_ust_ctl_reply_register_enum(int sock,
+       uint64_t id,                    /* enum id (input) */
+       int ret_code);
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int lttng_ust_ctl_recv_register_channel(int sock,
+       int *session_objd,              /* session descriptor (output) */
+       int *channel_objd,              /* channel descriptor (output) */
+       size_t *nr_fields,              /* context fields */
+       struct lttng_ust_ctl_field **fields);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int lttng_ust_ctl_reply_register_channel(int sock,
+       uint32_t chan_id,
+       enum lttng_ust_ctl_channel_header header_type,
+       int ret_code);                  /* return code. 0 ok, negative error */
+
+/*
+ * Counter API.
+ */
+
+enum lttng_ust_ctl_counter_bitness {
+       LTTNG_UST_CTL_COUNTER_BITNESS_32 = 0,
+       LTTNG_UST_CTL_COUNTER_BITNESS_64 = 1,
+};
+
+enum lttng_ust_ctl_counter_arithmetic {
+       LTTNG_UST_CTL_COUNTER_ARITHMETIC_MODULAR        = 0,
+       LTTNG_UST_CTL_COUNTER_ARITHMETIC_SATURATION     = 1,
+};
+
+/* Used as alloc flags. */
+enum lttng_ust_ctl_counter_alloc {
+       LTTNG_UST_CTL_COUNTER_ALLOC_PER_CPU = (1 << 0),
+       LTTNG_UST_CTL_COUNTER_ALLOC_GLOBAL = (1 << 1),
+};
+
+struct lttng_ust_ctl_daemon_counter;
+
+int lttng_ust_ctl_get_nr_cpu_per_counter(void);
+
+struct lttng_ust_ctl_counter_dimension {
+       uint64_t size;
+       uint64_t underflow_index;
+       uint64_t overflow_index;
+       uint8_t has_underflow;
+       uint8_t has_overflow;
+};
+
+struct lttng_ust_ctl_daemon_counter *
+       lttng_ust_ctl_create_counter(size_t nr_dimensions,
+               const struct lttng_ust_ctl_counter_dimension *dimensions,
+               int64_t global_sum_step,
+               int global_counter_fd,
+               int nr_counter_cpu_fds,
+               const int *counter_cpu_fds,
+               enum lttng_ust_ctl_counter_bitness bitness,
+               enum lttng_ust_ctl_counter_arithmetic arithmetic,
+               uint32_t alloc_flags,
+               bool coalesce_hits);
+
+int lttng_ust_ctl_create_counter_data(struct lttng_ust_ctl_daemon_counter *counter,
+               struct lttng_ust_abi_object_data **counter_data);
+
+int lttng_ust_ctl_create_counter_global_data(struct lttng_ust_ctl_daemon_counter *counter,
+               struct lttng_ust_abi_object_data **counter_global_data);
+int lttng_ust_ctl_create_counter_cpu_data(struct lttng_ust_ctl_daemon_counter *counter, int cpu,
+               struct lttng_ust_abi_object_data **counter_cpu_data);
+
+/*
+ * Each counter data and counter cpu data created need to be destroyed
+ * before calling lttng_ust_ctl_destroy_counter().
+ */
+void lttng_ust_ctl_destroy_counter(struct lttng_ust_ctl_daemon_counter *counter);
+
+int lttng_ust_ctl_send_counter_data_to_ust(int sock, int parent_handle,
+               struct lttng_ust_abi_object_data *counter_data);
+int lttng_ust_ctl_send_counter_global_data_to_ust(int sock,
+               struct lttng_ust_abi_object_data *counter_data,
+               struct lttng_ust_abi_object_data *counter_global_data);
+int lttng_ust_ctl_send_counter_cpu_data_to_ust(int sock,
+               struct lttng_ust_abi_object_data *counter_data,
+               struct lttng_ust_abi_object_data *counter_cpu_data);
+
+int lttng_ust_ctl_counter_read(struct lttng_ust_ctl_daemon_counter *counter,
+               const size_t *dimension_indexes,
+               int cpu, int64_t *value,
+               bool *overflow, bool *underflow);
+int lttng_ust_ctl_counter_aggregate(struct lttng_ust_ctl_daemon_counter *counter,
+               const size_t *dimension_indexes,
+               int64_t *value,
+               bool *overflow, bool *underflow);
+int lttng_ust_ctl_counter_clear(struct lttng_ust_ctl_daemon_counter *counter,
+               const size_t *dimension_indexes);
+
+void lttng_ust_ctl_sigbus_handle(void *addr);
+
+#endif /* LTTNG_UST_CTL_INTERNAL_H */
diff --git a/src/bin/lttng-sessiond/ust-error-internal.h b/src/bin/lttng-sessiond/ust-error-internal.h
deleted file mode 100644 (file)
index 3932fba..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef _LTTNG_UST_ERROR_H
-#define _LTTNG_UST_ERROR_H
-
-/*
- * This header is meant for liblttng and libust internal use ONLY.
- * These declarations should NOT be considered stable API.
- */
-
-#include <limits.h>
-#include <unistd.h>
-
-#include "lttng-ust-abi.h"
-
-/*
- * ustcomm error code.
- */
-enum lttng_ust_error_code {
-       LTTNG_UST_OK = 0,                       /* Ok */
-       LTTNG_UST_ERR = 1024,                   /* Unknown Error */
-       LTTNG_UST_ERR_NOENT = 1025,             /* No entry */
-       LTTNG_UST_ERR_EXIST = 1026,             /* Object exists */
-       LTTNG_UST_ERR_INVAL = 1027,             /* Invalid argument */
-       LTTNG_UST_ERR_PERM  = 1028,             /* Permission denied */
-       LTTNG_UST_ERR_NOSYS = 1029,             /* Not implemented */
-       LTTNG_UST_ERR_EXITING = 1030,           /* Process is exiting */
-
-       LTTNG_UST_ERR_INVAL_MAGIC = 1031,       /* Invalid magic number */
-       LTTNG_UST_ERR_INVAL_SOCKET_TYPE = 1032, /* Invalid socket type */
-       LTTNG_UST_ERR_UNSUP_MAJOR = 1033,       /* Unsupported major version */
-
-       /* MUST be last element */
-       LTTNG_UST_ERR_NR,                       /* Last element */
-};
-
-/*
- * Return a human-readable error message for an lttng-ust error code.
- * code must be a positive value (or 0).
- */
-extern const char *lttng_ust_strerror(int code);
-
-#endif /* _LTTNG_UST_ERROR_H */
diff --git a/src/bin/lttng-sessiond/ust-error-internal.hpp b/src/bin/lttng-sessiond/ust-error-internal.hpp
new file mode 100644 (file)
index 0000000..2c49900
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef _LTTNG_UST_ERROR_H
+#define _LTTNG_UST_ERROR_H
+
+/*
+ * This header is meant for liblttng and libust internal use ONLY.
+ * These declarations should NOT be considered stable API.
+ */
+
+#include <limits.h>
+#include <unistd.h>
+
+#include "lttng-ust-abi.hpp"
+
+/*
+ * ustcomm error code.
+ */
+enum lttng_ust_error_code {
+       LTTNG_UST_OK = 0,                       /* Ok */
+       LTTNG_UST_ERR = 1024,                   /* Unknown Error */
+       LTTNG_UST_ERR_NOENT = 1025,             /* No entry */
+       LTTNG_UST_ERR_EXIST = 1026,             /* Object exists */
+       LTTNG_UST_ERR_INVAL = 1027,             /* Invalid argument */
+       LTTNG_UST_ERR_PERM  = 1028,             /* Permission denied */
+       LTTNG_UST_ERR_NOSYS = 1029,             /* Not implemented */
+       LTTNG_UST_ERR_EXITING = 1030,           /* Process is exiting */
+
+       LTTNG_UST_ERR_INVAL_MAGIC = 1031,       /* Invalid magic number */
+       LTTNG_UST_ERR_INVAL_SOCKET_TYPE = 1032, /* Invalid socket type */
+       LTTNG_UST_ERR_UNSUP_MAJOR = 1033,       /* Unsupported major version */
+
+       /* MUST be last element */
+       LTTNG_UST_ERR_NR,                       /* Last element */
+};
+
+/*
+ * Return a human-readable error message for an lttng-ust error code.
+ * code must be a positive value (or 0).
+ */
+extern const char *lttng_ust_strerror(int code);
+
+#endif /* _LTTNG_UST_ERROR_H */
index a8f3da2ba7a96c088d54f373962e56311033697b..27d3070d2f453897c1112e4dedb9e173df72937d 100644 (file)
@@ -8,7 +8,7 @@
 #include <stdbool.h>
 #include <string.h>
 
-#include "ust-field-utils.h"
+#include "ust-field-utils.hpp"
 
 /*
  * The lttng_ust_ctl_field is made of a combination of C basic types
diff --git a/src/bin/lttng-sessiond/ust-field-utils.h b/src/bin/lttng-sessiond/ust-field-utils.h
deleted file mode 100644 (file)
index 39cd50b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2018 Francis Deslauriers francis.deslauriers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_UST_FIELD_UTILS_H
-#define LTTNG_UST_FIELD_UTILS_H
-
-#include "lttng-ust-ctl.h"
-
-/*
- * Compare two UST fields.
- * Return 1 if both fields have identical definition, 0 otherwise.
- */
-int match_lttng_ust_ctl_field(const struct lttng_ust_ctl_field *first,
-               const struct lttng_ust_ctl_field *second);
-
-/*
- * Compare two arrays of UST fields.
- * Return true if both arrays have identical field definitions, false otherwise.
- */
-bool match_lttng_ust_ctl_field_array(const struct lttng_ust_ctl_field *first,
-               size_t nr_first,
-               const struct lttng_ust_ctl_field *second,
-               size_t nr_second);
-
-#endif /* LTTNG_UST_FIELD_UTILS_H */
diff --git a/src/bin/lttng-sessiond/ust-field-utils.hpp b/src/bin/lttng-sessiond/ust-field-utils.hpp
new file mode 100644 (file)
index 0000000..886ae52
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 Francis Deslauriers francis.deslauriers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_UST_FIELD_UTILS_H
+#define LTTNG_UST_FIELD_UTILS_H
+
+#include "lttng-ust-ctl.hpp"
+
+/*
+ * Compare two UST fields.
+ * Return 1 if both fields have identical definition, 0 otherwise.
+ */
+int match_lttng_ust_ctl_field(const struct lttng_ust_ctl_field *first,
+               const struct lttng_ust_ctl_field *second);
+
+/*
+ * Compare two arrays of UST fields.
+ * Return true if both arrays have identical field definitions, false otherwise.
+ */
+bool match_lttng_ust_ctl_field_array(const struct lttng_ust_ctl_field *first,
+               size_t nr_first,
+               const struct lttng_ust_ctl_field *second,
+               size_t nr_second);
+
+#endif /* LTTNG_UST_FIELD_UTILS_H */
index 6028527c5ed27cbdb4cd7a0c885b4944b211fb0d..4666b4d5983451bd46bde20be1023735eed1000d 100644 (file)
@@ -5,6 +5,10 @@
  *
  */
 
+#include "common/bytecode/bytecode.hpp"
+#include "common/macros.hpp"
+#include "common/uuid.hpp"
+#include <endian.h>
 #define _LGPL_SOURCE
 #include <stdint.h>
 #include <string.h>
 #include <limits.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <common/common.h>
-#include <common/time.h>
+#include <common/common.hpp>
+#include <common/time.hpp>
+#include <vector>
+#include <vendor/nlohmann/json.hpp>
 
-#include "ust-registry.h"
-#include "ust-clock.h"
-#include "ust-app.h"
-
-#ifndef max_t
-#define max_t(type, a, b)      ((type) ((a) > (b) ? (a) : (b)))
-#endif
+#include "ust-registry.hpp"
+#include "ust-clock.hpp"
+#include "ust-app.hpp"
 
 #define NR_CLOCK_OFFSET_SAMPLES                10
 
+using json = nlohmann::json;
+
 struct offset_sample {
        int64_t offset;                 /* correlation offset */
        uint64_t measure_delta;         /* lower is better */
 };
 
+enum class byte_order
+{
+       BIG,
+       LITTLE,
+};
+
+enum class display_base
+{
+       BINARY,
+       OCTAL,
+       DECIMAL,
+       HEXADECIMAL,
+};
+
+struct metadata_generation_exception : public std::runtime_error
+{
+       metadata_generation_exception(const char *what)
+               : std::runtime_error(what)
+       {}
+};
+
+struct lttng_ust_ctl_field_iterator
+{
+       lttng_ust_ctl_field_iterator(const lttng_ust_ctl_field *array,
+                       size_t len)
+               : _array(array), _len(len)
+       {}
+
+       /* Make sure we don't pass it by value, by mistake. */
+       lttng_ust_ctl_field_iterator(const lttng_ust_ctl_field_iterator &) = delete;
+       void operator=(const lttng_ust_ctl_field_iterator &) = delete;
+
+       const lttng_ust_ctl_field &get_next()
+       {
+               if (done()) {
+                       throw metadata_generation_exception(
+                               "Field iterator overflow");
+               };
+
+               return _array[_cur++];
+       }
+
+       bool done() const
+       {
+               return _cur >= _len;
+       }
+
+private:
+       const lttng_ust_ctl_field *_array;
+       size_t _cur = 0;
+       size_t _len;
+};
+
+static
+byte_order get_byte_order(const ust_registry_session &session, bool reverse)
+{
+       if (session.byte_order == BIG_ENDIAN) {
+               return reverse ? byte_order::LITTLE : byte_order::BIG;
+       } else {
+               return reverse ? byte_order::BIG : byte_order::LITTLE;
+       }
+}
+
+struct bits
+{
+       using underlying_type = uint64_t;
+       explicit bits(uint64_t val)
+               : _val(val)
+       {}
+
+       underlying_type to_underlying() const
+       {
+               return static_cast<underlying_type>(_val);
+       }
+
+       bool operator==(bits other)
+       {
+               return to_underlying() == other.to_underlying();
+       }
+
+       bool operator!=(bits other)
+       {
+               return to_underlying() != other.to_underlying();
+       }
+
+private:
+       const uint64_t _val;
+};
+
+static
+bits operator"" _bits(unsigned long long val)
+{
+       return bits(val);
+}
+
+static
+json make_fragment(const char *type)
+{
+       return {
+               { "type", type }
+       };
+}
+
+static
+json make_field_class(const char *type, const char *role)
+{
+       json fc {
+               { "type", type },
+       };
+
+       if (role) {
+               fc["roles"] = {role};
+       }
+
+       return fc;
+}
+
+static
+const char *make_byte_order(byte_order byte_order)
+{
+       switch (byte_order) {
+       case byte_order::BIG:
+               return "big-endian";
+       case byte_order::LITTLE:
+               return "little-endian";
+       default:
+               abort();
+       }
+}
+
+static
+json make_fixed_length_bit_array_field_class(const char *type, bits length,
+               byte_order byte_order, bits alignment, const char *role)
+{
+       json fc = make_field_class(type, role);
+
+       fc.update ({
+               { "length", length.to_underlying() },
+               { "byte-order", make_byte_order(byte_order) },
+       });
+
+       if (alignment != 0_bits) {
+               fc["alignment"] = alignment.to_underlying();
+       }
+
+       return fc;
+}
+
+static
+json make_display_base(display_base display_base)
+{
+       switch (display_base) {
+               case display_base::BINARY:
+                       return 2;
+               case display_base::OCTAL:
+                       return 8;
+               case display_base::DECIMAL:
+                       return 10;
+               case display_base::HEXADECIMAL:
+                       return 16;
+               default:
+                       abort();
+       }
+}
+
+static
+json make_abstract_integer_field_class(display_base preferred_display_base)
+{
+       json base = json::object();
+       if (preferred_display_base != display_base::DECIMAL) {
+               base = {
+                       { "preferred-display-base",
+                       make_display_base(preferred_display_base)},
+
+               };
+       }
+       return base;
+}
+
+static
+json make_fixed_length_unsigned_integer_field_class(const char *type,
+               bits length, byte_order byte_order, bits alignment,
+               display_base preferred_display_base, const char *role)
+{
+       json fc = make_fixed_length_bit_array_field_class(type, length,
+               byte_order, alignment, role);
+       fc.update(make_abstract_integer_field_class(preferred_display_base));
+       return fc;
+}
+
+static
+json make_fixed_length_signed_integer_field_class(const char *type,
+               bits length, byte_order byte_order, bits alignment,
+               display_base preferred_display_base, const char *role)
+{
+       json fc = make_fixed_length_bit_array_field_class(type, length,
+               byte_order, alignment, role);
+       fc.update(make_abstract_integer_field_class(preferred_display_base));
+       return fc;
+}
+
+static
+json make_fixed_length_unsigned_integer_field_class(bits length,
+               byte_order byte_order, bits alignment,
+               display_base preferred_display_base, const char *role)
+{
+       return make_fixed_length_unsigned_integer_field_class(
+               "fixed-length-unsigned-integer", length, byte_order,
+               alignment, preferred_display_base, role);
+}
+
+static
+json make_fixed_length_signed_integer_field_class(bits length,
+               byte_order byte_order, bits alignment,
+               display_base preferred_display_base, const char *role)
+{
+       return make_fixed_length_signed_integer_field_class(
+               "fixed-length-signed-integer", length, byte_order,
+               alignment, preferred_display_base, role);
+}
+
+static
+json make_fixed_length_floating_point_number_field_class(
+               bits length, byte_order byte_order, bits alignment) {
+       return make_fixed_length_bit_array_field_class(
+               "fixed-length-floating-point-number",
+               length, byte_order, alignment, nullptr);
+}
+
+struct integer_range
+{
+       integer_range(int64_t lower_bound_, int64_t upper_bound_)
+               : is_signed(true), lower_bound(lower_bound_), upper_bound(upper_bound_)
+       {}
+
+       integer_range(uint64_t lower_bound_, uint64_t upper_bound_)
+               : is_signed(false), lower_bound(lower_bound_), upper_bound(upper_bound_)
+       {}
+
+       const bool is_signed;
+       const int64_t lower_bound, upper_bound;
+};
+
+struct integer_range_set
+{
+       using vec_type = std::vector<integer_range>;
+       using const_iterator = vec_type::const_iterator;
+
+       integer_range_set() = default;
+       DISABLE_COPY_AND_ASSIGN(integer_range_set);
+       integer_range_set(integer_range_set &&) = default;
+
+       void add_range(int64_t lower_bound, int64_t upper_bound)
+       {
+               _ranges.emplace_back(lower_bound, upper_bound);
+       }
+
+       void add_range(uint64_t lower_bound, uint64_t upper_bound)
+       {
+               _ranges.emplace_back(lower_bound, upper_bound);
+       }
+
+       const_iterator begin() const
+       { return _ranges.begin(); }
+
+       const_iterator end() const
+       { return _ranges.end(); }
+
+private:
+       vec_type _ranges;
+};
+
+struct enumeration_mapping
+{
+       enumeration_mapping(const char *name_, json ranges_)
+               : name(name_), ranges(std::move(ranges_))
+       {}
+
+       const char *const name;
+       json ranges;
+};
+
+struct enumeration_mappings
+{
+       using vec_type = std::vector<enumeration_mapping>;
+       using const_iterator = vec_type::const_iterator;
+
+       enumeration_mappings() = default;
+       DISABLE_COPY_AND_ASSIGN(enumeration_mappings);
+       enumeration_mappings(enumeration_mappings &&) = default;
+
+       void add_mapping(const char *name_, json ranges_)
+       {
+               _mappings.emplace_back(name_, std::move(ranges_));
+       }
+
+       const_iterator begin() const
+       { return _mappings.begin(); }
+
+       const_iterator end() const
+       { return _mappings.end(); }
+
+private:
+       vec_type _mappings;
+};
+
+static
+json make_integer_range_set(const integer_range_set &ranges)
+{
+       json rs = json::array();
+
+       for (const integer_range &range : ranges) {
+               rs.push_back({ range.lower_bound, range.upper_bound });
+       }
+
+       return rs;
+}
+
+static json
+make_enumeration_mappings(enumeration_mappings mappings)
+{
+       json mappings_obj = json::object();
+
+       for (const enumeration_mapping &mapping : mappings) {
+               mappings_obj[mapping.name] = std::move(mapping.ranges);
+       }
+
+       return mappings_obj;
+}
+
 static
-int _lttng_field_statedump(struct ust_registry_session *session,
-               const struct lttng_ust_ctl_field *fields, size_t nr_fields,
-               size_t *iter_field, size_t nesting);
+json make_abstract_enumeration_field_class(display_base preferred_display_base,
+               enumeration_mappings mappings)
+{
+       json fc = make_abstract_integer_field_class(preferred_display_base);
+       fc["mappings"] = make_enumeration_mappings(std::move(mappings));
+       return fc;
+}
+
+
+static
+json make_fixed_length_unsigned_enumeration_field_class(bits length,
+               byte_order byte_order, bits alignment,
+               display_base preferred_display_base, const char *role,
+               enumeration_mappings mappings)
+{
+       json fc = make_fixed_length_unsigned_integer_field_class(
+               "fixed-length-unsigned-enumeration", length, byte_order,
+               alignment, preferred_display_base, role);
+       fc.update(make_abstract_enumeration_field_class(preferred_display_base,
+               std::move(mappings)));
+       return fc;
+}
+
+static
+json make_fixed_length_signed_enumeration_field_class(bits length,
+               byte_order byte_order, bits alignment,
+               display_base preferred_display_base, const char *role,
+               enumeration_mappings mappings)
+{
+       json fc = make_fixed_length_signed_integer_field_class(
+               "fixed-length-signed-enumeration", length, byte_order,
+               alignment, preferred_display_base, role);
+       fc.update(make_abstract_enumeration_field_class(preferred_display_base,
+               std::move(mappings)));
+       return fc;
+}
+
+static
+json make_fixed_length_enumeration_field_class(bool signedness,
+               bits length, byte_order byte_order, bits alignment,
+               display_base preferred_display_base,
+               enumeration_mappings mappings)
+{
+       if (signedness) {
+               return make_fixed_length_signed_enumeration_field_class(
+                       length, byte_order, alignment, preferred_display_base,
+                       nullptr, std::move(mappings));
+       } else {
+               return make_fixed_length_unsigned_enumeration_field_class(
+                       length, byte_order, alignment, preferred_display_base,
+                       nullptr, std::move(mappings));
+       }
+}
+
+static
+json make_static_length_blob_field_class(uint64_t length, const char *role)
+{
+       json fc = make_field_class("static-length-blob", role);
+
+       fc.update({
+               { "length", length },
+       });
+
+       return fc;
+}
+
+static
+json make_uuid_field_class(const char *role)
+{
+       return make_static_length_blob_field_class(16, role);
+}
+
+struct structure_member
+{
+       structure_member(const char *name_, json field_class_)
+               : name(name_), field_class(std::move(field_class_))
+       {}
+
+       DISABLE_COPY_AND_ASSIGN(structure_member);
+       structure_member(structure_member &&) = default;
+
+       const char *const name;
+       json field_class;
+};
+
+struct structure_members
+{
+       using vec_type = std::vector<structure_member>;
+
+       structure_members() = default;
+       structure_members(const structure_members &) = delete;
+       structure_members(structure_members &&) = default;
+       structure_members &operator=(const structure_members &) = delete;
+
+       void add_member(const char *name, json field_class)
+       {
+               _members.emplace_back(structure_member(
+                       name, std::move(field_class)
+               ));
+       }
+
+       vec_type::iterator begin()
+       { return _members.begin (); }
+
+       vec_type::iterator end()
+       { return _members.end (); }
+
+private:
+       vec_type _members;
+};
+
+static
+json make_struct_member(structure_member member)
+{
+       return {
+               { "name", member.name },
+               { "field-class", std::move(member.field_class) },
+       };
+}
+
+static
+json make_structure_members(structure_members members)
+{
+       json members_obj = json::array();
+
+       for (structure_member &member : members) {
+               members_obj.push_back(make_struct_member(std::move(member)));
+       }
+
+       return members_obj;
+}
+
+static
+json make_structure_field_class(bits minimum_alignment,
+               structure_members members)
+{
+       json fc = make_field_class("structure", nullptr);
+
+       fc["member-classes"] = make_structure_members(std::move(members));
+
+       if (minimum_alignment != 0_bits) {
+               fc["minimum-alignment"] = minimum_alignment.to_underlying();
+       }
+
+       return fc;
+}
+
+
+struct variant_option
+{
+       variant_option(const char *name_,
+                       json selector_field_ranges_,
+                       json field_class_)
+               : name(name_),
+                       selector_field_ranges(std::move(selector_field_ranges_)),
+                       field_class(std::move(field_class_))
+       {}
+
+       variant_option(std::string name_,
+                       json selector_field_ranges_,
+                       json field_class_)
+               : _name_buf(std::move(name_)),
+                       name(_name_buf.c_str()),
+                       selector_field_ranges(std::move(selector_field_ranges_)),
+                       field_class(std::move(field_class_))
+       {}
+
+       DISABLE_COPY_AND_ASSIGN(variant_option);
+
+       variant_option(variant_option &&other)
+               : _name_buf(std::move(other._name_buf)),
+                       /*
+                        * If `_name_buf` is empty, `name` is not managed by us,
+                        * just copy the pointer.  If `_name_buf` is not empty,
+                        * make `name` point to our local copy.
+                        */
+                       name(_name_buf.empty() ? other.name : _name_buf.c_str()),
+                       selector_field_ranges(other.selector_field_ranges),
+                       field_class(other.field_class)
+
+       {}
+
+private:
+       /*
+        * Buffer for `name`, if it is dynamically allocated andmanaged by us.
+        */
+       const std::string _name_buf;
+
+public:
+       const char *name;
+       json selector_field_ranges;
+       json field_class;
+};
+
+struct variant_options
+{
+       using vec_type = std::vector<variant_option>;
+       using iterator = vec_type::iterator;
+       using const_iterator = vec_type::const_iterator;
+
+       variant_options() = default;
+       DISABLE_COPY_AND_ASSIGN(variant_options);
+       variant_options(variant_options &&) = default;
+
+       void add_option(const char *name, json selector_field_ranges,
+                       json field_class)
+       {
+               _options.emplace_back(variant_option(
+                       name, std::move(selector_field_ranges),
+                       std::move(field_class)
+               ));
+       }
+
+       void add_option(std::string name, json selector_field_ranges,
+                       json field_class)
+       {
+               _options.emplace_back(variant_option(
+                       std::move(name), std::move(selector_field_ranges),
+                       std::move(field_class)
+               ));
+       }
+
+       iterator begin()
+       { return _options.begin(); }
+
+       iterator end()
+       { return _options.end(); }
+
+       const_iterator begin() const
+       { return _options.begin(); }
+
+       const_iterator end() const
+       { return _options.end(); }
+
+private:
+       vec_type _options;
+};
+
+struct field_path
+{
+       using vec_type = std::vector<const char *>;
+
+       struct popper
+       {
+               popper(struct field_path &path)
+                       : _path(path)
+               {}
+
+               popper(const popper &) = delete;
+               popper(popper &&) = default;
+               void operator=(const popper &) = delete;
+
+               ~popper()
+               {
+                       _path._path.pop_back();
+
+               }
+
+       private:
+               field_path &_path;
+       };
+
+       field_path(const char *root)
+               : _path({root})
+       {}
+
+       field_path(std::initializer_list<const char *> list)
+               : _path(list)
+       {}
+
+       const vec_type &path() const
+       {
+               return _path;
+       }
+
+       popper push(const char *element)
+       {
+               _path.push_back(element);
+               return popper(*this);
+       }
+
+private:
+       vec_type _path;
+};
+
+static
+json make_variant_option(variant_option option)
+{
+       return {
+               { "name", option.name },
+               { "selector-field-ranges", std::move(option.selector_field_ranges) },
+               { "field-class", std::move(option.field_class ) },
+       };
+}
+
+static
+json make_variant_options(variant_options options)
+{
+       json options_obj = json::array();
+
+       for (variant_option &option : options) {
+               options_obj.push_back(make_variant_option(std::move(option)));
+       }
+
+       return options_obj;
+}
+
+static
+json make_field_location(const field_path &field_location)
+{
+       return field_location.path();
+}
+
+static
+json make_variant_field_class(variant_options options,
+               const field_path &selector_field_location)
+{
+       json fc = make_field_class("variant", nullptr);
+
+       fc["options"] = make_variant_options(std::move(options));
+       fc["selector-field-location"] =
+               make_field_location(selector_field_location);
+
+       return fc;
+}
+
+static
+json make_array_field_class(const char *type, json element_field_class,
+               bits minimum_alignment)
+{
+       json fc = make_field_class(type, nullptr);
+
+       fc["element-field-class"] = std::move(element_field_class);
+
+       if (minimum_alignment != 0_bits) {
+               fc["minimum-alignment"] = minimum_alignment.to_underlying();
+       }
+
+       return fc;
+}
+
+static
+json make_static_length_array_field_class(json element_field_class,
+               uint64_t length, bits minimum_alignment)
+{
+       json fc = make_array_field_class("static-length-array",
+               element_field_class, minimum_alignment);
+
+       fc["length"] = length;
+
+       return fc;
+}
+
+static
+json make_dynamic_length_array_field_class(json element_field_class,
+       const field_path &length_field_location, bits minimum_alignment)
+{
+       json fc = make_array_field_class("dynamic-length-array",
+               element_field_class, minimum_alignment);
+
+       fc["length-field-location"] =
+               make_field_location(length_field_location);
+
+       return fc;
+}
+
+static
+json make_string_field_class()
+{
+       return make_field_class("null-terminated-string", nullptr);
+}
+
+static
+json make_packet_header_field_class(const ust_registry_session &session)
+{
+       byte_order bo = get_byte_order(session, false);
+
+       structure_members members;
+
+       members.add_member("magic",
+               make_fixed_length_unsigned_integer_field_class(
+                       32_bits, bo, 8_bits, display_base::HEXADECIMAL,
+                       "packet-magic-number"));
+       members.add_member("uuid",
+               make_uuid_field_class("trace-class-uuid"));
+       members.add_member("stream_id",
+               make_fixed_length_unsigned_integer_field_class(
+                       32_bits, bo, 8_bits, display_base::DECIMAL,
+                       "data-stream-class-id"));
+       members.add_member("stream_instance_id",
+               make_fixed_length_unsigned_integer_field_class(
+                       64_bits, bo, 8_bits, display_base::DECIMAL,
+                       "data-stream-id"));
+
+       return make_structure_field_class(0_bits, std::move(members));
+}
+
+static
+json make_uuid(uint8_t uuid_bytes[LTTNG_UUID_LEN])
+{
+       json uuid = json::array();
+
+       for (size_t i = 0; i < LTTNG_UUID_LEN; ++i) {
+               uuid.push_back(uuid_bytes[i]);
+       }
+
+       return uuid;
+}
+
+static
+json make_clock_offset(int64_t offset_cycles, uint64_t freq)
+{
+       // FIXME: not tested at all, especially not for negative values of offset
+
+       /* Whole seconds. */
+       int64_t s = offset_cycles / freq;
+
+       /* Remaining cycles. */
+       int64_t cycles = offset_cycles % freq;
+
+       return {
+               { "seconds", s },
+               { "cycles", cycles },
+       };
+}
 
 static inline
 int get_count_order(unsigned int count)
@@ -53,11 +809,11 @@ int get_count_order(unsigned int count)
  * Returns offset where to write in metadata array, or negative error value on error.
  */
 static
-ssize_t metadata_reserve(struct ust_registry_session *session, size_t len)
+ssize_t metadata_reserve(ust_registry_session &session, size_t len)
 {
-       size_t new_len = session->metadata_len + len;
+       size_t new_len = session.metadata_len + len;
        size_t new_alloc_len = new_len;
-       size_t old_alloc_len = session->metadata_alloc_len;
+       size_t old_alloc_len = session.metadata_alloc_len;
        ssize_t ret;
 
        if (new_alloc_len > (UINT32_MAX >> 1))
@@ -69,31 +825,31 @@ ssize_t metadata_reserve(struct ust_registry_session *session, size_t len)
                char *newptr;
 
                new_alloc_len =
-                       max_t(size_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1);
-               newptr = (char *) realloc(session->metadata, new_alloc_len);
+                       std::max<size_t>(1U << get_count_order(new_alloc_len), old_alloc_len << 1);
+               newptr = (char *) realloc(session.metadata, new_alloc_len);
                if (!newptr)
                        return -ENOMEM;
-               session->metadata = newptr;
+               session.metadata = newptr;
                /* We zero directly the memory from start of allocation. */
-               memset(&session->metadata[old_alloc_len], 0, new_alloc_len - old_alloc_len);
-               session->metadata_alloc_len = new_alloc_len;
+               memset(&session.metadata[old_alloc_len], 0, new_alloc_len - old_alloc_len);
+               session.metadata_alloc_len = new_alloc_len;
        }
-       ret = session->metadata_len;
-       session->metadata_len += len;
+       ret = session.metadata_len;
+       session.metadata_len += len;
        return ret;
 }
 
 static
-int metadata_file_append(struct ust_registry_session *session,
+int metadata_file_append(ust_registry_session &session,
                const char *str, size_t len)
 {
        ssize_t written;
 
-       if (session->metadata_fd < 0) {
+       if (session.metadata_fd < 0) {
                return 0;
        }
        /* Write to metadata file */
-       written = lttng_write(session->metadata_fd, str, len);
+       written = lttng_write(session.metadata_fd, str, len);
        if (written != len) {
                return -1;
        }
@@ -107,7 +863,7 @@ int metadata_file_append(struct ust_registry_session *session,
  * protects us from concurrent writes.
  */
 static ATTR_FORMAT_PRINTF(2, 3)
-int lttng_metadata_printf(struct ust_registry_session *session,
+int lttng_metadata_printf(ust_registry_session &session,
                const char *fmt, ...)
 {
        char *str = NULL;
@@ -128,7 +884,7 @@ int lttng_metadata_printf(struct ust_registry_session *session,
                ret = offset;
                goto end;
        }
-       memcpy(&session->metadata[offset], str, len);
+       memcpy(&session.metadata[offset], str, len);
        ret = metadata_file_append(session, str, len);
        if (ret) {
                PERROR("Error appending to metadata file");
@@ -142,698 +898,449 @@ end:
        return ret;
 }
 
+
 static
-int print_tabs(struct ust_registry_session *session, size_t nesting)
+void lttng_metadata_print_fragment(ust_registry_session &session,
+               const json &fragment)
 {
-       size_t i;
-
-       for (i = 0; i < nesting; i++) {
-               int ret;
-
-               ret = lttng_metadata_printf(session, "  ");
-               if (ret) {
-                       return ret;
-               }
-       }
-       return 0;
+       lttng_metadata_printf(session, "\x1e%s", fragment.dump(2).c_str());
 }
 
 static
-void sanitize_ctf_identifier(char *out, const char *in)
+display_base int_to_display_base(int base)
 {
-       size_t i;
-
-       for (i = 0; i < LTTNG_UST_ABI_SYM_NAME_LEN; i++) {
-               switch (in[i]) {
-               case '.':
-               case '$':
-               case ':':
-                       out[i] = '_';
-                       break;
-               default:
-                       out[i] = in[i];
-               }
+       /* If we ever get an invalid value, default to 10. */
+       switch (base) {
+       case 2:
+               return display_base::BINARY;
+       case 8:
+               return display_base::OCTAL;
+       default:
+       case 10:
+               return display_base::DECIMAL;
+       case 16:
+               return display_base::HEXADECIMAL;
        }
 }
 
 static
-int print_escaped_ctf_string(struct ust_registry_session *session, const char *string)
-{
-       int ret = 0;
-       size_t i;
-       char cur;
-
-       i = 0;
-       cur = string[i];
-       while (cur != '\0') {
-               switch (cur) {
-               case '\n':
-                       ret = lttng_metadata_printf(session, "%s", "\\n");
-                       break;
-               case '\\':
-               case '"':
-                       ret = lttng_metadata_printf(session, "%c", '\\');
-                       if (ret) {
-                               goto error;
-                       }
-                       /* We still print the current char */
-                       /* Fallthrough */
-               default:
-                       ret = lttng_metadata_printf(session, "%c", cur);
-                       break;
-               }
-
-               if (ret) {
-                       goto error;
-               }
-
-               cur = string[++i];
+json make_ust_integer_field_class(const ust_registry_session &session,
+       const lttng_ust_ctl_integer_type &type)
+{
+       if (type.signedness) {
+               return make_fixed_length_signed_integer_field_class(
+                       bits(type.size), get_byte_order(session, type.reverse_byte_order),
+                       bits(type.alignment), int_to_display_base(type.base),
+                       nullptr);
+       } else {
+               return make_fixed_length_unsigned_integer_field_class(
+                       bits(type.size), get_byte_order(session, type.reverse_byte_order),
+                       bits(type.alignment), int_to_display_base(type.base),
+                       nullptr);
        }
-error:
-       return ret;
 }
 
 /* Called with session registry mutex held. */
 static
-int ust_metadata_enum_statedump(struct ust_registry_session *session,
-               const char *enum_name,
-               uint64_t enum_id,
-               const struct lttng_ust_ctl_integer_type *container_type,
-               const char *field_name, size_t *iter_field, size_t nesting)
-{
-       struct ust_registry_enum *reg_enum;
-       const struct lttng_ust_ctl_enum_entry *entries;
-       size_t nr_entries;
-       int ret = 0;
-       size_t i;
-       char identifier[LTTNG_UST_ABI_SYM_NAME_LEN];
-
+json make_ust_enum_field_class(const ust_registry_session &session,
+               const char *name, uint64_t id,
+               const lttng_ust_ctl_integer_type &container)
+{
        rcu_read_lock();
-       reg_enum = ust_registry_lookup_enum_by_id(session, enum_name, enum_id);
+       const ust_registry_enum *reg_enum = ust_registry_lookup_enum_by_id(
+               session, name, id);
        rcu_read_unlock();
+
        /* reg_enum can still be used because session registry mutex is held. */
        if (!reg_enum) {
-               ret = -ENOENT;
-               goto end;
+               return -ENOENT;
        }
-       entries = reg_enum->entries;
-       nr_entries = reg_enum->nr_entries;
 
-       ret = print_tabs(session, nesting);
-       if (ret) {
-               goto end;
-       }
-       ret = lttng_metadata_printf(session,
-               "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n",
-               container_type->size,
-               container_type->alignment,
-               container_type->signedness,
-               (container_type->encoding == lttng_ust_ctl_encode_none)
-                       ? "none"
-                       : (container_type->encoding == lttng_ust_ctl_encode_UTF8)
-                               ? "UTF8"
-                               : "ASCII",
-               container_type->base);
-       if (ret) {
-               goto end;
+       bool is_signed = container.signedness;
+       enumeration_mappings mappings;
+
+       const lttng_ust_ctl_enum_entry *entries = reg_enum->entries;
+
+       union {
+               int64_t sign;
+               uint64_t nosign;
+       } next_auto_low_bound;
+
+       if (is_signed) {
+               next_auto_low_bound.sign = 0;
+       } else {
+               next_auto_low_bound.nosign = 0;
        }
-       nesting++;
-       /* Dump all entries */
-       for (i = 0; i < nr_entries; i++) {
-               const struct lttng_ust_ctl_enum_entry *entry = &entries[i];
-               int j, len;
-
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-                               "\"");
-               if (ret) {
-                       goto end;
-               }
-               len = strlen(entry->string);
-               /* Escape the character '"' */
-               for (j = 0; j < len; j++) {
-                       char c = entry->string[j];
-
-                       switch (c) {
-                       case '"':
-                               ret = lttng_metadata_printf(session,
-                                               "\\\"");
-                               break;
-                       case '\\':
-                               ret = lttng_metadata_printf(session,
-                                               "\\\\");
-                               break;
-                       default:
-                               ret = lttng_metadata_printf(session,
-                                               "%c", c);
-                               break;
-                       }
-                       if (ret) {
-                               goto end;
-                       }
-               }
-               ret = lttng_metadata_printf(session, "\"");
-               if (ret) {
-                       goto end;
-               }
 
-               if (entry->u.extra.options &
-                               LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
-                       ret = lttng_metadata_printf(session, ",\n");
-                       if (ret) {
-                               goto end;
-                       }
-               } else {
-                       ret = lttng_metadata_printf(session,
-                                       " = ");
-                       if (ret) {
-                               goto end;
-                       }
+       for (size_t i = 0; i < reg_enum->nr_entries; ++i) {
+               const lttng_ust_ctl_enum_entry &entry = entries[i];
 
-                       if (entry->start.signedness) {
-                               ret = lttng_metadata_printf(session,
-                                       "%" PRId64, entry->start.value);
-                       } else {
-                               ret = lttng_metadata_printf(session,
-                                       "%" PRIu64, entry->start.value);
-                       }
-                       if (ret) {
-                               goto end;
-                       }
+               //len = strlen(entry->string);
 
-                       if (entry->start.signedness == entry->end.signedness &&
-                                       entry->start.value ==
-                                               entry->end.value) {
-                               ret = lttng_metadata_printf(session, ",\n");
+               if (entry.u.extra.options &
+                               LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
+                       if (is_signed) {
+                               integer_range_set rs;
+                               rs.add_range(next_auto_low_bound.sign, next_auto_low_bound.sign);
+                               mappings.add_mapping(entry.string, make_integer_range_set(rs));
+                               ++next_auto_low_bound.sign;
                        } else {
-                               if (entry->end.signedness) {
-                                       ret = lttng_metadata_printf(session,
-                                               " ... %" PRId64 ",\n",
-                                               entry->end.value);
-                               } else {
-                                       ret = lttng_metadata_printf(session,
-                                               " ... %" PRIu64 ",\n",
-                                               entry->end.value);
-                               }
+                               integer_range_set rs;
+                               rs.add_range(next_auto_low_bound.nosign, next_auto_low_bound.nosign);
+                               mappings.add_mapping(entry.string, make_integer_range_set(rs));
+                               ++next_auto_low_bound.nosign;
                        }
-                       if (ret) {
-                               goto end;
+               } else {
+                       if (is_signed) {
+                               integer_range_set rs;
+                               // FIXME: not sure if those casts work as intended.
+                               rs.add_range((int64_t) entry.start.value, (int64_t) entry.end.value);
+                               mappings.add_mapping(entry.string, make_integer_range_set(rs));
+                       } else {
+                               integer_range_set rs;
+                               rs.add_range(entry.start.value, entry.end.value);
+                               mappings.add_mapping(entry.string, make_integer_range_set(rs));
                        }
                }
        }
-       nesting--;
-       sanitize_ctf_identifier(identifier, field_name);
-       ret = print_tabs(session, nesting);
-       if (ret) {
-               goto end;
-       }
-       ret = lttng_metadata_printf(session, "} _%s;\n",
-                       identifier);
-end:
-       (*iter_field)++;
-       return ret;
+
+       return make_fixed_length_enumeration_field_class(
+               is_signed, bits(container.size),
+               get_byte_order(session, container.reverse_byte_order),
+               bits(container.alignment), int_to_display_base(container.base),
+               std::move(mappings));
 }
 
 static
-int _lttng_variant_statedump(struct ust_registry_session *session,
-               uint32_t nr_choices, const char *tag_name,
-               uint32_t alignment,
-               const struct lttng_ust_ctl_field *fields, size_t nr_fields,
-               size_t *iter_field, size_t nesting)
-{
-       const struct lttng_ust_ctl_field *variant = &fields[*iter_field];
-       uint32_t i;
-       int ret;
-       char identifier[LTTNG_UST_ABI_SYM_NAME_LEN];
+void make_ust_field_class(const ust_registry_session &session,
+               lttng_ust_ctl_field_iterator &field_iterator,
+               field_path &current_field_path,
+               std::function<void(const char *, json)> add_field,
+               std::function<const json &(const char *)> get_last_field);
 
-       if (variant->type.atype != lttng_ust_ctl_atype_variant) {
-               ret = -EINVAL;
-               goto end;
-       }
-       (*iter_field)++;
-       sanitize_ctf_identifier(identifier, tag_name);
-       if (alignment) {
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-               "struct { } align(%u) _%s_padding;\n",
-                               alignment * CHAR_BIT,
-                               variant->name);
-               if (ret) {
-                       goto end;
-               }
-       }
-       ret = print_tabs(session, nesting);
-       if (ret) {
-               goto end;
-       }
-       ret = lttng_metadata_printf(session,
-                       "variant <_%s> {\n",
-                       identifier);
-       if (ret) {
-               goto end;
-       }
+static
+void make_ust_variant_field_class(
+               const ust_registry_session &session,
+               lttng_ust_ctl_field_iterator &field_iterator,
+               field_path &current_field_path,
+               const char *field_name,
+               uint32_t nr_options,
+               const char *selector_name,
+               std::function<void(const char *, json)> add_field,
+               std::function<const json &(const char *)> lookup_field)
+{
+       variant_options options;
+       const json &selector_field = lookup_field (selector_name);
+       const json &mappings = selector_field["mappings"];
+
+       auto this_add_field = [&options, &mappings] (const char *option_name, json option_fc) {
+               /* UST prefixes the enumerators with and underscore.  */
+               std::string option_name_prefixed = std::string("_") + option_name;
+               const json &ranges = mappings[option_name_prefixed];
+               /*
+                * In CTF 1.8, the variant options were prefixed with an
+                * underscore to match the enumerator names.  It is not
+                * necessary to do it in CTF 2, as variant options don't rely
+                * on their names matchin an enumerator name.  But do it anyway
+                * to keep the old names, which may help readers migrating from
+                * 1.8 to 2.
+                */
+               options.add_option(std::move(option_name_prefixed), ranges, option_fc);
+       };
 
-       for (i = 0; i < nr_choices; i++) {
-               if (*iter_field >= nr_fields) {
-                       ret = -EOVERFLOW;
-                       goto end;
-               }
-               ret = _lttng_field_statedump(session,
-                               fields, nr_fields,
-                               iter_field, nesting + 1);
-               if (ret) {
-                       goto end;
+       {
+               auto field_location_popper = current_field_path.push(field_name);
+
+               for (uint32_t i = 0; i < nr_options; i++) {
+                       make_ust_field_class(session, field_iterator,
+                               current_field_path, this_add_field, lookup_field);
                }
        }
-       sanitize_ctf_identifier(identifier, variant->name);
-       ret = print_tabs(session, nesting);
-       if (ret) {
-               goto end;
-       }
-       ret = lttng_metadata_printf(session,
-                       "} _%s;\n",
-                       identifier);
-       if (ret) {
-               goto end;
-       }
-end:
-       return ret;
+
+       auto field_location_popper = current_field_path.push(selector_name);
+       add_field(field_name,
+               make_variant_field_class(std::move(options), current_field_path));
 }
 
 static
-int _lttng_field_statedump(struct ust_registry_session *session,
-               const struct lttng_ust_ctl_field *fields, size_t nr_fields,
-               size_t *iter_field, size_t nesting)
-{
-       int ret = 0;
-       const char *bo_be = " byte_order = be;";
-       const char *bo_le = " byte_order = le;";
-       const char *bo_native = "";
-       const char *bo_reverse;
-       const struct lttng_ust_ctl_field *field;
-
-       if (*iter_field >= nr_fields) {
-               ret = -EOVERFLOW;
-               goto end;
-       }
-       field = &fields[*iter_field];
-
-       if (session->byte_order == BIG_ENDIAN) {
-               bo_reverse = bo_le;
-       } else {
-               bo_reverse = bo_be;
-       }
+void make_ust_field_class(const ust_registry_session &session,
+               lttng_ust_ctl_field_iterator &field_iterator,
+               field_path &current_field_path,
+               std::function<void(const char *, json)> add_field,
+               std::function<const json &(const char *)> lookup_field)
+{
+       const lttng_ust_ctl_field &field = field_iterator.get_next();
 
-       switch (field->type.atype) {
+       switch (field.type.atype) {
        case lttng_ust_ctl_atype_integer:
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
-                       field->type.u.integer.size,
-                       field->type.u.integer.alignment,
-                       field->type.u.integer.signedness,
-                       (field->type.u.integer.encoding == lttng_ust_ctl_encode_none)
-                               ? "none"
-                               : (field->type.u.integer.encoding == lttng_ust_ctl_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII",
-                       field->type.u.integer.base,
-                       field->type.u.integer.reverse_byte_order ? bo_reverse : bo_native,
-                       field->name);
-               (*iter_field)++;
+               add_field(field.name,
+                       make_ust_integer_field_class(session,
+                               field.type.u.integer));
                break;
+
        case lttng_ust_ctl_atype_enum:
-               ret = ust_metadata_enum_statedump(session,
-                       field->type.u.legacy.basic.enumeration.name,
-                       field->type.u.legacy.basic.enumeration.id,
-                       &field->type.u.legacy.basic.enumeration.container_type,
-                       field->name, iter_field, nesting);
+       {
+               const auto &enumeration = field.type.u.legacy.basic.enumeration;
+               add_field(field.name,
+                       make_ust_enum_field_class(session,
+                               enumeration.name, enumeration.id,
+                               enumeration.container_type));
                break;
+       }
+
        case lttng_ust_ctl_atype_float:
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-                       "floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
-                       field->type.u._float.exp_dig,
-                       field->type.u._float.mant_dig,
-                       field->type.u._float.alignment,
-                       field->type.u._float.reverse_byte_order ? bo_reverse : bo_native,
-                       field->name);
-               (*iter_field)++;
+       {
+               const lttng_ust_ctl_float_type &t = field.type.u._float;
+
+               add_field(field.name,
+                       make_fixed_length_floating_point_number_field_class(
+                       bits(t.exp_dig + t.mant_dig),
+                       get_byte_order(session, t.reverse_byte_order), bits(t.alignment)));
+
                break;
+       }
+
        case lttng_ust_ctl_atype_array:
        {
-               const struct lttng_ust_ctl_basic_type *elem_type;
+               const auto &array_type = field.type.u.legacy.array;
 
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               elem_type = &field->type.u.legacy.array.elem_type;
                /* Only integers are currently supported in arrays. */
-               if (elem_type->atype != lttng_ust_ctl_atype_integer) {
-                       ret = -EINVAL;
-                       goto end;
+               if (array_type.elem_type.atype != lttng_ust_ctl_atype_integer) {
+                       throw metadata_generation_exception(
+                               "array element type not supported");
                }
-               ret = lttng_metadata_printf(session,
-                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
-                       elem_type->u.basic.integer.size,
-                       elem_type->u.basic.integer.alignment,
-                       elem_type->u.basic.integer.signedness,
-                       (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
-                               ? "none"
-                               : (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII",
-                       elem_type->u.basic.integer.base,
-                       elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
-                       field->name, field->type.u.legacy.array.length);
-               (*iter_field)++;
+
+               add_field(field.name, make_static_length_array_field_class(
+                       make_ust_integer_field_class(
+                               session, array_type.elem_type.u.basic.integer),
+                       array_type.length, 0_bits));
+
                break;
        }
+
        case lttng_ust_ctl_atype_array_nestable:
        {
-               uint32_t array_length;
-               const struct lttng_ust_ctl_field *array_nestable;
-               const struct lttng_ust_ctl_type *elem_type;
-
-               array_length = field->type.u.array_nestable.length;
-               (*iter_field)++;
-
-               if (*iter_field >= nr_fields) {
-                       ret = -EOVERFLOW;
-                       goto end;
-               }
-               array_nestable = &fields[*iter_field];
-               elem_type = &array_nestable->type;
+               const struct lttng_ust_ctl_type &element_type =
+                       field_iterator.get_next().type;
 
                /* Only integers are currently supported in arrays. */
-               if (elem_type->atype != lttng_ust_ctl_atype_integer) {
-                       ret = -EINVAL;
-                       goto end;
+               if (element_type.atype != lttng_ust_ctl_atype_integer) {
+                       throw metadata_generation_exception(
+                               "array element type not supported");
                }
 
-               if (field->type.u.array_nestable.alignment) {
-                       ret = print_tabs(session, nesting);
-                       if (ret) {
-                               goto end;
-                       }
-                       ret = lttng_metadata_printf(session,
-                               "struct { } align(%u) _%s_padding;\n",
-                               field->type.u.array_nestable.alignment * CHAR_BIT,
-                               field->name);
-                       if (ret) {
-                               goto end;
-                       }
-               }
+               const auto &array_type = field.type.u.array_nestable;
 
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
-                       elem_type->u.integer.size,
-                       elem_type->u.integer.alignment,
-                       elem_type->u.integer.signedness,
-                       (elem_type->u.integer.encoding == lttng_ust_ctl_encode_none)
-                               ? "none"
-                               : (elem_type->u.integer.encoding == lttng_ust_ctl_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII",
-                       elem_type->u.integer.base,
-                       elem_type->u.integer.reverse_byte_order ? bo_reverse : bo_native,
-                       field->name, array_length);
-               (*iter_field)++;
+               /* The array alignment value we receive is in bytes.  */
+               add_field(field.name,
+                       make_static_length_array_field_class(
+                               make_ust_integer_field_class(
+                                       session, element_type.u.integer),
+                               array_type.length, bits(array_type.alignment * 8)));
                break;
        }
+
        case lttng_ust_ctl_atype_sequence:
        {
-               const struct lttng_ust_ctl_basic_type *elem_type;
-               const struct lttng_ust_ctl_basic_type *length_type;
-
-               elem_type = &field->type.u.legacy.sequence.elem_type;
-               length_type = &field->type.u.legacy.sequence.length_type;
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
+               const auto &t = field.type.u.legacy.sequence;
 
                /* Only integers are currently supported in sequences. */
-               if (elem_type->atype != lttng_ust_ctl_atype_integer) {
-                       ret = -EINVAL;
-                       goto end;
+               if (t.elem_type.atype != lttng_ust_ctl_atype_integer) {
+                       throw metadata_generation_exception(
+                               "sequence element type not supported");
                }
 
-               ret = lttng_metadata_printf(session,
-                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
-                       length_type->u.basic.integer.size,
-                       (unsigned int) length_type->u.basic.integer.alignment,
-                       length_type->u.basic.integer.signedness,
-                       (length_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
-                               ? "none"
-                               : ((length_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII"),
-                       length_type->u.basic.integer.base,
-                       length_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
-                       field->name);
-               if (ret) {
-                       goto end;
-               }
+               const lttng_ust_ctl_integer_type &length_type
+                       = t.length_type.u.basic.integer;
 
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
-                       elem_type->u.basic.integer.size,
-                       (unsigned int) elem_type->u.basic.integer.alignment,
-                       elem_type->u.basic.integer.signedness,
-                       (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
-                               ? "none"
-                               : ((elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII"),
-                       elem_type->u.basic.integer.base,
-                       elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
-                       field->name,
-                       field->name);
-               (*iter_field)++;
+               std::stringstream sstream;
+               sstream << "__" << field.name << "_length";
+               add_field(sstream.str().c_str(),
+                       make_ust_integer_field_class(session, length_type));
+
+               auto popper = current_field_path.push(sstream.str().c_str());
+               add_field(field.name,
+                       make_dynamic_length_array_field_class(
+                               make_ust_integer_field_class(
+                                       session, t.elem_type.u.basic.integer),
+                               current_field_path, 0_bits));
                break;
        }
        case lttng_ust_ctl_atype_sequence_nestable:
        {
-               const struct lttng_ust_ctl_field *sequence_nestable;
-               const struct lttng_ust_ctl_type *elem_type;
-
-               (*iter_field)++;
-               if (*iter_field >= nr_fields) {
-                       ret = -EOVERFLOW;
-                       goto end;
-               }
-               sequence_nestable = &fields[*iter_field];
-               elem_type = &sequence_nestable->type;
+               const struct lttng_ust_ctl_type &element_type =
+                       field_iterator.get_next().type;
 
                /* Only integers are currently supported in sequences. */
-               if (elem_type->atype != lttng_ust_ctl_atype_integer) {
-                       ret = -EINVAL;
-                       goto end;
+               if (element_type.atype != lttng_ust_ctl_atype_integer) {
+                       throw metadata_generation_exception(
+                               "sequence element type not supported");
                }
 
-               if (field->type.u.sequence_nestable.alignment) {
-                       ret = print_tabs(session, nesting);
-                       if (ret) {
-                               goto end;
-                       }
-                       ret = lttng_metadata_printf(session,
-                               "struct { } align(%u) _%s_padding;\n",
-                               field->type.u.sequence_nestable.alignment * CHAR_BIT,
-                               field->name);
-                       if (ret) {
-                               goto end;
-                       }
-               }
-
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-                       "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ _%s ];\n",
-                       elem_type->u.integer.size,
-                       (unsigned int) elem_type->u.integer.alignment,
-                       elem_type->u.integer.signedness,
-                       (elem_type->u.integer.encoding == lttng_ust_ctl_encode_none)
-                               ? "none"
-                               : ((elem_type->u.integer.encoding == lttng_ust_ctl_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII"),
-                       elem_type->u.integer.base,
-                       elem_type->u.integer.reverse_byte_order ? bo_reverse : bo_native,
-                       field->name,
-                       field->type.u.sequence_nestable.length_name);
-               (*iter_field)++;
+               const auto &array_type = field.type.u.sequence_nestable;
+               auto popper = current_field_path.push(
+                       array_type.length_name);
+
+               /* The array alignment value we receive is in bytes.  */
+               add_field(field.name,
+                       make_dynamic_length_array_field_class(
+                               make_ust_integer_field_class(
+                                       session, element_type.u.integer),
+                               current_field_path,
+                               bits(array_type.alignment * 8)));
                break;
        }
+
        case lttng_ust_ctl_atype_string:
-               /* Default encoding is UTF8 */
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-                       "string%s _%s;\n",
-                       field->type.u.string.encoding == lttng_ust_ctl_encode_ASCII ?
-                               " { encoding = ASCII; }" : "",
-                       field->name);
-               (*iter_field)++;
+               add_field(field.name, make_string_field_class());
                break;
+
        case lttng_ust_ctl_atype_variant:
-               ret = _lttng_variant_statedump(session,
-                               field->type.u.legacy.variant.nr_choices,
-                               field->type.u.legacy.variant.tag_name,
-                               0,
-                               fields, nr_fields, iter_field, nesting);
-               if (ret) {
-                       goto end;
-               }
+       {
+               const decltype(field.type.u.legacy.variant) &variant_type =
+                       field.type.u.legacy.variant;
+
+               make_ust_variant_field_class(session, field_iterator,
+                       current_field_path, field.name, variant_type.nr_choices,
+                       variant_type.tag_name, add_field, lookup_field);
                break;
+       }
+
        case lttng_ust_ctl_atype_variant_nestable:
-               ret = _lttng_variant_statedump(session,
-                               field->type.u.variant_nestable.nr_choices,
-                               field->type.u.variant_nestable.tag_name,
-                               field->type.u.variant_nestable.alignment,
-                               fields, nr_fields, iter_field, nesting);
-               if (ret) {
-                       goto end;
-               }
+       {
+               const decltype(field.type.u.variant_nestable) &variant_type =
+                       field.type.u.variant_nestable;
+
+               make_ust_variant_field_class(session, field_iterator,
+                       current_field_path, field.name, variant_type.nr_choices,
+                       variant_type.tag_name, add_field, lookup_field);
                break;
+       }
+
        case lttng_ust_ctl_atype_struct:
-               if (field->type.u.legacy._struct.nr_fields != 0) {
+               if (field.type.u.legacy._struct.nr_fields != 0) {
                        /* Currently only 0-length structures are supported. */
-                       ret = -EINVAL;
-                       goto end;
+                       throw metadata_generation_exception("Only 0-length structures are supported");
                }
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               ret = lttng_metadata_printf(session,
-                       "struct {} _%s;\n",
-                       field->name);
-               (*iter_field)++;
+
+               /* Don't emit anything */
                break;
+
        case lttng_ust_ctl_atype_struct_nestable:
-               if (field->type.u.struct_nestable.nr_fields != 0) {
+               if (field.type.u.struct_nestable.nr_fields != 0) {
                        /* Currently only 0-length structures are supported. */
-                       ret = -EINVAL;
-                       goto end;
-               }
-               ret = print_tabs(session, nesting);
-               if (ret) {
-                       goto end;
-               }
-               if (field->type.u.struct_nestable.alignment) {
-                       ret = lttng_metadata_printf(session,
-                               "struct {} align(%u) _%s;\n",
-                               field->type.u.struct_nestable.alignment * CHAR_BIT,
-                               field->name);
-                       if (ret) {
-                               goto end;
-                       }
-               } else {
-                       ret = lttng_metadata_printf(session,
-                               "struct {} _%s;\n",
-                               field->name);
+                       throw metadata_generation_exception("Only 0-length structures are supported");
                }
-               (*iter_field)++;
+
+               /* Don't emit anything */
                break;
+
        case lttng_ust_ctl_atype_enum_nestable:
        {
-               const struct lttng_ust_ctl_field *container_field;
-               const struct lttng_ust_ctl_type *container_type;
-
-               (*iter_field)++;
-               if (*iter_field >= nr_fields) {
-                       ret = -EOVERFLOW;
-                       goto end;
-               }
-               container_field = &fields[*iter_field];
-               container_type = &container_field->type;
+               const lttng_ust_ctl_field &container =
+                       field_iterator.get_next();
 
                /* Only integers are supported as container types. */
-               if (container_type->atype != lttng_ust_ctl_atype_integer) {
-                       ret = -EINVAL;
-                       goto end;
+               if (container.type.atype != lttng_ust_ctl_atype_integer) {
+                       throw metadata_generation_exception(
+                               "Enumeration container type not an integer");
                }
-               ret = ust_metadata_enum_statedump(session,
-                       field->type.u.enum_nestable.name,
-                       field->type.u.enum_nestable.id,
-                       &container_type->u.integer,
-                       field->name, iter_field, nesting);
+
+               const auto &enumeration = field.type.u.enum_nestable;
+               add_field(field.name,
+                       make_ust_enum_field_class(session,
+                               enumeration.name, enumeration.id,
+                               container.type.u.integer));
                break;
        }
        default:
-               ret = -EINVAL;
+               throw metadata_generation_exception(
+                       "Unhandled lttng-ust field type");
        }
-end:
-       return ret;
 }
 
 static
-int _lttng_context_metadata_statedump(struct ust_registry_session *session,
-               size_t nr_ctx_fields,
-               struct lttng_ust_ctl_field *ctx)
+json make_record_common_context_field_class(
+       const ust_registry_session &session,
+       const ust_registry_channel &chan)
 {
-       int ret = 0;
-       size_t i = 0;
+       lttng_ust_ctl_field_iterator iter(chan.ctx_fields, chan.nr_ctx_fields);
+       field_path fp("event-record-common-context");
+       structure_members members;
 
-       if (!ctx)
-               return 0;
-       for (;;) {
-               if (i >= nr_ctx_fields) {
-                       break;
-               }
-               ret = _lttng_field_statedump(session, ctx,
-                               nr_ctx_fields, &i, 2);
-               if (ret) {
-                       break;
+       auto add_field = [&members] (const char *name, json field_class) {
+               members.add_member(name, field_class);
+       };
+
+       auto lookup_field = [&members] (const char *name) -> const json & {
+               for (const structure_member &member : members) {
+                       if (strcmp(member.name, name) == 0) {
+                               return member.field_class;
+                       }
                }
+
+               throw metadata_generation_exception("failed to look up field");
+       };
+
+       while (!iter.done()) {
+               make_ust_field_class(session, iter, fp, add_field,
+                       lookup_field);
        }
-       return ret;
+
+       return make_structure_field_class(0_bits, std::move(members));
 }
 
 static
-int _lttng_fields_metadata_statedump(struct ust_registry_session *session,
-               struct ust_registry_event *event)
+json make_event_record_class_payload_field_class(
+               const ust_registry_session &session,
+               const ust_registry_event &event)
 {
-       int ret = 0;
-       size_t i = 0;
+       lttng_ust_ctl_field_iterator iter(event.fields, event.nr_fields);
+       field_path fp("event-record-payload");
+       structure_members members;
 
-       for (;;) {
-               if (i >= event->nr_fields) {
-                       break;
-               }
-               ret = _lttng_field_statedump(session, event->fields,
-                               event->nr_fields, &i, 2);
-               if (ret) {
-                       break;
+       auto add_field = [&members] (const char *name, json field_class) {
+               members.add_member(name, field_class);
+       };
+
+       auto lookup_field = [&members] (const char *name) {
+               for (const structure_member &member : members) {
+                       if (strcmp(member.name, name) == 0) {
+                               return member.field_class;
+                       }
                }
+
+               throw metadata_generation_exception("failed to look up field");
+       };
+
+       while (!iter.done()) {
+               make_ust_field_class(session, iter, fp, add_field,
+                       lookup_field);
        }
-       return ret;
+
+       return make_structure_field_class(0_bits, std::move(members));
+}
+
+static
+json make_user_attributes(json attributes)
+{
+       return {
+               { "lttng.org,2009", attributes }
+       };
+}
+
+static
+json make_event_record_class_user_attributes(const ust_registry_event &event)
+{
+       json user_attributes = make_user_attributes({
+               { "log-level", event.loglevel_value },
+       });
+
+       if (event.model_emf_uri) {
+               user_attributes["emf-uri"] = event.model_emf_uri;
+       }
+
+       return user_attributes;
 }
 
 /*
@@ -843,62 +1350,199 @@ int ust_metadata_event_statedump(struct ust_registry_session *session,
                struct ust_registry_channel *chan,
                struct ust_registry_event *event)
 {
-       int ret = 0;
-
        /* Don't dump metadata events */
        if (chan->chan_id == -1U)
                return 0;
 
-       ret = lttng_metadata_printf(session,
-               "event {\n"
-               "       name = \"%s\";\n"
-               "       id = %u;\n"
-               "       stream_id = %u;\n",
-               event->name,
-               event->id,
-               chan->chan_id);
-       if (ret) {
-               goto end;
+       /*
+        * We don't want to output an event's metadata before its parent
+        * stream's metadata.  If the stream's metadata hasn't been output yet,
+        * skip this event.  Its metadata will be output when we output the
+        * stream's metadata.
+        */
+       if (!chan->metadata_dumped) {
+               return 0;
        }
 
-       ret = lttng_metadata_printf(session,
-               "       loglevel = %d;\n",
-               event->loglevel_value);
-       if (ret) {
-               goto end;
-       }
+       LTTNG_ASSERT(!event->metadata_dumped);
+
+       try {
+               json event_record_class = make_fragment("event-record-class");
+               event_record_class.update({
+                       { "name", event->name },
+                       { "id", event->id },
+                       { "data-stream-class-id", chan->chan_id },
+                       { "user-attributes", make_event_record_class_user_attributes(*event) },
+               });
 
-       if (event->model_emf_uri) {
-               ret = lttng_metadata_printf(session,
-                       "       model.emf.uri = \"%s\";\n",
-                       event->model_emf_uri);
-               if (ret) {
-                       goto end;
+               if (event->nr_fields) {
+                       event_record_class["payload-field-class"] =
+                                       make_event_record_class_payload_field_class(*session, *event);
                }
-       }
 
-       ret = lttng_metadata_printf(session,
-               "       fields := struct {\n"
-               );
-       if (ret) {
-               goto end;
-       }
+               lttng_metadata_print_fragment(*session, event_record_class);
 
-       ret = _lttng_fields_metadata_statedump(session, event);
-       if (ret) {
-               goto end;
-       }
+               event->metadata_dumped = 1;
 
-       ret = lttng_metadata_printf(session,
-               "       };\n"
-               "};\n\n");
-       if (ret) {
-               goto end;
+               return 0;
+       } catch (const std::exception &error) {
+               ERR("%s", error.what());
+               return  -LTTNG_ERR_UNK;
+       } catch (...) {
+               return -LTTNG_ERR_UNK;
        }
-       event->metadata_dumped = 1;
+}
 
-end:
-       return ret;
+static
+json make_packet_context_field_class(const ust_registry_session &session)
+{
+       byte_order bo = get_byte_order(session, false);
+       structure_members members;
+
+       members.add_member("timestamp_begin",
+               make_fixed_length_unsigned_integer_field_class(
+                       64_bits, bo, 8_bits, display_base::DECIMAL,
+                       "packet-beginning-default-clock-timestamp"));
+       members.add_member("timestamp_end",
+               make_fixed_length_unsigned_integer_field_class(
+                       64_bits, bo, 8_bits, display_base::DECIMAL,
+                       "packet-end-default-clock-timestamp"));
+       members.add_member("content_size",
+               make_fixed_length_unsigned_integer_field_class(
+                       64_bits, bo, 8_bits, display_base::DECIMAL,
+                       "packet-content-size"));
+       members.add_member("packet_size",
+               make_fixed_length_unsigned_integer_field_class(
+                       64_bits, bo, 8_bits, display_base::DECIMAL,
+                       "packet-total-size"));
+       members.add_member("packet_seq_num",
+               make_fixed_length_unsigned_integer_field_class(
+                       64_bits, bo, 8_bits, display_base::DECIMAL,
+                       "packet-sequence-number"));
+       members.add_member("events_discarded",
+               make_fixed_length_unsigned_integer_field_class(
+                       bits(session.bits_per_long), bo,
+                       bits(session.long_alignment),
+                       display_base::DECIMAL,
+                       "discarded-event-record-counter-snapshot"));
+       members.add_member("cpu_id",
+               make_fixed_length_unsigned_integer_field_class(
+                       32_bits, bo, 8_bits, display_base::DECIMAL, nullptr));
+
+       return make_structure_field_class(0_bits, std::move(members));
+}
+
+static
+json make_record_header_compact_field_class(const ust_registry_session &session)
+{
+       byte_order bo = get_byte_order(session, false);
+
+       structure_members compact_members;
+       compact_members.add_member("timestamp",
+               make_fixed_length_unsigned_integer_field_class(
+                       27_bits, bo, 1_bits, display_base::DECIMAL,
+                       "default-clock-timestamp"));
+
+       structure_members extended_members;
+       extended_members.add_member("id",
+               make_fixed_length_unsigned_integer_field_class(
+                       32_bits, bo, 8_bits, display_base::DECIMAL,
+                       "event-record-class-id"));
+       extended_members.add_member("timestamp",
+               make_fixed_length_unsigned_integer_field_class(
+                       64_bits, bo, 8_bits, display_base::DECIMAL,
+                       "default-clock-timestamp"));
+
+       integer_range_set compact_ranges, extended_ranges;
+       compact_ranges.add_range(UINT64_C(0), 30);
+       extended_ranges.add_range(UINT64_C(31), 31);
+
+       variant_options options;
+       options.add_option("compact",
+               make_integer_range_set(compact_ranges),
+               make_structure_field_class(0_bits, std::move(compact_members)));
+       options.add_option("extended",
+               make_integer_range_set(extended_ranges),
+               make_structure_field_class(0_bits, std::move(extended_members)));
+
+       enumeration_mappings id_mappings;
+       id_mappings.add_mapping("compact",
+               make_integer_range_set(compact_ranges));
+       id_mappings.add_mapping("extended",
+               make_integer_range_set(extended_ranges));
+
+       structure_members members;
+       members.add_member("id",
+               make_fixed_length_unsigned_enumeration_field_class(
+                       5_bits, bo, 8_bits, display_base::DECIMAL,
+                       "event-record-class-id", std::move(id_mappings)));
+       members.add_member("v",
+               make_variant_field_class(std::move(options),
+                       {"event-record-header", "id"}));
+
+       return make_structure_field_class(8_bits, std::move(members));
+}
+
+static
+json make_record_header_large_field_class(const ust_registry_session &session)
+{
+       byte_order bo = get_byte_order(session, false);
+
+       structure_members compact_members;
+       compact_members.add_member("timestamp",
+               make_fixed_length_unsigned_integer_field_class(
+                       32_bits, bo, 8_bits, display_base::DECIMAL,
+                       "default-clock-timestamp"));
+
+       structure_members extended_members;
+       extended_members.add_member("id",
+               make_fixed_length_unsigned_integer_field_class(
+                       32_bits, bo, 8_bits, display_base::DECIMAL,
+                       "event-record-class-id"));
+       extended_members.add_member("timestamp",
+               make_fixed_length_unsigned_integer_field_class(
+                       64_bits, bo, 8_bits, display_base::DECIMAL,
+                       "default-clock-timestamp"));
+
+       integer_range_set compact_ranges, extended_ranges;
+       compact_ranges.add_range(UINT64_C(0), 65534);
+       extended_ranges.add_range(UINT64_C(65535), 65535);
+
+       variant_options options;
+       options.add_option("compact",
+               make_integer_range_set(compact_ranges),
+               make_structure_field_class(0_bits, std::move(compact_members)));
+       options.add_option("extended",
+               make_integer_range_set(extended_ranges),
+               make_structure_field_class(0_bits, std::move(extended_members)));
+
+       enumeration_mappings id_mappings;
+       id_mappings.add_mapping("compact",
+               make_integer_range_set(compact_ranges));
+       id_mappings.add_mapping("extended",
+               make_integer_range_set(extended_ranges));
+
+       structure_members members;
+       members.add_member("id",
+               make_fixed_length_unsigned_enumeration_field_class(
+                       16_bits, bo, 8_bits, display_base::DECIMAL,
+                       "event-record-class-id", std::move(id_mappings)));
+       members.add_member("v",
+               make_variant_field_class(std::move(options),
+                       { "event-record-header", "id" }));
+
+       return make_structure_field_class(8_bits, std::move(members));
+}
+
+static
+json make_record_header_field_class(const ust_registry_session &session,
+               const ust_registry_channel &chan)
+{
+       if (chan.header_type == LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT) {
+               return make_record_header_compact_field_class(session);
+       } else {
+               return make_record_header_large_field_class(session);
+       }
 }
 
 /*
@@ -907,8 +1551,6 @@ end:
 int ust_metadata_channel_statedump(struct ust_registry_session *session,
                struct ust_registry_channel *chan)
 {
-       int ret = 0;
-
        /* Don't dump metadata events */
        if (chan->chan_id == -1U)
                return 0;
@@ -916,106 +1558,60 @@ int ust_metadata_channel_statedump(struct ust_registry_session *session,
        if (!chan->header_type)
                return -EINVAL;
 
-       ret = lttng_metadata_printf(session,
-               "stream {\n"
-               "       id = %u;\n"
-               "       event.header := %s;\n"
-               "       packet.context := struct packet_context;\n",
-               chan->chan_id,
-               chan->header_type == LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT ?
-                       "struct event_header_compact" :
-                       "struct event_header_large");
-       if (ret) {
-               goto end;
-       }
-
-       if (chan->ctx_fields) {
-               ret = lttng_metadata_printf(session,
-                       "       event.context := struct {\n");
-               if (ret) {
-                       goto end;
-               }
-       }
-       ret = _lttng_context_metadata_statedump(session,
-               chan->nr_ctx_fields,
-               chan->ctx_fields);
-       if (ret) {
-               goto end;
-       }
-       if (chan->ctx_fields) {
-               ret = lttng_metadata_printf(session,
-                       "       };\n");
-               if (ret) {
-                       goto end;
+       try {
+               json data_stream_class = make_fragment("data-stream-class");
+               data_stream_class.update({
+                       { "id", chan->chan_id },
+                       { "packet-context-field-class",
+                               make_packet_context_field_class(*session) },
+                       { "event-record-header-field-class",
+                               make_record_header_field_class(*session, *chan) },
+               });
+
+               if (chan->ctx_fields) {
+                       data_stream_class.update({
+                               { "event-record-common-context-field-class",
+                                       make_record_common_context_field_class(*session, *chan) }
+                       });
                }
-       }
 
-       ret = lttng_metadata_printf(session,
-               "};\n\n");
-       /* Flag success of metadata dump. */
-       chan->metadata_dumped = 1;
+               lttng_metadata_print_fragment(*session, data_stream_class);
 
-end:
-       return ret;
-}
+               /* Flag success of metadata dump. */
+               chan->metadata_dumped = 1;
 
-static
-int _lttng_stream_packet_context_declare(struct ust_registry_session *session)
-{
-       return lttng_metadata_printf(session,
-               "struct packet_context {\n"
-               "       uint64_clock_monotonic_t timestamp_begin;\n"
-               "       uint64_clock_monotonic_t timestamp_end;\n"
-               "       uint64_t content_size;\n"
-               "       uint64_t packet_size;\n"
-               "       uint64_t packet_seq_num;\n"
-               "       unsigned long events_discarded;\n"
-               "       uint32_t cpu_id;\n"
-               "};\n\n"
-               );
-}
+               /*
+                * Output the metadata of any existing event.
+                *
+                * Sort the events by id.  This is not necessary, but it's nice to have
+                * a more predictable order in the metadata file.
+                */
+               std::vector<ust_registry_event *> events;
+               {
+                       cds_lfht_iter event_iter;
+                       ust_registry_event *event;
+                       cds_lfht_for_each_entry(chan->events->ht, &event_iter, event,
+                                       node.node) {
+                               events.push_back(event);
+                       }
+               }
 
-/*
- * Compact header:
- * id: range: 0 - 30.
- * id 31 is reserved to indicate an extended header.
- *
- * Large header:
- * id: range: 0 - 65534.
- * id 65535 is reserved to indicate an extended header.
- */
-static
-int _lttng_event_header_declare(struct ust_registry_session *session)
-{
-       return lttng_metadata_printf(session,
-       "struct event_header_compact {\n"
-       "       enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
-       "       variant <id> {\n"
-       "               struct {\n"
-       "                       uint27_clock_monotonic_t timestamp;\n"
-       "               } compact;\n"
-       "               struct {\n"
-       "                       uint32_t id;\n"
-       "                       uint64_clock_monotonic_t timestamp;\n"
-       "               } extended;\n"
-       "       } v;\n"
-       "} align(%u);\n"
-       "\n"
-       "struct event_header_large {\n"
-       "       enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
-       "       variant <id> {\n"
-       "               struct {\n"
-       "                       uint32_clock_monotonic_t timestamp;\n"
-       "               } compact;\n"
-       "               struct {\n"
-       "                       uint32_t id;\n"
-       "                       uint64_clock_monotonic_t timestamp;\n"
-       "               } extended;\n"
-       "       } v;\n"
-       "} align(%u);\n\n",
-       session->uint32_t_alignment,
-       session->uint16_t_alignment
-       );
+               std::sort(events.begin(), events.end(),
+                       [] (ust_registry_event *a, ust_registry_event *b) {
+                               return a->id < b->id;
+                       });
+
+               for (ust_registry_event *event : events) {
+                       ust_metadata_event_statedump(session, chan, event);
+               }
+
+               return 0;
+       } catch (const std::exception &error) {
+               ERR("%s", error.what());
+               return  -LTTNG_ERR_UNK;
+       } catch (...) {
+               return -LTTNG_ERR_UNK;
+       }
 }
 
 /*
@@ -1079,98 +1675,6 @@ int64_t measure_clock_offset(void)
        return offset_best_sample.offset;
 }
 
-static
-int print_metadata_session_information(struct ust_registry_session *registry)
-{
-       int ret;
-       struct ltt_session *session = NULL;
-       char creation_datetime[ISO8601_STR_LEN];
-
-       rcu_read_lock();
-       session = session_find_by_id(registry->tracing_id);
-       if (!session) {
-               ret = -1;
-               goto error;
-       }
-
-       /* Print the trace name */
-       ret = lttng_metadata_printf(registry, " trace_name = \"");
-       if (ret) {
-               goto error;
-       }
-
-       /*
-        * This is necessary since the creation time is present in the session
-        * name when it is generated.
-        */
-       if (session->has_auto_generated_name) {
-               ret = print_escaped_ctf_string(registry, DEFAULT_SESSION_NAME);
-       } else {
-               ret = print_escaped_ctf_string(registry, session->name);
-       }
-       if (ret) {
-               goto error;
-       }
-
-       ret = lttng_metadata_printf(registry, "\";\n");
-       if (ret) {
-               goto error;
-       }
-
-       /* Prepare creation time */
-       ret = time_to_iso8601_str(session->creation_time, creation_datetime,
-                       sizeof(creation_datetime));
-       if (ret) {
-               goto error;
-       }
-
-       /* Output the reste of the information */
-       ret = lttng_metadata_printf(registry,
-                       "       trace_creation_datetime = \"%s\";\n"
-                       "       hostname = \"%s\";\n",
-                       creation_datetime, session->hostname);
-       if (ret) {
-               goto error;
-       }
-
-error:
-       if (session) {
-               session_put(session);
-       }
-       rcu_read_unlock();
-       return ret;
-}
-
-static
-int print_metadata_app_information(struct ust_registry_session *registry,
-               struct ust_app *app)
-{
-       int ret;
-       char datetime[ISO8601_STR_LEN];
-
-       if (!app) {
-               ret = 0;
-               goto end;
-       }
-
-       ret = time_to_iso8601_str(
-                       app->registration_time, datetime, sizeof(datetime));
-       if (ret) {
-               goto end;
-       }
-
-       ret = lttng_metadata_printf(registry,
-                       "       tracer_patchlevel = %u;\n"
-                       "       vpid = %d;\n"
-                       "       procname = \"%s\";\n"
-                       "       vpid_datetime = \"%s\";\n",
-                       app->version.patchlevel, (int) app->pid, app->name,
-                       datetime);
-
-end:
-       return ret;
-}
-
 /*
  * Should be called with session registry mutex held.
  */
@@ -1179,166 +1683,53 @@ int ust_metadata_session_statedump(struct ust_registry_session *session,
                uint32_t major,
                uint32_t minor)
 {
-       char uuid_s[LTTNG_UUID_STR_LEN],
-               clock_uuid_s[LTTNG_UUID_STR_LEN];
-       int ret = 0;
-
        LTTNG_ASSERT(session);
 
-       lttng_uuid_to_str(session->uuid, uuid_s);
-
-       /* For crash ABI */
-       ret = lttng_metadata_printf(session,
-               "/* CTF %u.%u */\n\n",
-               CTF_SPEC_MAJOR,
-               CTF_SPEC_MINOR);
-       if (ret) {
-               goto end;
-       }
-
-       ret = lttng_metadata_printf(session,
-               "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
-               "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
-               "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
-               "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
-               "typealias integer { size = %u; align = %u; signed = false; } := unsigned long;\n"
-               "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
-               "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
-               "\n"
-               "trace {\n"
-               "       major = %u;\n"
-               "       minor = %u;\n"
-               "       uuid = \"%s\";\n"
-               "       byte_order = %s;\n"
-               "       packet.header := struct {\n"
-               "               uint32_t magic;\n"
-               "               uint8_t  uuid[16];\n"
-               "               uint32_t stream_id;\n"
-               "               uint64_t stream_instance_id;\n"
-               "       };\n"
-               "};\n\n",
-               session->uint8_t_alignment,
-               session->uint16_t_alignment,
-               session->uint32_t_alignment,
-               session->uint64_t_alignment,
-               session->bits_per_long,
-               session->long_alignment,
-               CTF_SPEC_MAJOR,
-               CTF_SPEC_MINOR,
-               uuid_s,
-               session->byte_order == BIG_ENDIAN ? "be" : "le"
-               );
-       if (ret) {
-               goto end;
-       }
-
-       ret = lttng_metadata_printf(session,
-               "env {\n"
-               "       domain = \"ust\";\n"
-               "       tracer_name = \"lttng-ust\";\n"
-               "       tracer_major = %u;\n"
-               "       tracer_minor = %u;\n"
-               "       tracer_buffering_scheme = \"%s\";\n"
-               "       tracer_buffering_id = %u;\n"
-               "       architecture_bit_width = %u;\n",
-               major,
-               minor,
-               app ? "pid" : "uid",
-               app ? (int) app->pid : (int) session->tracing_uid,
-               session->bits_per_long);
-       if (ret) {
-               goto end;
-       }
-
-       ret = print_metadata_session_information(session);
-       if (ret) {
-               goto end;
-       }
-
-       /*
-        * If per-application registry, we can output extra information
-        * about the application.
-        */
-       ret = print_metadata_app_information(session, app);
-       if (ret) {
-               goto end;
-       }
-
-       ret = lttng_metadata_printf(session,
-               "};\n\n"
-               );
-       if (ret) {
-               goto end;
-       }
-
-       ret = lttng_metadata_printf(session,
-               "clock {\n"
-               "       name = \"%s\";\n",
-               trace_clock_name()
-               );
-       if (ret) {
-               goto end;
-       }
-
-       if (!trace_clock_uuid(clock_uuid_s)) {
-               ret = lttng_metadata_printf(session,
-                       "       uuid = \"%s\";\n",
-                       clock_uuid_s
-                       );
-               if (ret) {
-                       goto end;
+       try {
+               json preamble = make_fragment("preamble");
+               preamble.update({
+                       { "version", 2 },
+               });
+               lttng_metadata_print_fragment(*session, preamble);
+
+               json trace_class = make_fragment("trace-class");
+               trace_class.update({
+                       { "packet-header-field-class",
+                               make_packet_header_field_class(*session) },
+                       { "uuid", make_uuid (session->uuid) }
+               });
+               lttng_metadata_print_fragment(*session, trace_class);
+
+               uint64_t clock_freq = trace_clock_freq();
+               json clock_class = make_fragment("clock-class");
+               clock_class.update({
+                       { "name", trace_clock_name() },
+                       { "description", trace_clock_description() },
+                       { "frequency", clock_freq },
+                       { "offset", make_clock_offset(measure_clock_offset(), clock_freq) },
+               });
+
+               char clock_uuid_str[LTTNG_UUID_STR_LEN];
+               int ret = trace_clock_uuid(clock_uuid_str);
+               if (ret == 0) {
+                       uint8_t clock_uuid[LTTNG_UUID_LEN];
+                       ret = lttng_uuid_from_str(clock_uuid_str, clock_uuid);
+                       if (ret == 0) {
+                               clock_class["uuid"] = make_uuid(clock_uuid);
+                       } else {
+                               // FIXME: warn?
+                       }
+               } else {
+                       // FIXME: warn?
                }
-       }
-
-       ret = lttng_metadata_printf(session,
-               "       description = \"%s\";\n"
-               "       freq = %" PRIu64 "; /* Frequency, in Hz */\n"
-               "       /* clock value offset from Epoch is: offset * (1/freq) */\n"
-               "       offset = %" PRId64 ";\n"
-               "};\n\n",
-               trace_clock_description(),
-               trace_clock_freq(),
-               measure_clock_offset()
-               );
-       if (ret) {
-               goto end;
-       }
-
-       ret = lttng_metadata_printf(session,
-               "typealias integer {\n"
-               "       size = 27; align = 1; signed = false;\n"
-               "       map = clock.%s.value;\n"
-               "} := uint27_clock_monotonic_t;\n"
-               "\n"
-               "typealias integer {\n"
-               "       size = 32; align = %u; signed = false;\n"
-               "       map = clock.%s.value;\n"
-               "} := uint32_clock_monotonic_t;\n"
-               "\n"
-               "typealias integer {\n"
-               "       size = 64; align = %u; signed = false;\n"
-               "       map = clock.%s.value;\n"
-               "} := uint64_clock_monotonic_t;\n\n",
-               trace_clock_name(),
-               session->uint32_t_alignment,
-               trace_clock_name(),
-               session->uint64_t_alignment,
-               trace_clock_name()
-               );
-       if (ret) {
-               goto end;
-       }
 
-       ret = _lttng_stream_packet_context_declare(session);
-       if (ret) {
-               goto end;
-       }
+               lttng_metadata_print_fragment(*session, clock_class);
 
-       ret = _lttng_event_header_declare(session);
-       if (ret) {
-               goto end;
+               return 0;
+       } catch (const std::exception &error) {
+               ERR("%s", error.what());
+               return  -LTTNG_ERR_UNK;
+       } catch (...) {
+               return -LTTNG_ERR_UNK;
        }
-
-end:
-       return ret;
 }
index 088e8d64fedfd36e6aa7cba44ecdc74e68df553a..96ce92455e1bb1b7eb99f9d0928075b24df2ba6f 100644 (file)
@@ -8,16 +8,16 @@
 #define _LGPL_SOURCE
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/hashtable/utils.h>
+#include <common/common.hpp>
+#include <common/hashtable/utils.hpp>
 #include <lttng/lttng.h>
 
-#include "ust-registry.h"
-#include "ust-app.h"
-#include "ust-field-utils.h"
-#include "utils.h"
-#include "lttng-sessiond.h"
-#include "notification-thread-commands.h"
+#include "ust-registry.hpp"
+#include "ust-app.hpp"
+#include "ust-field-utils.hpp"
+#include "utils.hpp"
+#include "lttng-sessiond.hpp"
+#include "notification-thread-commands.hpp"
 
 /*
  * Hash table match function for event in the registry.
@@ -367,8 +367,8 @@ struct ust_registry_event *ust_registry_find_event(
        key.name[sizeof(key.name) - 1] = '\0';
        key.signature = sig;
 
-       cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed),
-                       chan->ht->match_fct, &key, &iter.iter);
+       cds_lfht_lookup(chan->events->ht, chan->events->hash_fct(&key, lttng_ht_seed),
+                       chan->events->match_fct, &key, &iter.iter);
        node = lttng_ht_iter_get_node_u64(&iter);
        if (!node) {
                goto end;
@@ -445,8 +445,8 @@ int ust_registry_create_event(struct ust_registry_session *session,
         * This is an add unique with a custom match function for event. The node
         * are matched using the event name and signature.
         */
-       nptr = cds_lfht_add_unique(chan->ht->ht, chan->ht->hash_fct(event,
-                               lttng_ht_seed), chan->ht->match_fct, event, &event->node.node);
+       nptr = cds_lfht_add_unique(chan->events->ht, chan->events->hash_fct(event,
+                               lttng_ht_seed), chan->events->match_fct, event, &event->node.node);
        if (nptr != &event->node.node) {
                if (buffer_type == LTTNG_BUFFER_PER_UID) {
                        /*
@@ -512,7 +512,7 @@ void ust_registry_destroy_event(struct ust_registry_channel *chan,
 
        /* Delete the node first. */
        iter.iter.node = &event->node.node;
-       ret = lttng_ht_del(chan->ht, &iter);
+       ret = lttng_ht_del(chan->events, &iter);
        LTTNG_ASSERT(!ret);
 
        call_rcu(&event->node.head, destroy_event_rcu);
@@ -566,7 +566,7 @@ end:
  * Needs to be called from RCU read-side critical section.
  */
 struct ust_registry_enum *
-       ust_registry_lookup_enum_by_id(struct ust_registry_session *session,
+       ust_registry_lookup_enum_by_id(const ust_registry_session &session,
                const char *enum_name, uint64_t enum_id)
 {
        struct ust_registry_enum *reg_enum = NULL;
@@ -578,7 +578,7 @@ struct ust_registry_enum *
        strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
        reg_enum_lookup.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
        reg_enum_lookup.id = enum_id;
-       cds_lfht_lookup(session->enums->ht,
+       cds_lfht_lookup(session.enums->ht,
                        ht_hash_enum((void *) &reg_enum_lookup, lttng_ht_seed),
                        ht_match_enum_id, &reg_enum_lookup, &iter.iter);
        node = lttng_ht_iter_get_node_str(&iter);
@@ -701,8 +701,8 @@ void destroy_channel_rcu(struct rcu_head *head)
        struct ust_registry_channel *chan =
                caa_container_of(head, struct ust_registry_channel, rcu_head);
 
-       if (chan->ht) {
-               ht_cleanup_push(chan->ht);
+       if (chan->events) {
+               ht_cleanup_push(chan->events);
        }
        free(chan->ctx_fields);
        free(chan);
@@ -730,11 +730,11 @@ static void destroy_channel(struct ust_registry_channel *chan, bool notif)
                }
        }
 
-       if (chan->ht) {
+       if (chan->events) {
                rcu_read_lock();
                /* Destroy all event associated with this registry. */
                cds_lfht_for_each_entry(
-                               chan->ht->ht, &iter.iter, event, node.node) {
+                               chan->events->ht, &iter.iter, event, node.node) {
                        /* Delete the node from the ht and free it. */
                        ust_registry_destroy_event(chan, event);
                }
@@ -761,15 +761,15 @@ int ust_registry_channel_add(struct ust_registry_session *session,
                goto error_alloc;
        }
 
-       chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
-       if (!chan->ht) {
+       chan->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+       if (!chan->events) {
                ret = -ENOMEM;
                goto error;
        }
 
        /* Set custom match function. */
-       chan->ht->match_fct = ht_match_event;
-       chan->ht->hash_fct = ht_hash_event;
+       chan->events->match_fct = ht_match_event;
+       chan->events->hash_fct = ht_hash_event;
 
        /*
         * Assign a channel ID right now since the event notification comes
diff --git a/src/bin/lttng-sessiond/ust-registry.h b/src/bin/lttng-sessiond/ust-registry.h
deleted file mode 100644 (file)
index a25cdc7..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_UST_REGISTRY_H
-#define LTTNG_UST_REGISTRY_H
-
-#include <pthread.h>
-#include <stdint.h>
-
-#include <common/hashtable/hashtable.h>
-#include <common/uuid.h>
-
-#include "lttng-ust-ctl.h"
-
-#define CTF_SPEC_MAJOR 1
-#define CTF_SPEC_MINOR 8
-
-struct ust_app;
-
-struct ust_registry_session {
-       /*
-        * With multiple writers and readers, use this lock to access
-        * the registry. Can nest within the ust app session lock.
-        * Also acts as a registry serialization lock. Used by registry
-        * readers to serialize the registry information sent from the
-        * sessiond to the consumerd.
-        * The consumer socket lock nests within this lock.
-        */
-       pthread_mutex_t lock;
-       /* Next channel ID available for a newly registered channel. */
-       uint32_t next_channel_id;
-       /* Once this value reaches UINT32_MAX, no more id can be allocated. */
-       uint32_t used_channel_id;
-       /* Next enumeration ID available. */
-       uint64_t next_enum_id;
-       /* Universal unique identifier used by the tracer. */
-       unsigned char uuid[LTTNG_UUID_LEN];
-
-       /* session ABI description */
-
-       /* Size of long, in bits */
-       unsigned int bits_per_long;
-       /* Alignment, in bits */
-       unsigned int uint8_t_alignment,
-               uint16_t_alignment,
-               uint32_t_alignment,
-               uint64_t_alignment,
-               long_alignment;
-       /* endianness */
-       int byte_order; /* BIG_ENDIAN or LITTLE_ENDIAN */
-
-       /* Generated metadata. */
-       char *metadata;         /* NOT null-terminated ! Use memcpy. */
-       size_t metadata_len, metadata_alloc_len;
-       /* Length of bytes sent to the consumer. */
-       size_t metadata_len_sent;
-       /* Current version of the metadata. */
-       uint64_t metadata_version;
-
-       /*
-        * Those fields are only used when a session is created with
-        * the --shm-path option. In this case, the metadata is output
-        * twice: once to the consumer, as ususal, but a second time
-        * also in the shm path directly. This is done so that a copy
-        * of the metadata that is as fresh as possible is available
-        * on the event of a crash.
-        *
-        * root_shm_path contains the shm-path provided by the user, along with
-        * the session's name and timestamp:
-        *   e.g. /tmp/my_shm/my_session-20180612-135822
-        *
-        * shm_path contains the full path of the memory buffers:
-        *   e.g. /tmp/my_shm/my_session-20180612-135822/ust/uid/1000/64-bit
-        *
-        * metadata_path contains the full path to the metadata file that
-        * is kept for the "crash buffer" extraction:
-        *  e.g. /tmp/my_shm/my_session-20180612-135822/ust/uid/1000/64-bit/metadata
-        *
-        * Note that this is not the trace's final metadata file. It is
-        * only meant to be used to read the contents of the ring buffers
-        * in the event of a crash.
-        *
-        * metadata_fd is a file descriptor that points to the file at
-        * 'metadata_path'.
-        */
-       char root_shm_path[PATH_MAX];
-       char shm_path[PATH_MAX];
-       char metadata_path[PATH_MAX];
-       int metadata_fd;        /* file-backed metadata FD */
-
-       /*
-        * Hash table containing channels sent by the UST tracer. MUST
-        * be accessed with a RCU read side lock acquired.
-        */
-       struct lttng_ht *channels;
-       /*
-        * Unique key to identify the metadata on the consumer side.
-        */
-       uint64_t metadata_key;
-       /*
-        * Indicates if the metadata is closed on the consumer side. This is to
-        * avoid double close of metadata when an application unregisters AND
-        * deletes its sessions.
-        */
-       unsigned int metadata_closed;
-
-       /* User and group owning the session. */
-       uid_t uid;
-       gid_t gid;
-
-       /* Enumerations table. */
-       struct lttng_ht *enums;
-
-       /*
-        * Copy of the tracer version when the first app is registered.
-        * It is used if we need to regenerate the metadata.
-        */
-       uint32_t major;
-       uint32_t minor;
-
-       /* The id of the parent session */
-       uint64_t tracing_id;
-       uid_t tracing_uid;
-};
-
-struct ust_registry_channel {
-       uint64_t key;
-       uint64_t consumer_key;
-       /* Id set when replying to a register channel. */
-       uint32_t chan_id;
-       enum lttng_ust_ctl_channel_header header_type;
-
-       /*
-        * Flag for this channel if the metadata was dumped once during
-        * registration. 0 means no, 1 yes.
-        */
-       unsigned int metadata_dumped;
-       /* Indicates if this channel registry has already been registered. */
-       unsigned int register_done;
-
-       /*
-        * Hash table containing events sent by the UST tracer. MUST be accessed
-        * with a RCU read side lock acquired.
-        */
-       struct lttng_ht *ht;
-       /* Next event ID available for a newly registered event. */
-       uint32_t next_event_id;
-       /* Once this value reaches UINT32_MAX, no more id can be allocated. */
-       uint32_t used_event_id;
-       /*
-        * Context fields of the registry. Context are per channel. Allocated by a
-        * register channel notification from the UST tracer.
-        */
-       size_t nr_ctx_fields;
-       struct lttng_ust_ctl_field *ctx_fields;
-       struct lttng_ht_node_u64 node;
-       /* For delayed reclaim */
-       struct rcu_head rcu_head;
-};
-
-/*
- * Event registered from a UST tracer sent to the session daemon. This is
- * indexed and matched by <event_name/signature>.
- */
-struct ust_registry_event {
-       int id;
-       /* Both objd are set by the tracer. */
-       int session_objd;
-       int channel_objd;
-       /* Name of the event returned by the tracer. */
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-       char *signature;
-       int loglevel_value;
-       size_t nr_fields;
-       struct lttng_ust_ctl_field *fields;
-       char *model_emf_uri;
-       /*
-        * Flag for this channel if the metadata was dumped once during
-        * registration. 0 means no, 1 yes.
-        */
-       unsigned int metadata_dumped;
-       /*
-        * Node in the ust-registry hash table. The event name is used to
-        * initialize the node and the event_name/signature for the match function.
-        */
-       struct lttng_ht_node_u64 node;
-};
-
-struct ust_registry_enum {
-       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
-       struct lttng_ust_ctl_enum_entry *entries;
-       size_t nr_entries;
-       uint64_t id;    /* enum id in session */
-       /* Enumeration node in session hash table. */
-       struct lttng_ht_node_str node;
-       /* For delayed reclaim. */
-       struct rcu_head rcu_head;
-};
-
-/*
- * Validate that the id has reached the maximum allowed or not.
- *
- * Return 0 if NOT else 1.
- */
-static inline int ust_registry_is_max_id(uint32_t id)
-{
-       return (id == UINT32_MAX) ? 1 : 0;
-}
-
-/*
- * Return next available event id and increment the used counter. The
- * ust_registry_is_max_id function MUST be called before in order to validate
- * if the maximum number of IDs have been reached. If not, it is safe to call
- * this function.
- *
- * Return a unique channel ID. If max is reached, the used_event_id counter is
- * returned.
- */
-static inline uint32_t ust_registry_get_next_event_id(
-               struct ust_registry_channel *r)
-{
-       if (ust_registry_is_max_id(r->used_event_id)) {
-               return r->used_event_id;
-       }
-
-       r->used_event_id++;
-       return r->next_event_id++;
-}
-
-/*
- * Return next available channel id and increment the used counter. The
- * ust_registry_is_max_id function MUST be called before in order to validate
- * if the maximum number of IDs have been reached. If not, it is safe to call
- * this function.
- *
- * Return a unique channel ID. If max is reached, the used_channel_id counter
- * is returned.
- */
-static inline uint32_t ust_registry_get_next_chan_id(
-               struct ust_registry_session *r)
-{
-       if (ust_registry_is_max_id(r->used_channel_id)) {
-               return r->used_channel_id;
-       }
-
-       r->used_channel_id++;
-       return r->next_channel_id++;
-}
-
-/*
- * Return registry event count. This is read atomically.
- */
-static inline uint32_t ust_registry_get_event_count(
-               struct ust_registry_channel *r)
-{
-       return (uint32_t) uatomic_read(&r->used_event_id);
-}
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-void ust_registry_channel_destroy(struct ust_registry_session *session,
-               struct ust_registry_channel *chan);
-struct ust_registry_channel *ust_registry_channel_find(
-               struct ust_registry_session *session, uint64_t key);
-int ust_registry_channel_add(struct ust_registry_session *session,
-               uint64_t key);
-void ust_registry_channel_del_free(struct ust_registry_session *session,
-               uint64_t key, bool notif);
-
-int ust_registry_session_init(struct ust_registry_session **sessionp,
-               struct ust_app *app,
-               uint32_t bits_per_long,
-               uint32_t uint8_t_alignment,
-               uint32_t uint16_t_alignment,
-               uint32_t uint32_t_alignment,
-               uint32_t uint64_t_alignment,
-               uint32_t long_alignment,
-               int byte_order,
-               uint32_t major,
-               uint32_t minor,
-               const char *root_shm_path,
-               const char *shm_path,
-               uid_t euid,
-               gid_t egid,
-               uint64_t tracing_id,
-               uid_t tracing_uid);
-void ust_registry_session_destroy(struct ust_registry_session *session);
-
-int ust_registry_create_event(struct ust_registry_session *session,
-               uint64_t chan_key, int session_objd, int channel_objd, char *name,
-               char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields,
-               int loglevel_value, char *model_emf_uri, int buffer_type,
-               uint32_t *event_id_p, struct ust_app *app);
-struct ust_registry_event *ust_registry_find_event(
-               struct ust_registry_channel *chan, char *name, char *sig);
-void ust_registry_destroy_event(struct ust_registry_channel *chan,
-               struct ust_registry_event *event);
-
-/* app can be NULL for registry shared across applications. */
-int ust_metadata_session_statedump(struct ust_registry_session *session,
-               struct ust_app *app, uint32_t major, uint32_t minor);
-int ust_metadata_channel_statedump(struct ust_registry_session *session,
-               struct ust_registry_channel *chan);
-int ust_metadata_event_statedump(struct ust_registry_session *session,
-               struct ust_registry_channel *chan,
-               struct ust_registry_event *event);
-int ust_registry_create_or_find_enum(struct ust_registry_session *session,
-               int session_objd, char *name,
-               struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries,
-               uint64_t *enum_id);
-struct ust_registry_enum *
-       ust_registry_lookup_enum_by_id(struct ust_registry_session *session,
-               const char *name, uint64_t id);
-
-#else /* HAVE_LIBLTTNG_UST_CTL */
-
-static inline
-void ust_registry_channel_destroy(struct ust_registry_session *session,
-               struct ust_registry_channel *chan)
-{}
-static inline
-struct ust_registry_channel *ust_registry_channel_find(
-               struct ust_registry_session *session, uint64_t key)
-{
-       return NULL;
-}
-static inline
-int ust_registry_channel_add(struct ust_registry_session *session,
-               uint64_t key)
-{
-       return 0;
-}
-static inline
-void ust_registry_channel_del_free(struct ust_registry_session *session,
-               uint64_t key, bool notif)
-{}
-static inline
-int ust_registry_session_init(struct ust_registry_session **sessionp,
-               struct ust_app *app,
-               uint32_t bits_per_long,
-               uint32_t uint8_t_alignment,
-               uint32_t uint16_t_alignment,
-               uint32_t uint32_t_alignment,
-               uint32_t uint64_t_alignment,
-               uint32_t long_alignment,
-               int byte_order,
-               uint32_t major,
-               uint32_t minor,
-               const char *root_shm_path,
-               const char *shm_path,
-               uid_t euid,
-               gid_t egid,
-               uint64_t tracing_id,
-               uid_t tracing_uid)
-{
-       return 0;
-}
-static inline
-void ust_registry_session_destroy(struct ust_registry_session *session)
-{}
-static inline
-int ust_registry_create_event(struct ust_registry_session *session,
-               uint64_t chan_key, int session_objd, int channel_objd, char *name,
-               char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields,
-               int loglevel_value, char *model_emf_uri, int buffer_type,
-               uint32_t *event_id_p)
-{
-       return 0;
-}
-static inline
-struct ust_registry_event *ust_registry_find_event(
-               struct ust_registry_channel *chan, char *name, char *sig)
-{
-       return NULL;
-}
-static inline
-void ust_registry_destroy_event(struct ust_registry_channel *chan,
-               struct ust_registry_event *event)
-{}
-
-/* The app object can be NULL for registry shared across applications. */
-static inline
-int ust_metadata_session_statedump(struct ust_registry_session *session,
-               struct ust_app *app, uint32_t major, uint32_t minor)
-{
-       return 0;
-}
-static inline
-int ust_metadata_channel_statedump(struct ust_registry_session *session,
-               struct ust_registry_channel *chan)
-{
-       return 0;
-}
-static inline
-int ust_metadata_event_statedump(struct ust_registry_session *session,
-               struct ust_registry_channel *chan,
-               struct ust_registry_event *event)
-{
-       return 0;
-}
-static inline
-int ust_registry_create_or_find_enum(struct ust_registry_session *session,
-               int session_objd, char *name,
-               struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries,
-               uint64_t *enum_id)
-{
-       return 0;
-}
-static inline
-struct ust_registry_enum *
-       ust_registry_lookup_enum_by_id(struct ust_registry_session *session,
-               const char *name, uint64_t id)
-{
-       return NULL;
-}
-
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* LTTNG_UST_REGISTRY_H */
diff --git a/src/bin/lttng-sessiond/ust-registry.hpp b/src/bin/lttng-sessiond/ust-registry.hpp
new file mode 100644 (file)
index 0000000..ea2bfbd
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_UST_REGISTRY_H
+#define LTTNG_UST_REGISTRY_H
+
+#include <pthread.h>
+#include <stdint.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <common/uuid.hpp>
+
+#include "lttng-ust-ctl.hpp"
+
+#define CTF_SPEC_MAJOR 1
+#define CTF_SPEC_MINOR 8
+
+struct ust_app;
+
+struct ust_registry_session {
+       /*
+        * With multiple writers and readers, use this lock to access
+        * the registry. Can nest within the ust app session lock.
+        * Also acts as a registry serialization lock. Used by registry
+        * readers to serialize the registry information sent from the
+        * sessiond to the consumerd.
+        * The consumer socket lock nests within this lock.
+        */
+       pthread_mutex_t lock;
+       /* Next channel ID available for a newly registered channel. */
+       uint32_t next_channel_id;
+       /* Once this value reaches UINT32_MAX, no more id can be allocated. */
+       uint32_t used_channel_id;
+       /* Next enumeration ID available. */
+       uint64_t next_enum_id;
+       /* Universal unique identifier used by the tracer. */
+       unsigned char uuid[LTTNG_UUID_LEN];
+
+       /* session ABI description */
+
+       /* Size of long, in bits */
+       unsigned int bits_per_long;
+       /* Alignment, in bits */
+       unsigned int uint8_t_alignment,
+               uint16_t_alignment,
+               uint32_t_alignment,
+               uint64_t_alignment,
+               long_alignment;
+       /* endianness */
+       int byte_order; /* BIG_ENDIAN or LITTLE_ENDIAN */
+
+       /* Generated metadata. */
+       char *metadata;         /* NOT null-terminated ! Use memcpy. */
+       size_t metadata_len, metadata_alloc_len;
+       /* Length of bytes sent to the consumer. */
+       size_t metadata_len_sent;
+       /* Current version of the metadata. */
+       uint64_t metadata_version;
+
+       /*
+        * Those fields are only used when a session is created with
+        * the --shm-path option. In this case, the metadata is output
+        * twice: once to the consumer, as ususal, but a second time
+        * also in the shm path directly. This is done so that a copy
+        * of the metadata that is as fresh as possible is available
+        * on the event of a crash.
+        *
+        * root_shm_path contains the shm-path provided by the user, along with
+        * the session's name and timestamp:
+        *   e.g. /tmp/my_shm/my_session-20180612-135822
+        *
+        * shm_path contains the full path of the memory buffers:
+        *   e.g. /tmp/my_shm/my_session-20180612-135822/ust/uid/1000/64-bit
+        *
+        * metadata_path contains the full path to the metadata file that
+        * is kept for the "crash buffer" extraction:
+        *  e.g. /tmp/my_shm/my_session-20180612-135822/ust/uid/1000/64-bit/metadata
+        *
+        * Note that this is not the trace's final metadata file. It is
+        * only meant to be used to read the contents of the ring buffers
+        * in the event of a crash.
+        *
+        * metadata_fd is a file descriptor that points to the file at
+        * 'metadata_path'.
+        */
+       char root_shm_path[PATH_MAX];
+       char shm_path[PATH_MAX];
+       char metadata_path[PATH_MAX];
+       int metadata_fd;        /* file-backed metadata FD */
+
+       /*
+        * Hash table containing channels sent by the UST tracer. MUST
+        * be accessed with a RCU read side lock acquired.
+        */
+       struct lttng_ht *channels;
+       /*
+        * Unique key to identify the metadata on the consumer side.
+        */
+       uint64_t metadata_key;
+       /*
+        * Indicates if the metadata is closed on the consumer side. This is to
+        * avoid double close of metadata when an application unregisters AND
+        * deletes its sessions.
+        */
+       unsigned int metadata_closed;
+
+       /* User and group owning the session. */
+       uid_t uid;
+       gid_t gid;
+
+       /* Enumerations table. */
+       struct lttng_ht *enums;
+
+       /*
+        * Copy of the tracer version when the first app is registered.
+        * It is used if we need to regenerate the metadata.
+        */
+       uint32_t major;
+       uint32_t minor;
+
+       /* The id of the parent session */
+       uint64_t tracing_id;
+       uid_t tracing_uid;
+};
+
+struct ust_registry_channel {
+       uint64_t key;
+       uint64_t consumer_key;
+       /* Id set when replying to a register channel. */
+       uint32_t chan_id;
+       enum lttng_ust_ctl_channel_header header_type;
+
+       /*
+        * Flag for this channel if the metadata was dumped once during
+        * registration. 0 means no, 1 yes.
+        */
+       unsigned int metadata_dumped;
+       /* Indicates if this channel registry has already been registered. */
+       unsigned int register_done;
+
+       /*
+        * Hash table containing events sent by the UST tracer. MUST be accessed
+        * with a RCU read side lock acquired.
+        */
+       struct lttng_ht *events;
+       /* Next event ID available for a newly registered event. */
+       uint32_t next_event_id;
+       /* Once this value reaches UINT32_MAX, no more id can be allocated. */
+       uint32_t used_event_id;
+       /*
+        * Context fields of the registry. Context are per channel. Allocated by a
+        * register channel notification from the UST tracer.
+        */
+       size_t nr_ctx_fields;
+       struct lttng_ust_ctl_field *ctx_fields;
+       struct lttng_ht_node_u64 node;
+       /* For delayed reclaim */
+       struct rcu_head rcu_head;
+};
+
+/*
+ * Event registered from a UST tracer sent to the session daemon. This is
+ * indexed and matched by <event_name/signature>.
+ */
+struct ust_registry_event {
+       int id;
+       /* Both objd are set by the tracer. */
+       int session_objd;
+       int channel_objd;
+       /* Name of the event returned by the tracer. */
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+       char *signature;
+       int loglevel_value;
+       size_t nr_fields;
+       struct lttng_ust_ctl_field *fields;
+       char *model_emf_uri;
+       /*
+        * Flag for this channel if the metadata was dumped once during
+        * registration. 0 means no, 1 yes.
+        */
+       unsigned int metadata_dumped;
+       /*
+        * Node in the ust-registry hash table. The event name is used to
+        * initialize the node and the event_name/signature for the match function.
+        */
+       struct lttng_ht_node_u64 node;
+};
+
+struct ust_registry_enum {
+       char name[LTTNG_UST_ABI_SYM_NAME_LEN];
+       struct lttng_ust_ctl_enum_entry *entries;
+       size_t nr_entries;
+       uint64_t id;    /* enum id in session */
+       /* Enumeration node in session hash table. */
+       struct lttng_ht_node_str node;
+       /* For delayed reclaim. */
+       struct rcu_head rcu_head;
+};
+
+/*
+ * Validate that the id has reached the maximum allowed or not.
+ *
+ * Return 0 if NOT else 1.
+ */
+static inline int ust_registry_is_max_id(uint32_t id)
+{
+       return (id == UINT32_MAX) ? 1 : 0;
+}
+
+/*
+ * Return next available event id and increment the used counter. The
+ * ust_registry_is_max_id function MUST be called before in order to validate
+ * if the maximum number of IDs have been reached. If not, it is safe to call
+ * this function.
+ *
+ * Return a unique channel ID. If max is reached, the used_event_id counter is
+ * returned.
+ */
+static inline uint32_t ust_registry_get_next_event_id(
+               struct ust_registry_channel *r)
+{
+       if (ust_registry_is_max_id(r->used_event_id)) {
+               return r->used_event_id;
+       }
+
+       r->used_event_id++;
+       return r->next_event_id++;
+}
+
+/*
+ * Return next available channel id and increment the used counter. The
+ * ust_registry_is_max_id function MUST be called before in order to validate
+ * if the maximum number of IDs have been reached. If not, it is safe to call
+ * this function.
+ *
+ * Return a unique channel ID. If max is reached, the used_channel_id counter
+ * is returned.
+ */
+static inline uint32_t ust_registry_get_next_chan_id(
+               struct ust_registry_session *r)
+{
+       if (ust_registry_is_max_id(r->used_channel_id)) {
+               return r->used_channel_id;
+       }
+
+       r->used_channel_id++;
+       return r->next_channel_id++;
+}
+
+/*
+ * Return registry event count. This is read atomically.
+ */
+static inline uint32_t ust_registry_get_event_count(
+               struct ust_registry_channel *r)
+{
+       return (uint32_t) uatomic_read(&r->used_event_id);
+}
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+void ust_registry_channel_destroy(struct ust_registry_session *session,
+               struct ust_registry_channel *chan);
+struct ust_registry_channel *ust_registry_channel_find(
+               struct ust_registry_session *session, uint64_t key);
+int ust_registry_channel_add(struct ust_registry_session *session,
+               uint64_t key);
+void ust_registry_channel_del_free(struct ust_registry_session *session,
+               uint64_t key, bool notif);
+
+int ust_registry_session_init(struct ust_registry_session **sessionp,
+               struct ust_app *app,
+               uint32_t bits_per_long,
+               uint32_t uint8_t_alignment,
+               uint32_t uint16_t_alignment,
+               uint32_t uint32_t_alignment,
+               uint32_t uint64_t_alignment,
+               uint32_t long_alignment,
+               int byte_order,
+               uint32_t major,
+               uint32_t minor,
+               const char *root_shm_path,
+               const char *shm_path,
+               uid_t euid,
+               gid_t egid,
+               uint64_t tracing_id,
+               uid_t tracing_uid);
+void ust_registry_session_destroy(struct ust_registry_session *session);
+
+int ust_registry_create_event(struct ust_registry_session *session,
+               uint64_t chan_key, int session_objd, int channel_objd, char *name,
+               char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields,
+               int loglevel_value, char *model_emf_uri, int buffer_type,
+               uint32_t *event_id_p, struct ust_app *app);
+struct ust_registry_event *ust_registry_find_event(
+               struct ust_registry_channel *chan, char *name, char *sig);
+void ust_registry_destroy_event(struct ust_registry_channel *chan,
+               struct ust_registry_event *event);
+
+/* app can be NULL for registry shared across applications. */
+int ust_metadata_session_statedump(struct ust_registry_session *session,
+               struct ust_app *app, uint32_t major, uint32_t minor);
+int ust_metadata_channel_statedump(struct ust_registry_session *session,
+               struct ust_registry_channel *chan);
+int ust_metadata_event_statedump(struct ust_registry_session *session,
+               struct ust_registry_channel *chan,
+               struct ust_registry_event *event);
+int ust_registry_create_or_find_enum(struct ust_registry_session *session,
+               int session_objd, char *name,
+               struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries,
+               uint64_t *enum_id);
+struct ust_registry_enum *
+       ust_registry_lookup_enum_by_id(const ust_registry_session &session,
+               const char *name, uint64_t id);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+static inline
+void ust_registry_channel_destroy(struct ust_registry_session *session,
+               struct ust_registry_channel *chan)
+{}
+static inline
+struct ust_registry_channel *ust_registry_channel_find(
+               struct ust_registry_session *session, uint64_t key)
+{
+       return NULL;
+}
+static inline
+int ust_registry_channel_add(struct ust_registry_session *session,
+               uint64_t key)
+{
+       return 0;
+}
+static inline
+void ust_registry_channel_del_free(struct ust_registry_session *session,
+               uint64_t key, bool notif)
+{}
+static inline
+int ust_registry_session_init(struct ust_registry_session **sessionp,
+               struct ust_app *app,
+               uint32_t bits_per_long,
+               uint32_t uint8_t_alignment,
+               uint32_t uint16_t_alignment,
+               uint32_t uint32_t_alignment,
+               uint32_t uint64_t_alignment,
+               uint32_t long_alignment,
+               int byte_order,
+               uint32_t major,
+               uint32_t minor,
+               const char *root_shm_path,
+               const char *shm_path,
+               uid_t euid,
+               gid_t egid,
+               uint64_t tracing_id,
+               uid_t tracing_uid)
+{
+       return 0;
+}
+static inline
+void ust_registry_session_destroy(struct ust_registry_session *session)
+{}
+static inline
+int ust_registry_create_event(struct ust_registry_session *session,
+               uint64_t chan_key, int session_objd, int channel_objd, char *name,
+               char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields,
+               int loglevel_value, char *model_emf_uri, int buffer_type,
+               uint32_t *event_id_p)
+{
+       return 0;
+}
+static inline
+struct ust_registry_event *ust_registry_find_event(
+               struct ust_registry_channel *chan, char *name, char *sig)
+{
+       return NULL;
+}
+static inline
+void ust_registry_destroy_event(struct ust_registry_channel *chan,
+               struct ust_registry_event *event)
+{}
+
+/* The app object can be NULL for registry shared across applications. */
+static inline
+int ust_metadata_session_statedump(struct ust_registry_session *session,
+               struct ust_app *app, uint32_t major, uint32_t minor)
+{
+       return 0;
+}
+static inline
+int ust_metadata_channel_statedump(struct ust_registry_session *session,
+               struct ust_registry_channel *chan)
+{
+       return 0;
+}
+static inline
+int ust_metadata_event_statedump(struct ust_registry_session *session,
+               struct ust_registry_channel *chan,
+               struct ust_registry_event *event)
+{
+       return 0;
+}
+static inline
+int ust_registry_create_or_find_enum(struct ust_registry_session *session,
+               int session_objd, char *name,
+               struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries,
+               uint64_t *enum_id)
+{
+       return 0;
+}
+static inline
+struct ust_registry_enum *
+       ust_registry_lookup_enum_by_id(const ust_registry_session &session,
+               const char *name, uint64_t id)
+{
+       return NULL;
+}
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* LTTNG_UST_REGISTRY_H */
index 93a974eb30a34b22343f487385c7b931aa80b8cf..cecaf4d584d244a5a54c2123dc9ce88e0d62c281 100644 (file)
@@ -8,7 +8,7 @@
 #include <lttng/ust-sigbus.h>
 #include <lttng/ust-ctl.h>
 #include <lttng/lttng-export.h>
-#include "ust-sigbus.h"
+#include "ust-sigbus.hpp"
 
 LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
 
diff --git a/src/bin/lttng-sessiond/ust-sigbus.h b/src/bin/lttng-sessiond/ust-sigbus.h
deleted file mode 100644 (file)
index 110ef7f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2021 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_UST_SIGBUS_H
-#define LTTNG_UST_SIGBUS_H
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-void lttng_ust_handle_sigbus(void *address);
-
-#else /* HAVE_LIBLTTNG_UST_CTL */
-
-static inline
-void lttng_ust_handle_sigbus(void *address)
-{
-}
-
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* LTTNG_UST_SIGBUS_H */
diff --git a/src/bin/lttng-sessiond/ust-sigbus.hpp b/src/bin/lttng-sessiond/ust-sigbus.hpp
new file mode 100644 (file)
index 0000000..110ef7f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_UST_SIGBUS_H
+#define LTTNG_UST_SIGBUS_H
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+void lttng_ust_handle_sigbus(void *address);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+static inline
+void lttng_ust_handle_sigbus(void *address)
+{
+}
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* LTTNG_UST_SIGBUS_H */
index 6936a03f963de2d0d37a18040f39fbd32b99d2a1..3fd1db03b83d7126f551d4eae87fb820317e070f 100644 (file)
 #include <stdlib.h>
 #include <unistd.h>
 
-#include <common/error.h>
+#include <common/error.hpp>
 
-#include "utils.h"
-#include "snapshot.h"
-#include "lttng-sessiond.h"
+#include "utils.hpp"
+#include "snapshot.hpp"
+#include "lttng-sessiond.hpp"
 
 int the_ht_cleanup_pipe[2] = {-1, -1};
 
diff --git a/src/bin/lttng-sessiond/utils.h b/src/bin/lttng-sessiond/utils.h
deleted file mode 100644 (file)
index ff8deae..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_UTILS_H
-#define _LTT_UTILS_H
-
-struct lttng_ht;
-struct ltt_session;
-struct consumer_output;
-
-const char *get_home_dir(void);
-int notify_thread_pipe(int wpipe);
-void ht_cleanup_push(struct lttng_ht *ht);
-int loglevels_match(int a_loglevel_type, int a_loglevel_value,
-       int b_loglevel_type, int b_loglevel_value, int loglevel_all_type);
-const char *session_get_base_path(const struct ltt_session *session);
-const char *consumer_output_get_base_path(const struct consumer_output *output);
-
-#endif /* _LTT_UTILS_H */
diff --git a/src/bin/lttng-sessiond/utils.hpp b/src/bin/lttng-sessiond/utils.hpp
new file mode 100644 (file)
index 0000000..ff8deae
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_UTILS_H
+#define _LTT_UTILS_H
+
+struct lttng_ht;
+struct ltt_session;
+struct consumer_output;
+
+const char *get_home_dir(void);
+int notify_thread_pipe(int wpipe);
+void ht_cleanup_push(struct lttng_ht *ht);
+int loglevels_match(int a_loglevel_type, int a_loglevel_value,
+       int b_loglevel_type, int b_loglevel_value, int loglevel_all_type);
+const char *session_get_base_path(const struct ltt_session *session);
+const char *consumer_output_get_base_path(const struct consumer_output *output);
+
+#endif /* _LTT_UTILS_H */
index f1c04a3e94aef453f048dd21e53d9865a7f8f7f0..b03065cd698707bc68a1a6c3b63a9db8fd76cfd8 100644 (file)
@@ -10,7 +10,7 @@ AUTOMAKE_OPTIONS = subdir-objects
 
 bin_PROGRAMS = lttng
 
-lttng_SOURCES = command.h conf.cpp conf.h commands/start.cpp \
+lttng_SOURCES = command.hpp conf.cpp conf.hpp commands/start.cpp \
                                commands/list.cpp commands/create.cpp commands/destroy.cpp \
                                commands/stop.cpp commands/enable_events.cpp \
                                commands/disable_events.cpp commands/enable_channels.cpp \
@@ -29,20 +29,19 @@ lttng_SOURCES = command.h conf.cpp conf.h commands/start.cpp \
                                commands/enable_rotation.cpp \
                                commands/disable_rotation.cpp \
                                commands/clear.cpp \
-                               loglevel.cpp loglevel.h \
+                               loglevel.cpp loglevel.hpp \
                                commands/add_trigger.cpp \
                                commands/list_triggers.cpp \
                                commands/remove_trigger.cpp \
-                               utils.cpp utils.h lttng.cpp \
-                               uprobe.cpp uprobe.h
+                               utils.cpp utils.hpp lttng.cpp \
+                               uprobe.cpp uprobe.hpp
 
 lttng_CXXFLAGS = $(AM_CXXFLAGS) $(POPT_CFLAGS)
 
 lttng_LDADD = $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la \
                        $(top_builddir)/src/common/libcommon.la \
-                       $(top_builddir)/src/common/config/libconfig.la \
-                       $(top_builddir)/src/common/string-utils/libstring-utils.la \
-                       $(top_builddir)/src/common/filter/libfilter.la \
-                       $(top_builddir)/src/common/argpar-utils/libargpar-utils.la \
-                       $(top_builddir)/src/common/argpar/libargpar.la \
+                       $(top_builddir)/src/common/libconfig.la \
+                       $(top_builddir)/src/common/libstring-utils.la \
+                       $(top_builddir)/src/common/libargpar-utils.la \
+                       $(top_builddir)/src/common/libargpar.la \
                        $(POPT_LIBS)
diff --git a/src/bin/lttng/command.h b/src/bin/lttng/command.h
deleted file mode 100644 (file)
index bf00452..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_CMD_H
-#define _LTTNG_CMD_H
-
-#include <lttng/lttng.h>
-#include <common/common.h>
-#include <common/defaults.h>
-
-#include "conf.h"
-#include "utils.h"
-
-#define DECL_COMMAND(_name) \
-       extern int cmd_##_name(int, const char **)
-
-#ifdef LTTNG_EMBED_HELP
-# define HELP_MSG_NAME         help_msg
-# define SHOW_HELP_ERROR_LINE  ERR("Cannot show --help for `lttng-%s`", argv[0]);
-#else
-# define HELP_MSG_NAME         NULL
-# define SHOW_HELP_ERROR_LINE  ;
-#endif
-
-#define SHOW_HELP()                                                    \
-       do {                                                            \
-               ret = show_cmd_help(argv[0], HELP_MSG_NAME);            \
-                                                                       \
-               if (ret) {                                              \
-                       SHOW_HELP_ERROR_LINE                            \
-                       ret = CMD_ERROR;                                \
-               }                                                       \
-       } while (0)
-
-enum cmd_error_code {
-       CMD_SUCCESS = 0,
-       CMD_ERROR,
-       CMD_UNDEFINED,
-       CMD_FATAL,
-       CMD_WARNING,
-       CMD_UNSUPPORTED,
-};
-
-struct cmd_struct {
-       const char *name;
-       int (*func)(int argc, const char **argv);
-};
-
-DECL_COMMAND(list);
-DECL_COMMAND(status);
-DECL_COMMAND(create);
-DECL_COMMAND(destroy);
-DECL_COMMAND(start);
-DECL_COMMAND(stop);
-DECL_COMMAND(enable_events);
-DECL_COMMAND(disable_events);
-DECL_COMMAND(enable_channels);
-DECL_COMMAND(disable_channels);
-DECL_COMMAND(add_context);
-DECL_COMMAND(set_session);
-DECL_COMMAND(version);
-DECL_COMMAND(view);
-DECL_COMMAND(enable_consumer);
-DECL_COMMAND(disable_consumer);
-DECL_COMMAND(snapshot);
-DECL_COMMAND(save);
-DECL_COMMAND(load);
-DECL_COMMAND(track);
-DECL_COMMAND(untrack);
-DECL_COMMAND(metadata);
-DECL_COMMAND(regenerate);
-DECL_COMMAND(rotate);
-DECL_COMMAND(enable_rotation);
-DECL_COMMAND(disable_rotation);
-DECL_COMMAND(clear);
-DECL_COMMAND(add_trigger);
-DECL_COMMAND(list_triggers);
-DECL_COMMAND(remove_trigger);
-
-extern int cmd_help(int argc, const char **argv,
-               const struct cmd_struct commands[]);
-
-#endif /* _LTTNG_CMD_H */
diff --git a/src/bin/lttng/command.hpp b/src/bin/lttng/command.hpp
new file mode 100644 (file)
index 0000000..0dd3b63
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_CMD_H
+#define _LTTNG_CMD_H
+
+#include <lttng/lttng.h>
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+
+#include "conf.hpp"
+#include "utils.hpp"
+
+#define DECL_COMMAND(_name) \
+       extern int cmd_##_name(int, const char **)
+
+#ifdef LTTNG_EMBED_HELP
+# define HELP_MSG_NAME         help_msg
+# define SHOW_HELP_ERROR_LINE  ERR("Cannot show --help for `lttng-%s`", argv[0]);
+#else
+# define HELP_MSG_NAME         NULL
+# define SHOW_HELP_ERROR_LINE  ;
+#endif
+
+#define SHOW_HELP()                                                    \
+       do {                                                            \
+               ret = show_cmd_help(argv[0], HELP_MSG_NAME);            \
+                                                                       \
+               if (ret) {                                              \
+                       SHOW_HELP_ERROR_LINE                            \
+                       ret = CMD_ERROR;                                \
+               }                                                       \
+       } while (0)
+
+enum cmd_error_code {
+       CMD_SUCCESS = 0,
+       CMD_ERROR,
+       CMD_UNDEFINED,
+       CMD_FATAL,
+       CMD_WARNING,
+       CMD_UNSUPPORTED,
+};
+
+struct cmd_struct {
+       const char *name;
+       int (*func)(int argc, const char **argv);
+};
+
+DECL_COMMAND(list);
+DECL_COMMAND(status);
+DECL_COMMAND(create);
+DECL_COMMAND(destroy);
+DECL_COMMAND(start);
+DECL_COMMAND(stop);
+DECL_COMMAND(enable_events);
+DECL_COMMAND(disable_events);
+DECL_COMMAND(enable_channels);
+DECL_COMMAND(disable_channels);
+DECL_COMMAND(add_context);
+DECL_COMMAND(set_session);
+DECL_COMMAND(version);
+DECL_COMMAND(view);
+DECL_COMMAND(enable_consumer);
+DECL_COMMAND(disable_consumer);
+DECL_COMMAND(snapshot);
+DECL_COMMAND(save);
+DECL_COMMAND(load);
+DECL_COMMAND(track);
+DECL_COMMAND(untrack);
+DECL_COMMAND(metadata);
+DECL_COMMAND(regenerate);
+DECL_COMMAND(rotate);
+DECL_COMMAND(enable_rotation);
+DECL_COMMAND(disable_rotation);
+DECL_COMMAND(clear);
+DECL_COMMAND(add_trigger);
+DECL_COMMAND(list_triggers);
+DECL_COMMAND(remove_trigger);
+
+extern int cmd_help(int argc, const char **argv,
+               const struct cmd_struct commands[]);
+
+#endif /* _LTTNG_CMD_H */
index 076fa83a44a69b717f3fad2f719bcec8861f0559..6ef52656f27408d898a3ac66dbb43879d4e0c2cb 100644 (file)
 
 #include <urcu/list.h>
 
-#include <lttng/domain-internal.h>
-#include <common/mi-lttng.h>
+#include <lttng/domain-internal.hpp>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static char *opt_channel_name;
 static char *opt_session_name;
index b09a1bf82dce418468c7e03fb52e32d8415a1873..0681f98618c36f2128ae0f57b7082663a21d64c7 100644 (file)
 #include <string.h>
 #include <stdarg.h>
 
-#include "../command.h"
-#include "../loglevel.h"
-#include "../uprobe.h"
+#include "../command.hpp"
+#include "../loglevel.hpp"
+#include "../uprobe.hpp"
 
 #include "common/argpar/argpar.h"
-#include "common/argpar-utils/argpar-utils.h"
-#include "common/dynamic-array.h"
-#include "common/mi-lttng.h"
-#include "common/string-utils/string-utils.h"
-#include "common/utils.h"
-#include <lttng/domain-internal.h>
+#include "common/argpar-utils/argpar-utils.hpp"
+#include "common/dynamic-array.hpp"
+#include "common/mi-lttng.hpp"
+#include "common/string-utils/string-utils.hpp"
+#include "common/utils.hpp"
+#include <lttng/domain-internal.hpp>
 /* For lttng_event_rule_type_str(). */
-#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/event-rule-internal.hpp>
 #include <lttng/lttng.h>
-#include "common/filter/filter-ast.h"
-#include "common/filter/filter-ir.h"
-#include "common/dynamic-array.h"
+#include "common/filter/filter-ast.hpp"
+#include "common/filter/filter-ir.hpp"
+#include "common/dynamic-array.hpp"
 
 #if (LTTNG_SYMBOL_NAME_LEN == 256)
 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
index 61879d61d1d9fd06751c736f5fd813be57bf94f2..6c2399181105cae25aa366ccf3d71f7a8de11082 100644 (file)
 #include <stdbool.h>
 #include <lttng/lttng.h>
 
-#include "../command.h"
+#include "../command.hpp"
 
-#include <common/mi-lttng.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/utils.h>
+#include <common/mi-lttng.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/utils.hpp>
 
 static int opt_clear_all;
 
index b266c10a9397a8e250c0c156a5d7e2fef547db46..376a9de8ad6f9dcf5d9d2afd511721a0caff2273 100644 (file)
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <common/compat/time.h>
+#include <common/compat/time.hpp>
 #include <unistd.h>
 #include <signal.h>
 #include <sys/wait.h>
 
-#include <common/mi-lttng.h>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
-#include "../utils.h"
+#include "../command.hpp"
+#include "../utils.hpp"
 
-#include <common/defaults.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/uri.h>
-#include <common/utils.h>
+#include <common/defaults.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/uri.hpp>
+#include <common/utils.hpp>
 #include <lttng/lttng.h>
 
 static char *opt_output_path;
index 78bbbaaad37e25a6e94648236860fe11a60252db..43c569fc6141909d5cf33394eb5b17759ff9bf84 100644 (file)
 #include <stdbool.h>
 #include <lttng/lttng.h>
 
-#include "../command.h"
+#include "../command.hpp"
 
-#include <common/mi-lttng.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/utils.h>
+#include <common/mi-lttng.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/utils.hpp>
 
 static char *opt_session_name;
 static int opt_destroy_all;
index cf9f20bb6d3fd2a539651c6c08d6a09699ca68c5..d4e4adc56e3b5e707a3818800af7e19a449054a7 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/mi-lttng.h>
-#include <lttng/domain-internal.h>
+#include <common/mi-lttng.hpp>
+#include <lttng/domain-internal.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static char *opt_channels;
 static int opt_kernel;
index 5ce36e50a0f84872e7b0dec35a7a1fc94f7006d2..08c2044425bbab15ccfd8205d94d3d7cdab816bd 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/mi-lttng.h>
-#include <lttng/domain-internal.h>
+#include <common/mi-lttng.hpp>
+#include <lttng/domain-internal.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static char *opt_event_list;
 static int opt_kernel;
index 8229f63e01bb4608d337759e7132c3a7f6160344..c2b6728ae758f0da0117213d5027d7b3ed7a0a01 100644 (file)
 #include <inttypes.h>
 #include <ctype.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/mi-lttng.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 #include <lttng/lttng.h>
 
 static char *opt_session_name;
index 194ec541eae167077597997fce467e3f10c101bd..ee1d5aab6bc48ad85e63f19a48efa2031783a87b 100644 (file)
 #include <inttypes.h>
 #include <ctype.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/utils.h>
-#include <common/mi-lttng.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/utils.hpp>
+#include <common/mi-lttng.hpp>
 
-#include <lttng/domain-internal.h>
+#include <lttng/domain-internal.hpp>
 
-#include "../command.h"
-#include "../utils.h"
+#include "../command.hpp"
+#include "../utils.hpp"
 
 
 static struct lttng_channel chan_opts;
index 50854faaa7141a918a3c605d7bf802b9e214f353..ea1f38312a1ad19b43c16f42978d0509ff7a8326 100644 (file)
 #include <inttypes.h>
 #include <ctype.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/compat/string.h>
-#include <common/compat/getenv.h>
-#include <common/string-utils/string-utils.h>
-#include <common/utils.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/compat/string.hpp>
+#include <common/compat/getenv.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <common/utils.hpp>
 
 /* Mi dependancy */
-#include <common/mi-lttng.h>
+#include <common/mi-lttng.hpp>
 
-#include <lttng/domain-internal.h>
-#include <lttng/event-internal.h>
+#include <lttng/domain-internal.hpp>
+#include <lttng/event-internal.hpp>
 
-#include "../command.h"
-#include "../loglevel.h"
-#include "../uprobe.h"
+#include "../command.hpp"
+#include "../loglevel.hpp"
+#include "../uprobe.hpp"
 
 #if (LTTNG_SYMBOL_NAME_LEN == 256)
 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API    "255"
index 1719f3ac243dd166f3a347399afefcbeea08539a..223d47ccafe583e2736b4ce30db1f043bdb45de1 100644 (file)
 #include <inttypes.h>
 #include <ctype.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/mi-lttng.h>
-#include <common/utils.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/utils.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 #include <lttng/lttng.h>
 
 static char *opt_session_name;
index a9a01e7f14a65db8084e5b8cdbdaa6c0ad038c8d..74b64964443aa184eb8ac7762491f4cac2e37037 100644 (file)
@@ -11,8 +11,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "../command.h"
-#include <common/utils.h>
+#include "../command.hpp"
+#include <common/utils.hpp>
 
 #ifdef LTTNG_EMBED_HELP
 static const char *help_msg =
index 28063ebc9cfdc631084621cc6fa25c4492b55913..b865d2ff8d2253a1d42a71026b134555ec86cd99 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include <common/mi-lttng.h>
-#include <common/time.h>
-#include <common/tracker.h>
-#include <lttng/domain-internal.h>
+#include <common/mi-lttng.hpp>
+#include <common/time.hpp>
+#include <common/tracker.hpp>
+#include <lttng/domain-internal.hpp>
 #include <lttng/lttng.h>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static int opt_userspace;
 static int opt_kernel;
index 274bae47d0af90e1301af4e4ad4443e99e31c84e..723fc2da02a331ca16ed00fe4684efcbb369c438 100644 (file)
@@ -7,21 +7,21 @@
 
 #include <stdio.h>
 
-#include "../command.h"
+#include "../command.hpp"
 
 #include "common/argpar/argpar.h"
-#include "common/argpar-utils/argpar-utils.h"
-#include "common/dynamic-array.h"
-#include "common/mi-lttng.h"
+#include "common/argpar-utils/argpar-utils.hpp"
+#include "common/dynamic-array.hpp"
+#include "common/mi-lttng.hpp"
 /* For lttng_condition_type_str(). */
-#include "lttng/condition/condition-internal.h"
+#include "lttng/condition/condition-internal.hpp"
 #include "lttng/condition/event-rule-matches.h"
-#include "lttng/condition/event-rule-matches-internal.h"
+#include "lttng/condition/event-rule-matches-internal.hpp"
 /* For lttng_domain_type_str(). */
-#include "lttng/domain-internal.h"
+#include "lttng/domain-internal.hpp"
 /* For lttng_event_rule_kernel_syscall_emission_site_str() */
-#include "lttng/event-rule/kernel-syscall-internal.h"
-#include "../loglevel.h"
+#include "lttng/event-rule/kernel-syscall-internal.hpp"
+#include "../loglevel.hpp"
 #include <lttng/lttng.h>
 
 #ifdef LTTNG_EMBED_HELP
index cdc3905168a7b12ee37c8f34f99d88364c4315ff..2ab005f2a3a029546a370e8141e0cf1af9c3531f 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include <common/mi-lttng.h>
-#include <common/config/session-config.h>
+#include <common/mi-lttng.hpp>
+#include <common/config/session-config.hpp>
 #include <lttng/lttng.h>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static char *the_opt_input_path;
 static char *the_opt_override_url;
index 35aea004e67aecb05b5c44c54630468b82c551ce..12c841eab04d398dcd080f145ddb5dd6090efa9f 100644 (file)
@@ -13,9 +13,9 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <common/mi-lttng.h>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static char *opt_session_name;
 static char *session_name = NULL;
index 0e904f8abcba1cdc6c92f6e4b5be3030ba84dac9..8e34d65d34fd64e40390d37055180091aa69a816 100644 (file)
@@ -13,9 +13,9 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <common/mi-lttng.h>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static char *opt_session_name;
 static char *session_name = NULL;
index a84b552dfb1d3aab583ebac0fbe525f828c7f3dd..65b5e79a9b4b18b562e536772b87bfd4f94e0a89 100644 (file)
@@ -5,10 +5,10 @@
  *
  */
 
-#include "../command.h"
+#include "../command.hpp"
 #include "common/argpar/argpar.h"
-#include "common/argpar-utils/argpar-utils.h"
-#include "common/mi-lttng.h"
+#include "common/argpar-utils/argpar-utils.hpp"
+#include "common/mi-lttng.hpp"
 #include <lttng/lttng.h>
 #include <stdio.h>
 
index 63cf3882a55a9b6b4a00453c531dfa5c18bd3fd4..339e39598891505d3b62eafffc123be901b445dd 100644 (file)
 #include <inttypes.h>
 #include <ctype.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/mi-lttng.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 #include <lttng/lttng.h>
 
 static char *opt_session_name;
index 4231922ad3f724f5ac36995184efd5c6053e7cdb..9b939102ccb8c8d8511c7cbefedd6c8c702645d6 100644 (file)
@@ -12,9 +12,9 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <common/mi-lttng.h>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 #include <lttng/lttng.h>
 
 static char *opt_output_path;
index fb42d14d5d5e5b931485383c71c291c52e30821e..8f9876f2a9278203c760667e6db9f9cf25524ebb 100644 (file)
@@ -14,9 +14,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/mi-lttng.h>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static char *opt_session_name;
 
index 8e19fa3d86f40f0bca00996793ed15cbab72081c..61ec0ae8a399c30a1750dcbebb2318b32a9b8a18 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/utils.h>
-#include <common/mi-lttng.h>
+#include <common/utils.hpp>
+#include <common/mi-lttng.hpp>
 #include <lttng/lttng.h>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static const char *opt_session_name;
 static const char *opt_output_name;
index 7082e097dfa5a3dcc9f9f7b384d7bfbbd90b2ea2..ac9cd14473ecea73c2da9cf9bc712fdfa445c017 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/mi-lttng.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 
 
 static char *opt_session_name;
index 23e8c03d390bc8fa2007cd82e7e271ec5bcda810..a77830ece028d002ba0cf97ac30019ff585d7267 100644 (file)
@@ -14,8 +14,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "../command.h"
-#include "../utils.h"
+#include "../command.hpp"
+#include "../utils.hpp"
 #include <config.h>
 
 #ifdef LTTNG_EMBED_HELP
index d69da40abe677b63c6ba5860416667ff97b6917c..3318eec67ae4abae1822dbb254d75e0403d4b358 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/mi-lttng.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
+#include "../command.hpp"
 
 static char *opt_session_name;
 static int opt_no_wait;
index 59b6144232a3efe335d8e7eb980f7a9241573613..1dd11b18b7e27e7fd86f2e8e57b1a47e8af11f0f 100644 (file)
 
 #include <urcu/list.h>
 
-#include <common/dynamic-array.h>
-#include <common/mi-lttng.h>
-#include <common/optional.h>
-#include <common/dynamic-buffer.h>
-#include <common/tracker.h>
+#include <common/dynamic-array.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/optional.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/tracker.hpp>
 
 #include <lttng/lttng.h>
 
-#include "../command.h"
+#include "../command.hpp"
 
 struct process_attr_command_args {
        enum lttng_process_attr process_attr;
index ccc7f6633d7e4a318e7aae6a4f3eb926b1295463..2e1851e0b912e2d07860a867cf59cded1543023d 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/mi-lttng.h>
+#include <common/mi-lttng.hpp>
 
-#include "../command.h"
-#include "version.h"
+#include "../command.hpp"
+#include "version.hpp"
 
 #ifdef LTTNG_EMBED_HELP
 static const char help_msg[] =
index a2623fe49e0ccb66b4baecbf1f27552d22ffad43..1bf2648714193fd9270c57ef30931224c759ed09 100644 (file)
@@ -14,8 +14,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/spawn-viewer.h>
-#include "../command.h"
+#include <common/spawn-viewer.hpp>
+#include "../command.hpp"
 
 static char *opt_session_name;
 static char *opt_viewer;
index e347c4b3afdd2361df09c877e464bc8038fd112a..a28a2c390924b3d8e57e71af64ce2ccb4d527981 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/compat/errno.h>
-#include <common/common.h>
-#include <common/utils.h>
+#include <common/compat/errno.hpp>
+#include <common/common.hpp>
+#include <common/utils.hpp>
 
-#include "conf.h"
+#include "conf.hpp"
 
 /*
  * Returns the path with '/CONFIG_FILENAME' added to it;
diff --git a/src/bin/lttng/conf.h b/src/bin/lttng/conf.h
deleted file mode 100644 (file)
index dcfce05..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_CONFIG_H
-#define _LTTNG_CONFIG_H
-
-#define CONFIG_FILENAME ".lttngrc"
-
-void config_destroy(const char *path);
-void config_destroy_default(void);
-int config_exists(const char *path);
-int config_init(const char *path);
-int config_add_session_name(const char *path, const char *name);
-
-/* Must free() the return pointer */
-char *config_read_session_name(const char *path);
-char *config_read_session_name_quiet(const char *path);
-char *config_get_file_path(const char *path);
-
-#endif /* _LTTNG_CONFIG_H */
diff --git a/src/bin/lttng/conf.hpp b/src/bin/lttng/conf.hpp
new file mode 100644 (file)
index 0000000..dcfce05
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_CONFIG_H
+#define _LTTNG_CONFIG_H
+
+#define CONFIG_FILENAME ".lttngrc"
+
+void config_destroy(const char *path);
+void config_destroy_default(void);
+int config_exists(const char *path);
+int config_init(const char *path);
+int config_add_session_name(const char *path, const char *name);
+
+/* Must free() the return pointer */
+char *config_read_session_name(const char *path);
+char *config_read_session_name_quiet(const char *path);
+char *config_get_file_path(const char *path);
+
+#endif /* _LTTNG_CONFIG_H */
index 83c7b3048f02b1202f1aee312b7cff2ebcc15628..fe588bd8e01d957727e2acd7a3e04d42c23cc994 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include "loglevel.h"
+#include "loglevel.hpp"
 #include <string.h>
 #include <strings.h>
 #include <ctype.h>
diff --git a/src/bin/lttng/loglevel.h b/src/bin/lttng/loglevel.h
deleted file mode 100644 (file)
index 43ae8e4..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_LOGLEVEL_UTILS_H
-#define _LTTNG_LOGLEVEL_UTILS_H
-
-#include <lttng/lttng.h>
-#include <common/macros.h>
-
-int loglevel_name_to_value(const char *name, enum lttng_loglevel *loglevel);
-
-bool loglevel_parse_range_string(const char *str,
-               enum lttng_loglevel *min,
-               enum lttng_loglevel *max);
-
-int loglevel_log4j_name_to_value(
-               const char *name, enum lttng_loglevel_log4j *loglevel);
-
-bool loglevel_log4j_parse_range_string(const char *str,
-               enum lttng_loglevel_log4j *min,
-               enum lttng_loglevel_log4j *max);
-
-int loglevel_jul_name_to_value(
-               const char *name, enum lttng_loglevel_jul *loglevel);
-
-bool loglevel_jul_parse_range_string(const char *str,
-               enum lttng_loglevel_jul *min,
-               enum lttng_loglevel_jul *max);
-
-int loglevel_python_name_to_value(
-               const char *name, enum lttng_loglevel_python *loglevel);
-
-bool loglevel_python_parse_range_string(const char *str,
-               enum lttng_loglevel_python *min,
-               enum lttng_loglevel_python *max);
-
-const char *loglevel_value_to_name(int loglevel);
-
-const char *loglevel_log4j_value_to_name(int loglevel);
-
-const char *loglevel_jul_value_to_name(int loglevel);
-
-const char *loglevel_python_value_to_name(int loglevel);
-
-#endif /* _LTTNG_LOGLEVEL_UTILS_H */
diff --git a/src/bin/lttng/loglevel.hpp b/src/bin/lttng/loglevel.hpp
new file mode 100644 (file)
index 0000000..f2cc913
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_LOGLEVEL_UTILS_H
+#define _LTTNG_LOGLEVEL_UTILS_H
+
+#include <lttng/lttng.h>
+#include <common/macros.hpp>
+
+int loglevel_name_to_value(const char *name, enum lttng_loglevel *loglevel);
+
+bool loglevel_parse_range_string(const char *str,
+               enum lttng_loglevel *min,
+               enum lttng_loglevel *max);
+
+int loglevel_log4j_name_to_value(
+               const char *name, enum lttng_loglevel_log4j *loglevel);
+
+bool loglevel_log4j_parse_range_string(const char *str,
+               enum lttng_loglevel_log4j *min,
+               enum lttng_loglevel_log4j *max);
+
+int loglevel_jul_name_to_value(
+               const char *name, enum lttng_loglevel_jul *loglevel);
+
+bool loglevel_jul_parse_range_string(const char *str,
+               enum lttng_loglevel_jul *min,
+               enum lttng_loglevel_jul *max);
+
+int loglevel_python_name_to_value(
+               const char *name, enum lttng_loglevel_python *loglevel);
+
+bool loglevel_python_parse_range_string(const char *str,
+               enum lttng_loglevel_python *min,
+               enum lttng_loglevel_python *max);
+
+const char *loglevel_value_to_name(int loglevel);
+
+const char *loglevel_log4j_value_to_name(int loglevel);
+
+const char *loglevel_jul_value_to_name(int loglevel);
+
+const char *loglevel_python_value_to_name(int loglevel);
+
+#endif /* _LTTNG_LOGLEVEL_UTILS_H */
index af1d3f4882cfd7fc6894257099a85f785cd5f6b0..bde66c06f6f1594b17f80d8abae66833d0159bcb 100644 (file)
 #include <ctype.h>
 
 #include <lttng/lttng.h>
-#include <common/error.h>
-#include <common/compat/getenv.h>
-#include <common/utils.h>
+#include <common/error.hpp>
+#include <common/compat/getenv.hpp>
+#include <common/utils.hpp>
 
-#include "command.h"
-#include "version.h"
+#include "command.hpp"
+#include "version.hpp"
 
 static const char *help_msg =
 #ifdef LTTNG_EMBED_HELP
index 7a119ae61dea32fc4999f45cdba159cfa134c1fe..8f873852451d78920331c047b7bd49346c23cc74 100644 (file)
@@ -5,18 +5,18 @@
  *
  */
 
-#include "uprobe.h"
+#include "uprobe.hpp"
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "common/compat/getenv.h"
-#include "common/string-utils/string-utils.h"
-#include "common/utils.h"
+#include "common/compat/getenv.hpp"
+#include "common/string-utils/string-utils.hpp"
+#include "common/utils.hpp"
 #include "lttng/constant.h"
 
-#include "command.h"
+#include "command.hpp"
 
 /*
  * Walk the directories in the PATH environment variable to find the target
diff --git a/src/bin/lttng/uprobe.h b/src/bin/lttng/uprobe.h
deleted file mode 100644 (file)
index 54dc674..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2020 EfficiOS, Inc.
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef SRC_BIN_LTTNG_UPROBE_H
-#define SRC_BIN_LTTNG_UPROBE_H
-
-#include <common/macros.h>
-
-struct lttng_userspace_probe_location;
-
-int parse_userspace_probe_opts(const char *opt,
-               struct lttng_userspace_probe_location **uprobe_loc);
-
-#endif /* SRC_BIN_LTTNG_UPROBE_H */
diff --git a/src/bin/lttng/uprobe.hpp b/src/bin/lttng/uprobe.hpp
new file mode 100644 (file)
index 0000000..8373312
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2020 EfficiOS, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef SRC_BIN_LTTNG_UPROBE_H
+#define SRC_BIN_LTTNG_UPROBE_H
+
+#include <common/macros.hpp>
+
+struct lttng_userspace_probe_location;
+
+int parse_userspace_probe_opts(const char *opt,
+               struct lttng_userspace_probe_location **uprobe_loc);
+
+#endif /* SRC_BIN_LTTNG_UPROBE_H */
index 6440ca7dfc883db2bd282aeff098e4acaa910977..85b422020f97d43ab34c81d5bd41e97b2b011e5d 100644 (file)
 #include <inttypes.h>
 #include <unistd.h>
 
-#include <common/error.h>
-#include <common/utils.h>
-#include <common/defaults.h>
+#include <common/error.hpp>
+#include <common/utils.hpp>
+#include <common/defaults.hpp>
 
-#include "conf.h"
-#include "utils.h"
-#include "command.h"
+#include "conf.hpp"
+#include "utils.hpp"
+#include "command.hpp"
 
 static const char *str_all = "ALL";
 static const char *str_tracepoint = "Tracepoint";
diff --git a/src/bin/lttng/utils.h b/src/bin/lttng/utils.h
deleted file mode 100644 (file)
index ba893ed..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_UTILS_H
-#define _LTTNG_UTILS_H
-
-#include <popt.h>
-#include <common/argpar/argpar.h>
-#include <common/dynamic-array.h>
-
-#include <lttng/lttng.h>
-
-extern char *opt_relayd_path;
-extern int opt_no_sessiond;
-extern char * opt_sessiond_path;
-extern pid_t sessiond_pid;
-
-struct cmd_struct;
-
-char *get_session_name(void);
-char *get_session_name_quiet(void);
-void list_commands(struct cmd_struct *commands, FILE *ofp);
-void list_cmd_options(FILE *ofp, struct poptOption *options);
-void list_cmd_options_argpar(FILE *ofp, const struct argpar_opt_descr *options);
-
-/*
- * Return the minimum order for which x <= (1UL << order).
- * Return -1 if x is 0.
- */
-int get_count_order_u32(uint32_t x);
-
-/*
- * Return the minimum order for which x <= (1UL << order).
- * Return -1 if x is 0.
- */
-int get_count_order_u64(uint64_t x);
-
-/*
- * Return the minimum order for which x <= (1UL << order).
- * Return -1 if x is 0.
- */
-int get_count_order_ulong(unsigned long x);
-
-const char *get_event_type_str(enum lttng_event_type event_type);
-
-int print_missing_or_multiple_domains(unsigned int domain_count,
-               bool include_agent_domains);
-
-int spawn_relayd(const char *pathname, int port);
-int check_relayd(void);
-void print_session_stats(const char *session_name);
-int get_session_stats_str(const char *session_name, char **str);
-int show_cmd_help(const char *cmd_name, const char *help_msg);
-
-int print_trace_archive_location(
-               const struct lttng_trace_archive_location *location,
-               const char *session_name);
-
-int validate_exclusion_list(const char *event_name,
-               const struct lttng_dynamic_pointer_array *exclusions);
-
-#endif /* _LTTNG_UTILS_H */
diff --git a/src/bin/lttng/utils.hpp b/src/bin/lttng/utils.hpp
new file mode 100644 (file)
index 0000000..8ac7873
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_UTILS_H
+#define _LTTNG_UTILS_H
+
+#include <popt.h>
+#include <common/argpar/argpar.h>
+#include <common/dynamic-array.hpp>
+
+#include <lttng/lttng.h>
+
+extern char *opt_relayd_path;
+extern int opt_no_sessiond;
+extern char * opt_sessiond_path;
+extern pid_t sessiond_pid;
+
+struct cmd_struct;
+
+char *get_session_name(void);
+char *get_session_name_quiet(void);
+void list_commands(struct cmd_struct *commands, FILE *ofp);
+void list_cmd_options(FILE *ofp, struct poptOption *options);
+void list_cmd_options_argpar(FILE *ofp, const struct argpar_opt_descr *options);
+
+/*
+ * Return the minimum order for which x <= (1UL << order).
+ * Return -1 if x is 0.
+ */
+int get_count_order_u32(uint32_t x);
+
+/*
+ * Return the minimum order for which x <= (1UL << order).
+ * Return -1 if x is 0.
+ */
+int get_count_order_u64(uint64_t x);
+
+/*
+ * Return the minimum order for which x <= (1UL << order).
+ * Return -1 if x is 0.
+ */
+int get_count_order_ulong(unsigned long x);
+
+const char *get_event_type_str(enum lttng_event_type event_type);
+
+int print_missing_or_multiple_domains(unsigned int domain_count,
+               bool include_agent_domains);
+
+int spawn_relayd(const char *pathname, int port);
+int check_relayd(void);
+void print_session_stats(const char *session_name);
+int get_session_stats_str(const char *session_name, char **str);
+int show_cmd_help(const char *cmd_name, const char *help_msg);
+
+int print_trace_archive_location(
+               const struct lttng_trace_archive_location *location,
+               const char *session_name);
+
+int validate_exclusion_list(const char *event_name,
+               const struct lttng_dynamic_pointer_array *exclusions);
+
+#endif /* _LTTNG_UTILS_H */
index 7ac2b09ccc9eaca9c35c28eb8621b384405d68a0..902c61df036d49f7e03e2730ceab883ada9f9ffd 100644 (file)
@@ -2,45 +2,45 @@
 
 AUTOMAKE_OPTIONS = subdir-objects
 
-SUBDIRS = \
-       argpar \
-       bytecode \
-       compat \
-       config \
-       ini-config \
-       fd-tracker \
-       string-utils \
-       filter \
-       hashtable \
-       argpar-utils
-
-# Make sure to always distribute all folders
-# since SUBDIRS is decided at configure time.
-DIST_SUBDIRS = \
-       compat \
-       health \
-       hashtable \
-       kernel-ctl \
-       sessiond-comm \
-       relayd \
-       kernel-consumer \
-       ust-consumer \
-       testpoint \
-       index \
-       config \
-       ini-config \
-       consumer \
-       string-utils \
-       fd-tracker \
-       bytecode \
-       filter \
-       argpar \
-       argpar-utils
-
-# Common library
-noinst_LTLIBRARIES = libcommon.la
-EXTRA_DIST = mi-lttng-4.1.xsd
+noinst_LTLIBRARIES =
 
+noinst_HEADERS = \
+       align.hpp \
+       bug.hpp \
+       defaults.hpp \
+       error.hpp \
+       futex.hpp \
+       lttng-kernel.hpp \
+       lttng-kernel-old.hpp \
+       macros.hpp \
+       time.hpp \
+       uri.hpp \
+       utils.hpp
+
+
+# libargpar
+noinst_LTLIBRARIES += libargpar.la
+libargpar_la_SOURCES = \
+       argpar/argpar.c \
+       argpar/argpar.h
+
+
+# libargpar-utils
+noinst_LTLIBRARIES += libargpar-utils.la
+libargpar_utils_la_SOURCES = \
+       argpar-utils/argpar-utils.cpp \
+       argpar-utils/argpar-utils.hpp
+
+
+# libbytecode
+noinst_LTLIBRARIES += libbytecode.la
+libbytecode_la_SOURCES = \
+       bytecode/bytecode.cpp \
+       bytecode/bytecode.hpp
+
+
+# libcommon
+noinst_LTLIBRARIES += libcommon.la
 libcommon_la_SOURCES = \
        actions/action.cpp \
        actions/list.cpp \
@@ -51,22 +51,22 @@ libcommon_la_SOURCES = \
        actions/start-session.cpp \
        actions/stop-session.cpp \
        actions/rate-policy.cpp \
-       buffer-view.h buffer-view.cpp \
-       common.h \
+       buffer-view.hpp buffer-view.cpp \
+       common.hpp \
        conditions/buffer-usage.cpp \
        conditions/condition.cpp \
        conditions/event-rule-matches.cpp \
        conditions/session-consumed-size.cpp \
        conditions/session-rotation.cpp \
-       context.cpp context.h \
-       credentials.cpp credentials.h \
-       daemonize.cpp daemonize.h \
+       context.cpp context.hpp \
+       credentials.cpp credentials.hpp \
+       daemonize.cpp daemonize.hpp \
        defaults.cpp \
        domain.cpp \
-       dynamic-array.cpp dynamic-array.h \
-       dynamic-buffer.cpp dynamic-buffer.h \
+       dynamic-array.cpp dynamic-array.hpp \
+       dynamic-buffer.cpp dynamic-buffer.hpp \
        endpoint.cpp \
-       error.cpp error.h \
+       error.cpp error.hpp \
        error-query.cpp \
        evaluation.cpp \
        event.cpp \
@@ -81,109 +81,328 @@ libcommon_la_SOURCES = \
        event-rule/log4j-logging.cpp \
        event-rule/jul-logging.cpp \
        event-rule/python-logging.cpp \
-       filter.cpp filter.h \
-       fd-handle.cpp fd-handle.h \
-       fs-handle.cpp fs-handle.h fs-handle-internal.h \
-       futex.cpp futex.h \
+       filter.cpp filter.hpp \
+       fd-handle.cpp fd-handle.hpp \
+       fs-handle.cpp fs-handle.hpp fs-handle-internal.hpp \
+       futex.cpp futex.hpp \
        kernel-probe.cpp \
-       index-allocator.cpp index-allocator.h \
+       index-allocator.cpp index-allocator.hpp \
        location.cpp \
        log-level-rule.cpp \
-       mi-lttng.cpp mi-lttng.h \
+       mi-lttng.cpp mi-lttng.hpp \
        notification.cpp \
-       optional.h \
-       payload.cpp payload.h \
-       payload-view.cpp payload-view.h \
-       pipe.cpp pipe.h \
-       readwrite.cpp readwrite.h \
-       runas.cpp runas.h \
-       shm.cpp shm.h \
+       optional.hpp \
+       payload.cpp payload.hpp \
+       payload-view.cpp payload-view.hpp \
+       pipe.cpp pipe.hpp \
+       readwrite.cpp readwrite.hpp \
+       runas.cpp runas.hpp \
+       shm.cpp shm.hpp \
        session-descriptor.cpp \
-       snapshot.cpp snapshot.h \
-       spawn-viewer.cpp spawn-viewer.h \
+       snapshot.cpp snapshot.hpp \
+       spawn-viewer.cpp spawn-viewer.hpp \
        time.cpp \
-       trace-chunk.cpp trace-chunk.h \
-       trace-chunk-registry.h \
+       trace-chunk.cpp trace-chunk.hpp \
+       trace-chunk-registry.hpp \
        trigger.cpp \
-       unix.cpp unix.h \
-       uri.cpp uri.h \
+       unix.cpp unix.hpp \
+       uri.cpp uri.hpp \
        userspace-probe.cpp \
-       utils.cpp utils.h \
-       uuid.cpp uuid.h \
-       thread.cpp thread.h \
-       tracker.cpp tracker.h \
-       waiter.cpp waiter.h
+       utils.cpp utils.hpp \
+       uuid.cpp uuid.hpp \
+       thread.cpp thread.hpp \
+       tracker.cpp tracker.hpp \
+       waiter.cpp waiter.hpp
 
 if HAVE_ELF_H
 libcommon_la_SOURCES += \
-       lttng-elf.cpp lttng-elf.h
+       lttng-elf.cpp lttng-elf.hpp
 endif
 
 libcommon_la_LIBADD = \
-       $(top_builddir)/src/common/bytecode/libbytecode.la \
-       $(top_builddir)/src/common/config/libconfig.la \
-       $(top_builddir)/src/common/ini-config/libini-config.la \
-       $(top_builddir)/src/common/compat/libcompat.la \
-       $(top_builddir)/src/common/hashtable/libhashtable.la \
-       $(top_builddir)/src/common/fd-tracker/libfd-tracker.la \
-       $(top_builddir)/src/common/filter/libfilter.la \
+       libbytecode.la \
+       libcompat.la \
+       libconfig.la \
+       libfd-tracker.la \
+       libhashtable.la \
+       libini-config.la \
+       libstring-utils.la \
+       libfilter.la \
        $(top_builddir)/src/vendor/msgpack/libmsgpack.la
 
+
+# libcompat
+noinst_LTLIBRARIES += libcompat.la
+libcompat_la_SOURCES = \
+        compat/compat-fcntl.cpp \
+        compat/directory-handle.cpp \
+        compat/directory-handle.hpp \
+        compat/dirent.hpp \
+        compat/endian.hpp \
+        compat/errno.hpp \
+        compat/fcntl.hpp \
+        compat/getenv.hpp \
+        compat/mman.hpp \
+        compat/netdb.hpp \
+        compat/path.hpp \
+        compat/paths.hpp \
+        compat/poll.cpp \
+        compat/poll.hpp \
+        compat/pthread.hpp \
+        compat/socket.hpp \
+        compat/string.hpp \
+        compat/tid.hpp \
+        compat/time.hpp
+
+
+# libconfig
+noinst_LTLIBRARIES += libconfig.la
+libconfig_la_SOURCES = \
+       config/config-internal.hpp \
+       config/config-session-abi.hpp \
+       config/session-config.cpp \
+       config/session-config.hpp
+
+libconfig_la_CPPFLAGS = $(libxml2_CFLAGS) $(AM_CPPFLAGS)
+libconfig_la_LIBADD = ${libxml2_LIBS}
+
+
+if BUILD_LIB_CONSUMER
+noinst_LTLIBRARIES += libconsumer.la
+
+libconsumer_la_SOURCES = \
+       consumer/consumer.cpp \
+       consumer/consumer.hpp \
+       consumer/consumer-metadata-cache.cpp \
+       consumer/consumer-metadata-cache.hpp \
+       consumer/consumer-stream.cpp \
+       consumer/consumer-stream.hpp \
+       consumer/consumer-testpoint.hpp \
+       consumer/consumer-timer.cpp \
+       consumer/consumer-timer.hpp \
+       consumer/metadata-bucket.cpp \
+       consumer/metadata-bucket.hpp
+
+libconsumer_la_LIBADD = \
+       libcompat.la \
+       libhashtable.la \
+       libkernel-consumer.la \
+       librelayd.la \
+       libsessiond-comm.la
+
+if HAVE_LIBLTTNG_UST_CTL
+libconsumer_la_LIBADD += \
+       libust-consumer.la
+endif
+endif # BUILD_LIB_CONSUMER
+
+
+# libfd-tracker
+noinst_LTLIBRARIES += libfd-tracker.la
+libfd_tracker_la_SOURCES = \
+       fd-tracker/fd-tracker.cpp \
+       fd-tracker/fd-tracker.hpp \
+       fd-tracker/inode.cpp \
+       fd-tracker/inode.hpp \
+       fd-tracker/utils.cpp \
+       fd-tracker/utils.hpp \
+       fd-tracker/utils-poll.cpp
+
+# libfilter
+noinst_LTLIBRARIES += libfilter.la
+
+libfilter_la_SOURCES = \
+       filter/filter-ast.hpp \
+       filter/filter-ir.hpp \
+       filter/filter-lexer.lpp \
+       filter/filter-parser.ypp \
+       filter/filter-symbols.hpp \
+       filter/filter-visitor-generate-bytecode.cpp \
+       filter/filter-visitor-generate-ir.cpp \
+       filter/filter-visitor-ir-check-binary-op-nesting.cpp \
+       filter/filter-visitor-ir-normalize-glob-patterns.cpp \
+       filter/filter-visitor-ir-validate-globbing.cpp \
+       filter/filter-visitor-ir-validate-string.cpp \
+       filter/filter-visitor-xml.cpp \
+       filter/memstream.hpp
+
+BUILT_SOURCES = filter/filter-parser.hpp
+
+libfilter_la_CXXFLAGS = -include filter-symbols.hpp $(AM_CXXFLAGS)
+libfilter_la_CPPFLAGS = -I$(srcdir)/filter -I$(builddir)/filter $(AM_CPPFLAGS)
+
+AM_YFLAGS = -t -d -v -Wno-yacc
+
+# start with empty files to clean
+CLEANFILES =
+
+if HAVE_BISON
+# we have bison: we can clean the generated parser files
+CLEANFILES += \
+       filter/filter-parser.cpp \
+       filter/filter-parser.hpp \
+       filter/filter-parser.output
+else # HAVE_BISON
+# create target used to stop the build if we want to build the parser,
+# but we don't have the necessary tool to do so
+ERR_MSG = "Error: Cannot build target because bison is missing."
+ERR_MSG += "Make sure bison is installed and run the configure script again."
+
+filter/filter-parser.cpp filter/filter-parser.hpp: filter/filter-parser.ypp
+       @echo $(ERR_MSG)
+       @false
+
+all-local: filter/filter-parser.cpp filter/filter-parser.hpp
+endif # HAVE_BISON
+
+if HAVE_FLEX
+# we have flex: we can clean the generated lexer files
+CLEANFILES += filter/filter-lexer.cpp
+else # HAVE_FLEX
+# create target used to stop the build if we want to build the lexer,
+# but we don't have the necessary tool to do so
+ERR_MSG = "Error: Cannot build target because flex is missing."
+ERR_MSG += "Make sure flex is installed and run the configure script again."
+
+filter/filter-lexer.cpp: filter/filter-lexer.lpp
+       @echo $(ERR_MSG)
+       @false
+
+all-local: filter/filter-lexer.cpp
+endif # HAVE_FLEX
+
+
+# libhashtable
+noinst_LTLIBRARIES += libhashtable.la
+libhashtable_la_SOURCES = \
+       hashtable/hashtable.cpp \
+       hashtable/hashtable.hpp \
+       hashtable/hashtable-symbols.hpp \
+        hashtable/utils.cpp \
+       hashtable/utils.hpp
+
+libhashtable_la_LIBADD = $(URCU_LIBS) $(URCU_CDS_LIBS)
+
+
 if BUILD_LIB_HEALTH
-SUBDIRS += health
+noinst_LTLIBRARIES += libhealth.la
+
+libhealth_la_SOURCES = \
+       health/health.cpp
 endif
 
+
+# libini-config
+noinst_LTLIBRARIES += libini-config.la
+libini_config_la_SOURCES = \
+       ini-config/ini.cpp \
+       ini-config/ini.hpp \
+       ini-config/ini-config.cpp \
+       ini-config/ini-config.hpp
+
+
+if BUILD_LIB_INDEX
+noinst_LTLIBRARIES += libindex.la
+
+libindex_la_SOURCES = \
+       index/ctf-index.hpp \
+       index/index.cpp \
+       index/index.hpp
+endif
+
+
 if BUILD_LIB_KERNEL_CTL
-SUBDIRS += kernel-ctl
+noinst_LTLIBRARIES += libkernel-ctl.la
+
+libkernel_ctl_la_SOURCES = \
+       kernel-ctl/kernel-ctl.cpp \
+       kernel-ctl/kernel-ctl.hpp \
+       kernel-ctl/kernel-ioctl.hpp
 endif
 
 if BUILD_LIB_SESSIOND_COMM
-SUBDIRS += sessiond-comm
+noinst_LTLIBRARIES += libsessiond-comm.la
+
+libsessiond_comm_la_SOURCES = \
+       sessiond-comm/agent.hpp \
+       sessiond-comm/inet.cpp \
+       sessiond-comm/inet.hpp \
+       sessiond-comm/inet6.cpp \
+       sessiond-comm/inet6.hpp \
+       sessiond-comm/relayd.hpp \
+       sessiond-comm/sessiond-comm.cpp \
+       sessiond-comm/sessiond-comm.hpp
 endif
 
 if BUILD_LIB_RELAYD
-SUBDIRS += relayd
+noinst_LTLIBRARIES += librelayd.la
+
+librelayd_la_SOURCES = \
+       relayd/relayd.cpp \
+       relayd/relayd.hpp
+
+librelayd_la_LIBADD = libsessiond-comm.la
 endif
 
 
 if BUILD_LIB_KERNEL_CONSUMER
-SUBDIRS += kernel-consumer
+noinst_LTLIBRARIES += libkernel-consumer.la
+
+libkernel_consumer_la_SOURCES = \
+       kernel-consumer/kernel-consumer.cpp \
+       kernel-consumer/kernel-consumer.hpp
+
+libkernel_consumer_la_LIBADD = \
+       libkernel-ctl.la \
+       librelayd.la
 endif
 
 if BUILD_LIB_UST_CONSUMER
-SUBDIRS += ust-consumer
+if HAVE_LIBLTTNG_UST_CTL
+noinst_LTLIBRARIES += libust-consumer.la
+
+libust_consumer_la_SOURCES = \
+       ust-consumer/ust-consumer.cpp \
+       ust-consumer/ust-consumer.hpp
+
+libust_consumer_la_LIBADD = \
+       $(UST_CTL_LIBS) \
+       librelayd.la
+endif
 endif
 
 if BUILD_LIB_TESTPOINT
-SUBDIRS += testpoint
-endif
+noinst_LTLIBRARIES += libtestpoint.la
 
-if BUILD_LIB_INDEX
-SUBDIRS += index
-endif
+libtestpoint_la_SOURCES = \
+       testpoint/testpoint.cpp \
+       testpoint/testpoint.hpp
 
-if BUILD_LIB_CONSUMER
-SUBDIRS += consumer
+libtestpoint_la_LIBADD = $(DL_LIBS)
 endif
 
-noinst_HEADERS = \
-       align.h \
-       bug.h \
-       defaults.h \
-       error.h \
-       futex.h \
-       lttng-kernel.h \
-       lttng-kernel-old.h \
-       macros.h \
-       time.h \
-       uri.h \
-       utils.h
+
+# libstring-utils
+noinst_LTLIBRARIES += libstring-utils.la
+libstring_utils_la_SOURCES = \
+       string-utils/format.hpp \
+       string-utils/string-utils.cpp \
+       string-utils/string-utils.hpp
+
 
 noinst_PROGRAMS = filter-grammar-test
 filter_grammar_test_SOURCES = filter-grammar-test.cpp
 filter_grammar_test_LDADD = \
        libcommon.la
 
+EXTRA_DIST = \
+       mi-lttng-4.1.xsd \
+       session.xsd
+
+xmldir = $(datadir)/xml/lttng
+dist_xml_DATA = session.xsd
+
+# Copy EXTRA_DIST files to the build directory
 all-local:
        @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
                for script in $(EXTRA_DIST); do \
index b71538b3f477d10a4dbf9b8de29d97ebf289edd3..74dec1247468324df9c42d57ccff7567a740c697 100644 (file)
@@ -5,17 +5,17 @@
  *
  */
 
-#include <common/error.h>
-#include <common/mi-lttng.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/list-internal.h>
-#include <lttng/action/notify-internal.h>
-#include <lttng/action/rate-policy-internal.h>
-#include <lttng/action/rotate-session-internal.h>
-#include <lttng/action/snapshot-session-internal.h>
-#include <lttng/action/start-session-internal.h>
-#include <lttng/action/stop-session-internal.h>
-#include <lttng/error-query-internal.h>
+#include <common/error.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/list-internal.hpp>
+#include <lttng/action/notify-internal.hpp>
+#include <lttng/action/rate-policy-internal.hpp>
+#include <lttng/action/rotate-session-internal.hpp>
+#include <lttng/action/snapshot-session-internal.hpp>
+#include <lttng/action/start-session-internal.hpp>
+#include <lttng/action/stop-session-internal.hpp>
+#include <lttng/error-query-internal.hpp>
 
 const char *lttng_action_type_string(enum lttng_action_type action_type)
 {
index 42d3d653e1bce7a53f351693467e9e8a51bbb7da..c80832570d2dab694a4e77c61a33adffc84cdd26 100644 (file)
@@ -5,14 +5,14 @@
  *
  */
 
-#include <common/dynamic-array.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/list-internal.h>
+#include <common/dynamic-array.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/list-internal.hpp>
 #include <lttng/action/list.h>
 
 #define IS_LIST_ACTION(action) \
index e3f837adeabaca6288c79770b4060b2ba3f37b1a..8ee51c31617a6370b776a5415230056bfa9f2901 100644 (file)
@@ -5,12 +5,12 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/notify-internal.h>
-#include <lttng/action/rate-policy-internal.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/notify-internal.hpp>
+#include <lttng/action/rate-policy-internal.hpp>
 #include <lttng/lttng-error.h>
 
 #define IS_NOTIFY_ACTION(action) \
index 816f2cd219cd49d865270136e68cacf2617a8c7d..0c8181896dfc612614baebf3775d5a37c250c2e7 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include <lttng/action/path-internal.h>
+#include <lttng/action/path-internal.hpp>
 
 struct lttng_action_path_comm {
        uint32_t index_count;
index d0834dd732e14c2f203897b7dc743dbb137307bf..58db624d8312814bff23b1fec56e78ee4d5c698a 100644 (file)
@@ -5,15 +5,15 @@
  *
  */
 
-#include <common/buffer-view.h>
-#include <common/dynamic-buffer.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
+#include <common/buffer-view.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
 #include <limits.h>
-#include <lttng/action/rate-policy-internal.h>
+#include <lttng/action/rate-policy-internal.hpp>
 #include <lttng/action/rate-policy.h>
 #include <stdbool.h>
 #include <sys/types.h>
index 985036acc84bc26818444b45b63c30add3126716..ad2f9e2938c1d7bc228adce90cb7d8800e90bdfe 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/rate-policy-internal.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/rate-policy-internal.hpp>
 #include <lttng/action/rate-policy.h>
-#include <lttng/action/rotate-session-internal.h>
+#include <lttng/action/rotate-session-internal.hpp>
 #include <lttng/action/rotate-session.h>
 
 #define IS_ROTATE_SESSION_ACTION(action) \
index 0f3da782fd1c37832ca21697821e4434ec99617c..600d803e3610b1d065a23cbe82e7fc79e2151596 100644 (file)
@@ -5,19 +5,19 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/snapshot.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/snapshot.hpp>
 #include <inttypes.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/rate-policy-internal.h>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/rate-policy-internal.hpp>
 #include <lttng/action/rate-policy.h>
-#include <lttng/action/snapshot-session-internal.h>
+#include <lttng/action/snapshot-session-internal.hpp>
 #include <lttng/action/snapshot-session.h>
-#include <lttng/snapshot-internal.h>
+#include <lttng/snapshot-internal.hpp>
 #include <lttng/snapshot.h>
 
 #define IS_SNAPSHOT_SESSION_ACTION(action) \
index 1312e5ec5f278e3026893089e080fe87f8dbc6ca..739540189e24dbb3882345007b6579103e572552 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/rate-policy-internal.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/rate-policy-internal.hpp>
 #include <lttng/action/rate-policy.h>
-#include <lttng/action/start-session-internal.h>
+#include <lttng/action/start-session-internal.hpp>
 #include <lttng/action/start-session.h>
 
 #define IS_START_SESSION_ACTION(action) \
index 55f1a55ed239df31bcfa40771c6d0f48bb4fa6f6..3cffb4a553b8a774684b0a438856273544609052 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/rate-policy-internal.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/rate-policy-internal.hpp>
 #include <lttng/action/rate-policy.h>
-#include <lttng/action/stop-session-internal.h>
+#include <lttng/action/stop-session-internal.hpp>
 #include <lttng/action/stop-session.h>
 
 #define IS_STOP_SESSION_ACTION(action) \
diff --git a/src/common/align.h b/src/common/align.h
deleted file mode 100644 (file)
index dff6c91..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef _LTTNG_ALIGN_H
-#define _LTTNG_ALIGN_H
-
-#include "bug.h"
-
-/*
- * Align value to the next multiple of align. Returns val if it already is a
- * multiple of align. Align must be a power of two.
- */
-#define __lttng_align_ceil_mask(v, mask)       (((v) + (mask)) & ~(mask))
-
-#define lttng_align_ceil(v, align) \
-       __lttng_align_ceil_mask(v, (__typeof__(v)) (align) - 1)
-
-/*
- * Align value to the previous multiple of align. Returns val if it already is a
- * multiple of align. Align must be a power of two.
- */
-#define __lttng_align_floor_mask(v, mask)      ((v) & ~(mask))
-
-#define lttng_align_floor(v, align) \
-       __lttng_align_floor_mask(v, (__typeof__(v)) (align) - 1)
-
-/**
- * lttng_offset_align - Calculate the offset needed to align an object on its natural
- *                alignment towards higher addresses.
- * @align_drift:  object offset from an "alignment"-aligned address.
- * @alignment:    natural object alignment. Must be non-zero, power of 2.
- *
- * Returns the offset that must be added to align towards higher
- * addresses.
- */
-#define lttng_offset_align(align_drift, alignment)                                    \
-       ({                                                                     \
-               LTTNG_BUILD_RUNTIME_BUG_ON((alignment) == 0                    \
-                                  || ((alignment) & ((alignment) - 1)));      \
-               (((alignment) - (align_drift)) & ((alignment) - 1));           \
-       })
-
-/**
- * lttng_offset_align_floor - Calculate the offset needed to align an object
- *                      on its natural alignment towards lower addresses.
- * @align_drift:  object offset from an "alignment"-aligned address.
- * @alignment:    natural object alignment. Must be non-zero, power of 2.
- *
- * Returns the offset that must be substracted to align towards lower addresses.
- */
-#define lttng_offset_align_floor(align_drift, alignment)                              \
-       ({                                                                     \
-               LTTNG_BUILD_RUNTIME_BUG_ON((alignment) == 0                    \
-                                  || ((alignment) & ((alignment) - 1)));      \
-               (((align_drift) - (alignment)) & ((alignment) - 1));           \
-       })
-
-#endif /* _LTTNG_ALIGN_H */
diff --git a/src/common/align.hpp b/src/common/align.hpp
new file mode 100644 (file)
index 0000000..c957824
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef _LTTNG_ALIGN_H
+#define _LTTNG_ALIGN_H
+
+#include "bug.hpp"
+
+/*
+ * Align value to the next multiple of align. Returns val if it already is a
+ * multiple of align. Align must be a power of two.
+ */
+#define __lttng_align_ceil_mask(v, mask)       (((v) + (mask)) & ~(mask))
+
+#define lttng_align_ceil(v, align) \
+       __lttng_align_ceil_mask(v, (__typeof__(v)) (align) - 1)
+
+/*
+ * Align value to the previous multiple of align. Returns val if it already is a
+ * multiple of align. Align must be a power of two.
+ */
+#define __lttng_align_floor_mask(v, mask)      ((v) & ~(mask))
+
+#define lttng_align_floor(v, align) \
+       __lttng_align_floor_mask(v, (__typeof__(v)) (align) - 1)
+
+/**
+ * lttng_offset_align - Calculate the offset needed to align an object on its natural
+ *                alignment towards higher addresses.
+ * @align_drift:  object offset from an "alignment"-aligned address.
+ * @alignment:    natural object alignment. Must be non-zero, power of 2.
+ *
+ * Returns the offset that must be added to align towards higher
+ * addresses.
+ */
+#define lttng_offset_align(align_drift, alignment)                                    \
+       ({                                                                     \
+               LTTNG_BUILD_RUNTIME_BUG_ON((alignment) == 0                    \
+                                  || ((alignment) & ((alignment) - 1)));      \
+               (((alignment) - (align_drift)) & ((alignment) - 1));           \
+       })
+
+/**
+ * lttng_offset_align_floor - Calculate the offset needed to align an object
+ *                      on its natural alignment towards lower addresses.
+ * @align_drift:  object offset from an "alignment"-aligned address.
+ * @alignment:    natural object alignment. Must be non-zero, power of 2.
+ *
+ * Returns the offset that must be substracted to align towards lower addresses.
+ */
+#define lttng_offset_align_floor(align_drift, alignment)                              \
+       ({                                                                     \
+               LTTNG_BUILD_RUNTIME_BUG_ON((alignment) == 0                    \
+                                  || ((alignment) & ((alignment) - 1)));      \
+               (((align_drift) - (alignment)) & ((alignment) - 1));           \
+       })
+
+#endif /* _LTTNG_ALIGN_H */
diff --git a/src/common/argpar-utils/Makefile.am b/src/common/argpar-utils/Makefile.am
deleted file mode 100644 (file)
index 53425cd..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-noinst_LTLIBRARIES = libargpar-utils.la
-
-libargpar_utils_la_SOURCES = \
-       argpar-utils.cpp \
-       argpar-utils.h
index 493598693632ec32556a0260488a7d16662c8a84..0beff92adfc7598bb02cc2389a406e517a84ae52 100644 (file)
@@ -5,12 +5,12 @@
  *
  */
 
-#include "argpar-utils.h"
+#include "argpar-utils.hpp"
 
 #include <stdio.h>
 
-#include <common/error.h>
-#include <common/string-utils/string-utils.h>
+#include <common/error.hpp>
+#include <common/string-utils/string-utils.hpp>
 
 /*
  * Given argpar error status `status` and error `error`, return a formatted
diff --git a/src/common/argpar-utils/argpar-utils.h b/src/common/argpar-utils/argpar-utils.h
deleted file mode 100644 (file)
index 1bdff7e..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef COMMON_ARGPAR_UTILS_H
-#define COMMON_ARGPAR_UTILS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdarg.h>
-
-#include <common/macros.h>
-#include <common/argpar/argpar.h>
-#include <common/string-utils/format.h>
-
-#define WHILE_PARSING_ARG_N_ARG_FMT "While parsing argument #%d (`%s`): "
-
-enum parse_next_item_status
-{
-       PARSE_NEXT_ITEM_STATUS_OK = 0,
-       PARSE_NEXT_ITEM_STATUS_END = 1,
-       PARSE_NEXT_ITEM_STATUS_ERROR = -1,
-       PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY = -2,
-};
-
-/*
- * Parse the next argpar item using `iter`.
- *
- * The item in `*item` is always freed and cleared on entry.
- *
- * If an item is parsed successfully, return the new item in `*item` and return
- * PARSE_NEXT_ITEM_STATUS_OK.
- *
- * If the end of the argument list is reached, return
- * PARSE_NEXT_ITEM_STATUS_END.
- *
- * On error, print a descriptive error message and return
- * PARSE_NEXT_ITEM_STATUS_ERROR.  If `context_fmt` is non-NULL, it is formatted
- * using the following arguments and prepended to the error message.
- * Add `argc_offset` to the argument index mentioned in the error message.
- *
- * If `unknown_opt_is_error` is true, an unknown option is considered an error.
- * Otherwise, it is considered as the end of the argument list.
- *
- * If `error_out` is given and PARSE_NEXT_ITEM_STATUS_ERROR is returned, set
- * `*error_out` to the argpar_error object corresponding to the error.  The
- * caller must free the object with `argpar_error_destroy`.
- */
-ATTR_FORMAT_PRINTF(7, 8)
-enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
-               const struct argpar_item **item, int argc_offset,
-               const char **argv, bool unknown_opt_is_error,
-               const struct argpar_error **error_out,
-               const char *context_fmt, ...);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/common/argpar-utils/argpar-utils.hpp b/src/common/argpar-utils/argpar-utils.hpp
new file mode 100644 (file)
index 0000000..ea77345
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef COMMON_ARGPAR_UTILS_H
+#define COMMON_ARGPAR_UTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#include <common/macros.hpp>
+#include <common/argpar/argpar.h>
+#include <common/string-utils/format.hpp>
+
+#define WHILE_PARSING_ARG_N_ARG_FMT "While parsing argument #%d (`%s`): "
+
+enum parse_next_item_status
+{
+       PARSE_NEXT_ITEM_STATUS_OK = 0,
+       PARSE_NEXT_ITEM_STATUS_END = 1,
+       PARSE_NEXT_ITEM_STATUS_ERROR = -1,
+       PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY = -2,
+};
+
+/*
+ * Parse the next argpar item using `iter`.
+ *
+ * The item in `*item` is always freed and cleared on entry.
+ *
+ * If an item is parsed successfully, return the new item in `*item` and return
+ * PARSE_NEXT_ITEM_STATUS_OK.
+ *
+ * If the end of the argument list is reached, return
+ * PARSE_NEXT_ITEM_STATUS_END.
+ *
+ * On error, print a descriptive error message and return
+ * PARSE_NEXT_ITEM_STATUS_ERROR.  If `context_fmt` is non-NULL, it is formatted
+ * using the following arguments and prepended to the error message.
+ * Add `argc_offset` to the argument index mentioned in the error message.
+ *
+ * If `unknown_opt_is_error` is true, an unknown option is considered an error.
+ * Otherwise, it is considered as the end of the argument list.
+ *
+ * If `error_out` is given and PARSE_NEXT_ITEM_STATUS_ERROR is returned, set
+ * `*error_out` to the argpar_error object corresponding to the error.  The
+ * caller must free the object with `argpar_error_destroy`.
+ */
+ATTR_FORMAT_PRINTF(7, 8)
+enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
+               const struct argpar_item **item, int argc_offset,
+               const char **argv, bool unknown_opt_is_error,
+               const struct argpar_error **error_out,
+               const char *context_fmt, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/common/argpar/Makefile.am b/src/common/argpar/Makefile.am
deleted file mode 100644 (file)
index 175526a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-noinst_LTLIBRARIES = libargpar.la
-
-libargpar_la_SOURCES = argpar.c argpar.h
index ebe6869852f90a2bec8e7f1283e24cd130e2f04e..9498423cae64efb38d1b5e55fbccd1db879bdd82 100644 (file)
@@ -5,9 +5,9 @@
  *
  */
 
-#include <common/buffer-view.h>
-#include <common/dynamic-buffer.h>
-#include <common/error.h>
+#include <common/buffer-view.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/error.hpp>
 
 struct lttng_buffer_view lttng_buffer_view_init(
                const char *src, size_t offset, ptrdiff_t len)
diff --git a/src/common/buffer-view.h b/src/common/buffer-view.h
deleted file mode 100644 (file)
index 58f1ede..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_BUFFER_VIEW_H
-#define LTTNG_BUFFER_VIEW_H
-
-#include <common/macros.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-struct lttng_dynamic_buffer;
-
-struct lttng_buffer_view {
-       const char *data;
-       size_t size;
-};
-
-/**
- * Return a buffer view referencing a subset of the memory referenced by a raw
- * pointer.
- *
- * @src                Source buffer to reference
- * @offset     Offset to apply to the source memory buffer
- * @len                Length of the memory contents to reference.
- *
- * Note that a buffer view never assumes the ownership of the memory it
- * references.
- */
-struct lttng_buffer_view lttng_buffer_view_init(
-               const char *src, size_t offset, ptrdiff_t len);
-
-/**
- * Checks if a buffer view is safe to access.
- *
- * After calling the buffer view creation functions, callers should verify
- * if the resquested length (if any is explicitly provided) could be mapped
- * to a new view.
- *
- * @view       Buffer view to validate
- */
-bool lttng_buffer_view_is_valid(const struct lttng_buffer_view *view);
-
-/**
- * Return a buffer view referencing a subset of the memory referenced by another
- * view.
- *
- * @src                Source view to reference
- * @offset     Offset to apply to the source memory content
- * @len                Length of the memory contents to reference. Passing -1 will
- *             cause the view to reference the whole view from the offset
- *             provided.
- *
- * Note that a buffer view never assumes the ownership of the memory it
- * references.
- */
-struct lttng_buffer_view lttng_buffer_view_from_view(
-               const struct lttng_buffer_view *src, size_t offset,
-               ptrdiff_t len);
-
-/**
- * Return a buffer view referencing a subset of the memory referenced by a
- * dynamic buffer.
- *
- * @src                Source dynamic buffer to reference
- * @offset     Offset to apply to the source memory content
- * @len                Length of the memory contents to reference. Passing -1 will
- *             cause the view to reference the whole dynamic buffer from the
- *             offset provided.
- *
- * Note that a buffer view never assumes the ownership of the memory it
- * references.
- */
-struct lttng_buffer_view lttng_buffer_view_from_dynamic_buffer(
-               const struct lttng_dynamic_buffer *src, size_t offset,
-               ptrdiff_t len);
-
-/**
- * Verify that `buf` contains a string starting at `str` of length
- * `len_with_null_terminator`.
- *
- * @buf                                The buffer view
- * @str                                The start of the string
- * @len_with_null_terminator   Expected length of the string, including the
- *                             NULL terminator.
- */
-bool lttng_buffer_view_contains_string(const struct lttng_buffer_view *buf,
-               const char *str,
-               size_t len_with_null_terminator);
-
-#endif /* LTTNG_BUFFER_VIEW_H */
diff --git a/src/common/buffer-view.hpp b/src/common/buffer-view.hpp
new file mode 100644 (file)
index 0000000..7e638c0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_BUFFER_VIEW_H
+#define LTTNG_BUFFER_VIEW_H
+
+#include <common/macros.hpp>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+struct lttng_dynamic_buffer;
+
+struct lttng_buffer_view {
+       const char *data;
+       size_t size;
+};
+
+/**
+ * Return a buffer view referencing a subset of the memory referenced by a raw
+ * pointer.
+ *
+ * @src                Source buffer to reference
+ * @offset     Offset to apply to the source memory buffer
+ * @len                Length of the memory contents to reference.
+ *
+ * Note that a buffer view never assumes the ownership of the memory it
+ * references.
+ */
+struct lttng_buffer_view lttng_buffer_view_init(
+               const char *src, size_t offset, ptrdiff_t len);
+
+/**
+ * Checks if a buffer view is safe to access.
+ *
+ * After calling the buffer view creation functions, callers should verify
+ * if the resquested length (if any is explicitly provided) could be mapped
+ * to a new view.
+ *
+ * @view       Buffer view to validate
+ */
+bool lttng_buffer_view_is_valid(const struct lttng_buffer_view *view);
+
+/**
+ * Return a buffer view referencing a subset of the memory referenced by another
+ * view.
+ *
+ * @src                Source view to reference
+ * @offset     Offset to apply to the source memory content
+ * @len                Length of the memory contents to reference. Passing -1 will
+ *             cause the view to reference the whole view from the offset
+ *             provided.
+ *
+ * Note that a buffer view never assumes the ownership of the memory it
+ * references.
+ */
+struct lttng_buffer_view lttng_buffer_view_from_view(
+               const struct lttng_buffer_view *src, size_t offset,
+               ptrdiff_t len);
+
+/**
+ * Return a buffer view referencing a subset of the memory referenced by a
+ * dynamic buffer.
+ *
+ * @src                Source dynamic buffer to reference
+ * @offset     Offset to apply to the source memory content
+ * @len                Length of the memory contents to reference. Passing -1 will
+ *             cause the view to reference the whole dynamic buffer from the
+ *             offset provided.
+ *
+ * Note that a buffer view never assumes the ownership of the memory it
+ * references.
+ */
+struct lttng_buffer_view lttng_buffer_view_from_dynamic_buffer(
+               const struct lttng_dynamic_buffer *src, size_t offset,
+               ptrdiff_t len);
+
+/**
+ * Verify that `buf` contains a string starting at `str` of length
+ * `len_with_null_terminator`.
+ *
+ * @buf                                The buffer view
+ * @str                                The start of the string
+ * @len_with_null_terminator   Expected length of the string, including the
+ *                             NULL terminator.
+ */
+bool lttng_buffer_view_contains_string(const struct lttng_buffer_view *buf,
+               const char *str,
+               size_t len_with_null_terminator);
+
+#endif /* LTTNG_BUFFER_VIEW_H */
diff --git a/src/common/bug.h b/src/common/bug.h
deleted file mode 100644 (file)
index f77c775..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef _LTTNG_BUG_H
-#define _LTTNG_BUG_H
-
-#include <urcu/compiler.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define LTTNG_BUG_ON(condition)                                                \
-       do {                                                            \
-               if (caa_unlikely(condition)) {                          \
-                       fprintf(stderr,                                 \
-                               "LTTng BUG in file %s, line %d.\n",     \
-                               __FILE__, __LINE__);                    \
-                       exit(EXIT_FAILURE);                             \
-               }                                                       \
-       } while (0)
-
-#define LTTNG_BUILD_BUG_ON(condition)                                  \
-       ((void) sizeof(char[-!!(condition)]))
-
-/**
- * LTTNG_BUILD_RUNTIME_BUG_ON - check condition at build (if constant) or runtime
- * @condition: the condition which should be false.
- *
- * If the condition is a constant and true, the compiler will generate a build
- * error. If the condition is not constant, a BUG will be triggered at runtime
- * if the condition is ever true. If the condition is constant and false, no
- * code is emitted.
- */
-#define LTTNG_BUILD_RUNTIME_BUG_ON(condition)                  \
-       do {                                                    \
-               if (__builtin_constant_p(condition))            \
-                       LTTNG_BUILD_BUG_ON(condition);          \
-               else                                            \
-                       LTTNG_BUG_ON(condition);                \
-       } while (0)
-
-#endif
diff --git a/src/common/bug.hpp b/src/common/bug.hpp
new file mode 100644 (file)
index 0000000..f77c775
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef _LTTNG_BUG_H
+#define _LTTNG_BUG_H
+
+#include <urcu/compiler.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LTTNG_BUG_ON(condition)                                                \
+       do {                                                            \
+               if (caa_unlikely(condition)) {                          \
+                       fprintf(stderr,                                 \
+                               "LTTng BUG in file %s, line %d.\n",     \
+                               __FILE__, __LINE__);                    \
+                       exit(EXIT_FAILURE);                             \
+               }                                                       \
+       } while (0)
+
+#define LTTNG_BUILD_BUG_ON(condition)                                  \
+       ((void) sizeof(char[-!!(condition)]))
+
+/**
+ * LTTNG_BUILD_RUNTIME_BUG_ON - check condition at build (if constant) or runtime
+ * @condition: the condition which should be false.
+ *
+ * If the condition is a constant and true, the compiler will generate a build
+ * error. If the condition is not constant, a BUG will be triggered at runtime
+ * if the condition is ever true. If the condition is constant and false, no
+ * code is emitted.
+ */
+#define LTTNG_BUILD_RUNTIME_BUG_ON(condition)                  \
+       do {                                                    \
+               if (__builtin_constant_p(condition))            \
+                       LTTNG_BUILD_BUG_ON(condition);          \
+               else                                            \
+                       LTTNG_BUG_ON(condition);                \
+       } while (0)
+
+#endif
diff --git a/src/common/bytecode/Makefile.am b/src/common/bytecode/Makefile.am
deleted file mode 100644 (file)
index ac7509b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libbytecode.la
-
-libbytecode_la_SOURCES = \
-       bytecode.cpp \
-       bytecode.h
index 064f2bfe203d92c8e1b0c14f1e1fa5282f8f69c8..30474274363baa723f74d19cd6740e9866506d49 100644 (file)
@@ -5,12 +5,12 @@
  *
  */
 
-#include "bytecode.h"
+#include "bytecode.hpp"
 
 #include <errno.h>
 #include <algorithm>
 
-#include "common/align.h"
+#include "common/align.hpp"
 
 #define INIT_ALLOC_SIZE 4
 
diff --git a/src/common/bytecode/bytecode.h b/src/common/bytecode/bytecode.h
deleted file mode 100644 (file)
index 386f582..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright 2020 EfficiOS, Inc.
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_COMMON_BYTECODE_H
-#define LTTNG_COMMON_BYTECODE_H
-
-#include <stdint.h>
-
-#include "common/macros.h"
-#include "common/sessiond-comm/sessiond-comm.h"
-
-/*
- * offsets are absolute from start of bytecode.
- */
-
-struct field_ref {
-       /* Initially, symbol offset. After link, field offset. */
-       uint16_t offset;
-} LTTNG_PACKED;
-
-struct get_symbol {
-       /* Symbol offset. */
-       uint16_t offset;
-} LTTNG_PACKED;
-
-struct get_index_u16 {
-       uint16_t index;
-} LTTNG_PACKED;
-
-struct get_index_u64 {
-       uint64_t index;
-} LTTNG_PACKED;
-
-struct literal_numeric {
-       int64_t v;
-} LTTNG_PACKED;
-
-struct literal_double {
-       double v;
-} LTTNG_PACKED;
-
-enum bytecode_op {
-       BYTECODE_OP_UNKNOWN                             = 0,
-
-       BYTECODE_OP_RETURN                              = 1,
-
-       /* binary */
-       BYTECODE_OP_MUL                                 = 2,
-       BYTECODE_OP_DIV                                 = 3,
-       BYTECODE_OP_MOD                                 = 4,
-       BYTECODE_OP_PLUS                                = 5,
-       BYTECODE_OP_MINUS                               = 6,
-       BYTECODE_OP_BIT_RSHIFT                          = 7,
-       BYTECODE_OP_BIT_LSHIFT                          = 8,
-       BYTECODE_OP_BIT_AND                             = 9,
-       BYTECODE_OP_BIT_OR                              = 10,
-       BYTECODE_OP_BIT_XOR                             = 11,
-
-       /* binary comparators */
-       BYTECODE_OP_EQ                                  = 12,
-       BYTECODE_OP_NE                                  = 13,
-       BYTECODE_OP_GT                                  = 14,
-       BYTECODE_OP_LT                                  = 15,
-       BYTECODE_OP_GE                                  = 16,
-       BYTECODE_OP_LE                                  = 17,
-
-       /* string binary comparator: apply to  */
-       BYTECODE_OP_EQ_STRING                           = 18,
-       BYTECODE_OP_NE_STRING                           = 19,
-       BYTECODE_OP_GT_STRING                           = 20,
-       BYTECODE_OP_LT_STRING                           = 21,
-       BYTECODE_OP_GE_STRING                           = 22,
-       BYTECODE_OP_LE_STRING                           = 23,
-
-       /* s64 binary comparator */
-       BYTECODE_OP_EQ_S64                              = 24,
-       BYTECODE_OP_NE_S64                              = 25,
-       BYTECODE_OP_GT_S64                              = 26,
-       BYTECODE_OP_LT_S64                              = 27,
-       BYTECODE_OP_GE_S64                              = 28,
-       BYTECODE_OP_LE_S64                              = 29,
-
-       /* double binary comparator */
-       BYTECODE_OP_EQ_DOUBLE                           = 30,
-       BYTECODE_OP_NE_DOUBLE                           = 31,
-       BYTECODE_OP_GT_DOUBLE                           = 32,
-       BYTECODE_OP_LT_DOUBLE                           = 33,
-       BYTECODE_OP_GE_DOUBLE                           = 34,
-       BYTECODE_OP_LE_DOUBLE                           = 35,
-
-       /* Mixed S64-double binary comparators */
-       BYTECODE_OP_EQ_DOUBLE_S64                       = 36,
-       BYTECODE_OP_NE_DOUBLE_S64                       = 37,
-       BYTECODE_OP_GT_DOUBLE_S64                       = 38,
-       BYTECODE_OP_LT_DOUBLE_S64                       = 39,
-       BYTECODE_OP_GE_DOUBLE_S64                       = 40,
-       BYTECODE_OP_LE_DOUBLE_S64                       = 41,
-
-       BYTECODE_OP_EQ_S64_DOUBLE                       = 42,
-       BYTECODE_OP_NE_S64_DOUBLE                       = 43,
-       BYTECODE_OP_GT_S64_DOUBLE                       = 44,
-       BYTECODE_OP_LT_S64_DOUBLE                       = 45,
-       BYTECODE_OP_GE_S64_DOUBLE                       = 46,
-       BYTECODE_OP_LE_S64_DOUBLE                       = 47,
-
-       /* unary */
-       BYTECODE_OP_UNARY_PLUS                          = 48,
-       BYTECODE_OP_UNARY_MINUS                         = 49,
-       BYTECODE_OP_UNARY_NOT                           = 50,
-       BYTECODE_OP_UNARY_PLUS_S64                      = 51,
-       BYTECODE_OP_UNARY_MINUS_S64                     = 52,
-       BYTECODE_OP_UNARY_NOT_S64                       = 53,
-       BYTECODE_OP_UNARY_PLUS_DOUBLE                   = 54,
-       BYTECODE_OP_UNARY_MINUS_DOUBLE                  = 55,
-       BYTECODE_OP_UNARY_NOT_DOUBLE                    = 56,
-
-       /* logical */
-       BYTECODE_OP_AND                                 = 57,
-       BYTECODE_OP_OR                                  = 58,
-
-       /* load field ref */
-       BYTECODE_OP_LOAD_FIELD_REF                      = 59,
-       BYTECODE_OP_LOAD_FIELD_REF_STRING               = 60,
-       BYTECODE_OP_LOAD_FIELD_REF_SEQUENCE             = 61,
-       BYTECODE_OP_LOAD_FIELD_REF_S64                  = 62,
-       BYTECODE_OP_LOAD_FIELD_REF_DOUBLE               = 63,
-
-       /* load immediate from operand */
-       BYTECODE_OP_LOAD_STRING                         = 64,
-       BYTECODE_OP_LOAD_S64                            = 65,
-       BYTECODE_OP_LOAD_DOUBLE                         = 66,
-
-       /* cast */
-       BYTECODE_OP_CAST_TO_S64                         = 67,
-       BYTECODE_OP_CAST_DOUBLE_TO_S64                  = 68,
-       BYTECODE_OP_CAST_NOP                            = 69,
-
-       /* get context ref */
-       BYTECODE_OP_GET_CONTEXT_REF                     = 70,
-       BYTECODE_OP_GET_CONTEXT_REF_STRING              = 71,
-       BYTECODE_OP_GET_CONTEXT_REF_S64                 = 72,
-       BYTECODE_OP_GET_CONTEXT_REF_DOUBLE              = 73,
-
-       /* load userspace field ref */
-       BYTECODE_OP_LOAD_FIELD_REF_USER_STRING          = 74,
-       BYTECODE_OP_LOAD_FIELD_REF_USER_SEQUENCE        = 75,
-
-       /*
-        * load immediate star globbing pattern (literal string)
-        * from immediate
-        */
-       BYTECODE_OP_LOAD_STAR_GLOB_STRING               = 76,
-
-       /* globbing pattern binary operator: apply to */
-       BYTECODE_OP_EQ_STAR_GLOB_STRING                 = 77,
-       BYTECODE_OP_NE_STAR_GLOB_STRING                 = 78,
-
-       /*
-        * Instructions for recursive traversal through composed types.
-        */
-       BYTECODE_OP_GET_CONTEXT_ROOT                    = 79,
-       BYTECODE_OP_GET_APP_CONTEXT_ROOT                = 80,
-       BYTECODE_OP_GET_PAYLOAD_ROOT                    = 81,
-
-       BYTECODE_OP_GET_SYMBOL                          = 82,
-       BYTECODE_OP_GET_SYMBOL_FIELD                    = 83,
-       BYTECODE_OP_GET_INDEX_U16                       = 84,
-       BYTECODE_OP_GET_INDEX_U64                       = 85,
-
-       BYTECODE_OP_LOAD_FIELD                          = 86,
-       BYTECODE_OP_LOAD_FIELD_S8                       = 87,
-       BYTECODE_OP_LOAD_FIELD_S16                      = 88,
-       BYTECODE_OP_LOAD_FIELD_S32                      = 89,
-       BYTECODE_OP_LOAD_FIELD_S64                      = 90,
-       BYTECODE_OP_LOAD_FIELD_U8                       = 91,
-       BYTECODE_OP_LOAD_FIELD_U16                      = 92,
-       BYTECODE_OP_LOAD_FIELD_U32                      = 93,
-       BYTECODE_OP_LOAD_FIELD_U64                      = 94,
-       BYTECODE_OP_LOAD_FIELD_STRING                   = 95,
-       BYTECODE_OP_LOAD_FIELD_SEQUENCE                 = 96,
-       BYTECODE_OP_LOAD_FIELD_DOUBLE                   = 97,
-
-       BYTECODE_OP_UNARY_BIT_NOT                       = 98,
-
-       BYTECODE_OP_RETURN_S64                          = 99,
-
-       NR_BYTECODE_OPS,
-};
-
-typedef uint8_t bytecode_opcode_t;
-
-struct load_op {
-       bytecode_opcode_t op;
-
-       /*
-        * data to load. Size known by enum bytecode_opcode_t and null-term
-        * char.
-        */
-       char data[0];
-} LTTNG_PACKED;
-
-struct binary_op {
-       bytecode_opcode_t op;
-} LTTNG_PACKED;
-
-struct unary_op {
-       bytecode_opcode_t op;
-} LTTNG_PACKED;
-
-/* skip_offset is absolute from start of bytecode */
-struct logical_op {
-       bytecode_opcode_t op;
-       uint16_t skip_offset;   /* bytecode insn, if skip second test */
-} LTTNG_PACKED;
-
-struct cast_op {
-       bytecode_opcode_t op;
-} LTTNG_PACKED;
-
-struct return_op {
-       bytecode_opcode_t op;
-} LTTNG_PACKED;
-
-struct lttng_bytecode_alloc {
-       uint32_t alloc_len;
-       struct lttng_bytecode b;
-};
-
-int bytecode_init(struct lttng_bytecode_alloc **fb);
-int bytecode_push(struct lttng_bytecode_alloc **fb,
-               const void *data, uint32_t align, uint32_t len);
-int bytecode_push_logical(struct lttng_bytecode_alloc **fb,
-               struct logical_op *data, uint32_t align, uint32_t len,
-               uint16_t *skip_offset);
-struct lttng_bytecode *lttng_bytecode_copy(
-               const struct lttng_bytecode *orig_f);
-
-int bytecode_push_get_payload_root(
-               struct lttng_bytecode_alloc **bytecode);
-int bytecode_push_get_context_root(
-               struct lttng_bytecode_alloc **bytecode);
-int bytecode_push_get_app_context_root(
-               struct lttng_bytecode_alloc **bytecode);
-int bytecode_push_get_index_u64(
-               struct lttng_bytecode_alloc **bytecode, uint64_t index);
-int bytecode_push_get_symbol(
-               struct lttng_bytecode_alloc **bytecode,
-               struct lttng_bytecode_alloc **bytecode_reloc,
-               const char *symbol);
-
-static inline
-unsigned int bytecode_get_len(struct lttng_bytecode *bytecode)
-{
-       return bytecode->len;
-}
-
-#endif /* LTTNG_COMMON_BYTECODE_H */
diff --git a/src/common/bytecode/bytecode.hpp b/src/common/bytecode/bytecode.hpp
new file mode 100644 (file)
index 0000000..4ed51dc
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2020 EfficiOS, Inc.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_COMMON_BYTECODE_H
+#define LTTNG_COMMON_BYTECODE_H
+
+#include <stdint.h>
+
+#include "common/macros.hpp"
+#include "common/sessiond-comm/sessiond-comm.hpp"
+
+/*
+ * offsets are absolute from start of bytecode.
+ */
+
+struct field_ref {
+       /* Initially, symbol offset. After link, field offset. */
+       uint16_t offset;
+} LTTNG_PACKED;
+
+struct get_symbol {
+       /* Symbol offset. */
+       uint16_t offset;
+} LTTNG_PACKED;
+
+struct get_index_u16 {
+       uint16_t index;
+} LTTNG_PACKED;
+
+struct get_index_u64 {
+       uint64_t index;
+} LTTNG_PACKED;
+
+struct literal_numeric {
+       int64_t v;
+} LTTNG_PACKED;
+
+struct literal_double {
+       double v;
+} LTTNG_PACKED;
+
+enum bytecode_op {
+       BYTECODE_OP_UNKNOWN                             = 0,
+
+       BYTECODE_OP_RETURN                              = 1,
+
+       /* binary */
+       BYTECODE_OP_MUL                                 = 2,
+       BYTECODE_OP_DIV                                 = 3,
+       BYTECODE_OP_MOD                                 = 4,
+       BYTECODE_OP_PLUS                                = 5,
+       BYTECODE_OP_MINUS                               = 6,
+       BYTECODE_OP_BIT_RSHIFT                          = 7,
+       BYTECODE_OP_BIT_LSHIFT                          = 8,
+       BYTECODE_OP_BIT_AND                             = 9,
+       BYTECODE_OP_BIT_OR                              = 10,
+       BYTECODE_OP_BIT_XOR                             = 11,
+
+       /* binary comparators */
+       BYTECODE_OP_EQ                                  = 12,
+       BYTECODE_OP_NE                                  = 13,
+       BYTECODE_OP_GT                                  = 14,
+       BYTECODE_OP_LT                                  = 15,
+       BYTECODE_OP_GE                                  = 16,
+       BYTECODE_OP_LE                                  = 17,
+
+       /* string binary comparator: apply to  */
+       BYTECODE_OP_EQ_STRING                           = 18,
+       BYTECODE_OP_NE_STRING                           = 19,
+       BYTECODE_OP_GT_STRING                           = 20,
+       BYTECODE_OP_LT_STRING                           = 21,
+       BYTECODE_OP_GE_STRING                           = 22,
+       BYTECODE_OP_LE_STRING                           = 23,
+
+       /* s64 binary comparator */
+       BYTECODE_OP_EQ_S64                              = 24,
+       BYTECODE_OP_NE_S64                              = 25,
+       BYTECODE_OP_GT_S64                              = 26,
+       BYTECODE_OP_LT_S64                              = 27,
+       BYTECODE_OP_GE_S64                              = 28,
+       BYTECODE_OP_LE_S64                              = 29,
+
+       /* double binary comparator */
+       BYTECODE_OP_EQ_DOUBLE                           = 30,
+       BYTECODE_OP_NE_DOUBLE                           = 31,
+       BYTECODE_OP_GT_DOUBLE                           = 32,
+       BYTECODE_OP_LT_DOUBLE                           = 33,
+       BYTECODE_OP_GE_DOUBLE                           = 34,
+       BYTECODE_OP_LE_DOUBLE                           = 35,
+
+       /* Mixed S64-double binary comparators */
+       BYTECODE_OP_EQ_DOUBLE_S64                       = 36,
+       BYTECODE_OP_NE_DOUBLE_S64                       = 37,
+       BYTECODE_OP_GT_DOUBLE_S64                       = 38,
+       BYTECODE_OP_LT_DOUBLE_S64                       = 39,
+       BYTECODE_OP_GE_DOUBLE_S64                       = 40,
+       BYTECODE_OP_LE_DOUBLE_S64                       = 41,
+
+       BYTECODE_OP_EQ_S64_DOUBLE                       = 42,
+       BYTECODE_OP_NE_S64_DOUBLE                       = 43,
+       BYTECODE_OP_GT_S64_DOUBLE                       = 44,
+       BYTECODE_OP_LT_S64_DOUBLE                       = 45,
+       BYTECODE_OP_GE_S64_DOUBLE                       = 46,
+       BYTECODE_OP_LE_S64_DOUBLE                       = 47,
+
+       /* unary */
+       BYTECODE_OP_UNARY_PLUS                          = 48,
+       BYTECODE_OP_UNARY_MINUS                         = 49,
+       BYTECODE_OP_UNARY_NOT                           = 50,
+       BYTECODE_OP_UNARY_PLUS_S64                      = 51,
+       BYTECODE_OP_UNARY_MINUS_S64                     = 52,
+       BYTECODE_OP_UNARY_NOT_S64                       = 53,
+       BYTECODE_OP_UNARY_PLUS_DOUBLE                   = 54,
+       BYTECODE_OP_UNARY_MINUS_DOUBLE                  = 55,
+       BYTECODE_OP_UNARY_NOT_DOUBLE                    = 56,
+
+       /* logical */
+       BYTECODE_OP_AND                                 = 57,
+       BYTECODE_OP_OR                                  = 58,
+
+       /* load field ref */
+       BYTECODE_OP_LOAD_FIELD_REF                      = 59,
+       BYTECODE_OP_LOAD_FIELD_REF_STRING               = 60,
+       BYTECODE_OP_LOAD_FIELD_REF_SEQUENCE             = 61,
+       BYTECODE_OP_LOAD_FIELD_REF_S64                  = 62,
+       BYTECODE_OP_LOAD_FIELD_REF_DOUBLE               = 63,
+
+       /* load immediate from operand */
+       BYTECODE_OP_LOAD_STRING                         = 64,
+       BYTECODE_OP_LOAD_S64                            = 65,
+       BYTECODE_OP_LOAD_DOUBLE                         = 66,
+
+       /* cast */
+       BYTECODE_OP_CAST_TO_S64                         = 67,
+       BYTECODE_OP_CAST_DOUBLE_TO_S64                  = 68,
+       BYTECODE_OP_CAST_NOP                            = 69,
+
+       /* get context ref */
+       BYTECODE_OP_GET_CONTEXT_REF                     = 70,
+       BYTECODE_OP_GET_CONTEXT_REF_STRING              = 71,
+       BYTECODE_OP_GET_CONTEXT_REF_S64                 = 72,
+       BYTECODE_OP_GET_CONTEXT_REF_DOUBLE              = 73,
+
+       /* load userspace field ref */
+       BYTECODE_OP_LOAD_FIELD_REF_USER_STRING          = 74,
+       BYTECODE_OP_LOAD_FIELD_REF_USER_SEQUENCE        = 75,
+
+       /*
+        * load immediate star globbing pattern (literal string)
+        * from immediate
+        */
+       BYTECODE_OP_LOAD_STAR_GLOB_STRING               = 76,
+
+       /* globbing pattern binary operator: apply to */
+       BYTECODE_OP_EQ_STAR_GLOB_STRING                 = 77,
+       BYTECODE_OP_NE_STAR_GLOB_STRING                 = 78,
+
+       /*
+        * Instructions for recursive traversal through composed types.
+        */
+       BYTECODE_OP_GET_CONTEXT_ROOT                    = 79,
+       BYTECODE_OP_GET_APP_CONTEXT_ROOT                = 80,
+       BYTECODE_OP_GET_PAYLOAD_ROOT                    = 81,
+
+       BYTECODE_OP_GET_SYMBOL                          = 82,
+       BYTECODE_OP_GET_SYMBOL_FIELD                    = 83,
+       BYTECODE_OP_GET_INDEX_U16                       = 84,
+       BYTECODE_OP_GET_INDEX_U64                       = 85,
+
+       BYTECODE_OP_LOAD_FIELD                          = 86,
+       BYTECODE_OP_LOAD_FIELD_S8                       = 87,
+       BYTECODE_OP_LOAD_FIELD_S16                      = 88,
+       BYTECODE_OP_LOAD_FIELD_S32                      = 89,
+       BYTECODE_OP_LOAD_FIELD_S64                      = 90,
+       BYTECODE_OP_LOAD_FIELD_U8                       = 91,
+       BYTECODE_OP_LOAD_FIELD_U16                      = 92,
+       BYTECODE_OP_LOAD_FIELD_U32                      = 93,
+       BYTECODE_OP_LOAD_FIELD_U64                      = 94,
+       BYTECODE_OP_LOAD_FIELD_STRING                   = 95,
+       BYTECODE_OP_LOAD_FIELD_SEQUENCE                 = 96,
+       BYTECODE_OP_LOAD_FIELD_DOUBLE                   = 97,
+
+       BYTECODE_OP_UNARY_BIT_NOT                       = 98,
+
+       BYTECODE_OP_RETURN_S64                          = 99,
+
+       NR_BYTECODE_OPS,
+};
+
+typedef uint8_t bytecode_opcode_t;
+
+struct load_op {
+       bytecode_opcode_t op;
+
+       /*
+        * data to load. Size known by enum bytecode_opcode_t and null-term
+        * char.
+        */
+       char data[0];
+} LTTNG_PACKED;
+
+struct binary_op {
+       bytecode_opcode_t op;
+} LTTNG_PACKED;
+
+struct unary_op {
+       bytecode_opcode_t op;
+} LTTNG_PACKED;
+
+/* skip_offset is absolute from start of bytecode */
+struct logical_op {
+       bytecode_opcode_t op;
+       uint16_t skip_offset;   /* bytecode insn, if skip second test */
+} LTTNG_PACKED;
+
+struct cast_op {
+       bytecode_opcode_t op;
+} LTTNG_PACKED;
+
+struct return_op {
+       bytecode_opcode_t op;
+} LTTNG_PACKED;
+
+struct lttng_bytecode_alloc {
+       uint32_t alloc_len;
+       struct lttng_bytecode b;
+};
+
+int bytecode_init(struct lttng_bytecode_alloc **fb);
+int bytecode_push(struct lttng_bytecode_alloc **fb,
+               const void *data, uint32_t align, uint32_t len);
+int bytecode_push_logical(struct lttng_bytecode_alloc **fb,
+               struct logical_op *data, uint32_t align, uint32_t len,
+               uint16_t *skip_offset);
+struct lttng_bytecode *lttng_bytecode_copy(
+               const struct lttng_bytecode *orig_f);
+
+int bytecode_push_get_payload_root(
+               struct lttng_bytecode_alloc **bytecode);
+int bytecode_push_get_context_root(
+               struct lttng_bytecode_alloc **bytecode);
+int bytecode_push_get_app_context_root(
+               struct lttng_bytecode_alloc **bytecode);
+int bytecode_push_get_index_u64(
+               struct lttng_bytecode_alloc **bytecode, uint64_t index);
+int bytecode_push_get_symbol(
+               struct lttng_bytecode_alloc **bytecode,
+               struct lttng_bytecode_alloc **bytecode_reloc,
+               const char *symbol);
+
+static inline
+unsigned int bytecode_get_len(struct lttng_bytecode *bytecode)
+{
+       return bytecode->len;
+}
+
+#endif /* LTTNG_COMMON_BYTECODE_H */
diff --git a/src/common/common.h b/src/common/common.h
deleted file mode 100644 (file)
index f2c2b18..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMMON_H
-#define _COMMON_H
-
-#include "error.h"
-#include "macros.h"
-#include "runas.h"
-#include "readwrite.h"
-#include "time.h"
-
-#endif /* _COMMON_H */
diff --git a/src/common/common.hpp b/src/common/common.hpp
new file mode 100644 (file)
index 0000000..97273d0
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#include "error.hpp"
+#include "macros.hpp"
+#include "runas.hpp"
+#include "readwrite.hpp"
+#include "time.hpp"
+
+#endif /* _COMMON_H */
diff --git a/src/common/compat/Makefile.am b/src/common/compat/Makefile.am
deleted file mode 100644 (file)
index 0499b35..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libcompat.la
-
-libcompat_la_SOURCES = \
-        compat-fcntl.cpp \
-        directory-handle.cpp \
-        directory-handle.h \
-        dirent.h \
-        endian.h \
-        errno.h \
-        fcntl.h \
-        getenv.h \
-        mman.h \
-        netdb.h \
-        path.h \
-        paths.h \
-        poll.cpp \
-        poll.h \
-        pthread.h \
-        socket.h \
-        string.h \
-        tid.h \
-        time.h
index bc014d6404df4f1a78f71a0783d4b4ab6b47656a..a0e1334ae6e0b292a315d0cfffdad4552a856f4e 100644 (file)
@@ -6,8 +6,8 @@
  */
 
 #define _LGPL_SOURCE
-#include <common/compat/fcntl.h>
-#include <common/macros.h>
+#include <common/compat/fcntl.hpp>
+#include <common/macros.hpp>
 #include <unistd.h>
 
 #ifdef __linux__
index edd82ebb64765bb1f887cbfb7b075ce9a0c0e6c5..6a1b993f8b039cb145ae4e6e4f3f1b4a3560184f 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include <common/compat/directory-handle.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/runas.h>
-#include <common/credentials.h>
+#include <common/compat/directory-handle.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/runas.hpp>
+#include <common/credentials.hpp>
 #include <lttng/constant.h>
-#include <common/dynamic-array.h>
+#include <common/dynamic-array.hpp>
 
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/src/common/compat/directory-handle.h b/src/common/compat/directory-handle.h
deleted file mode 100644 (file)
index 6aa5c3d..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_DIRECTORY_HANDLE_H
-#define _COMPAT_DIRECTORY_HANDLE_H
-
-#include <common/credentials.h>
-#include <common/macros.h>
-#include <sys/stat.h>
-#include <urcu/ref.h>
-
-enum lttng_directory_handle_rmdir_recursive_flags {
-       LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG = (1U << 0),
-       LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG = (1U << 1),
-};
-
-/*
- * Some platforms, such as Solaris 10, do not support directory file descriptors
- * and their associated functions (*at(...)), which are defined in POSIX.2008.
- *
- * This wrapper provides a handle that is either a copy of a directory's path
- * or a directory file descriptors, depending on the platform's capabilities.
- */
-#ifdef HAVE_DIRFD
-
-struct lttng_directory_handle;
-
-typedef void (*lttng_directory_handle_destroy_cb)(
-               struct lttng_directory_handle *handle, void *data);
-
-struct lttng_directory_handle {
-       struct urcu_ref ref;
-       ino_t directory_inode;
-       int dirfd;
-       lttng_directory_handle_destroy_cb destroy_cb;
-       void *destroy_cb_data;
-};
-
-static inline
-int lttng_directory_handle_get_dirfd(
-               const struct lttng_directory_handle *handle)
-{
-       return handle->dirfd;
-}
-
-#else
-struct lttng_directory_handle {
-       struct urcu_ref ref;
-       char *base_path;
-};
-#endif
-
-/*
- * Create a directory handle to the provided path. Passing a NULL path
- * returns a handle to the current working directory.
- *
- * The reference to the directory handle must be released using
- * lttng_directory_handle_put().
- */
-struct lttng_directory_handle *lttng_directory_handle_create(
-               const char *path);
-
-/*
- * Create a new directory handle to a path relative to an existing handle.
- *
- * The provided path must already exist. Note that the creation of a
- * subdirectory and the creation of a handle are kept as separate operations
- * to highlight the fact that there is an inherent race between the creation of
- * a directory and the creation of a handle to it.
- *
- * Passing a NULL path effectively copies the original handle.
- *
- * The reference to the directory handle must be released using
- * lttng_directory_handle_put().
- */
-struct lttng_directory_handle *lttng_directory_handle_create_from_handle(
-               const char *path,
-               const struct lttng_directory_handle *ref_handle);
-
-/*
- * Create a new directory handle from an existing directory fd.
- *
- * The new directory handle assumes the ownership of the directory fd.
- * Note that this method should only be used in very specific cases, such as
- * re-creating a directory handle from a dirfd passed over a unix socket.
- *
- * The reference to the directory handle must be released using
- * lttng_directory_handle_put().
- */
-struct lttng_directory_handle *lttng_directory_handle_create_from_dirfd(
-               int dirfd);
-
-/*
- * Copy a directory handle.
- *
- * The reference to the directory handle must be released using
- * lttng_directory_handle_put().
- */
-struct lttng_directory_handle *lttng_directory_handle_copy(
-               const struct lttng_directory_handle *handle);
-
-/*
- * Acquire a reference to a directory handle.
- */
-bool lttng_directory_handle_get(struct lttng_directory_handle *handle);
-
-/*
- * Release a reference to a directory handle.
- */
-void lttng_directory_handle_put(struct lttng_directory_handle *handle);
-
-/*
- * Create a subdirectory relative to a directory handle.
- */
-int lttng_directory_handle_create_subdirectory(
-               const struct lttng_directory_handle *handle,
-               const char *subdirectory,
-               mode_t mode);
-
-/*
- * Create a subdirectory relative to a directory handle
- * as a given user.
- */
-int lttng_directory_handle_create_subdirectory_as_user(
-               const struct lttng_directory_handle *handle,
-               const char *subdirectory,
-               mode_t mode, const struct lttng_credentials *creds);
-
-/*
- * Recursively create a directory relative to a directory handle.
- */
-int lttng_directory_handle_create_subdirectory_recursive(
-               const struct lttng_directory_handle *handle,
-               const char *subdirectory_path,
-               mode_t mode);
-
-/*
- * Recursively create a directory relative to a directory handle
- * as a given user.
- */
-int lttng_directory_handle_create_subdirectory_recursive_as_user(
-               const struct lttng_directory_handle *handle,
-               const char *subdirectory_path,
-               mode_t mode, const struct lttng_credentials *creds);
-
-/*
- * Open a file descriptor to a path relative to a directory handle.
- */
-int lttng_directory_handle_open_file(
-               const struct lttng_directory_handle *handle,
-               const char *filename,
-               int flags, mode_t mode);
-
-/*
- * Open a file descriptor to a path relative to a directory handle
- * as a given user.
- */
-int lttng_directory_handle_open_file_as_user(
-               const struct lttng_directory_handle *handle,
-               const char *filename,
-               int flags, mode_t mode,
-               const struct lttng_credentials *creds);
-
-/*
- * Unlink a file to a path relative to a directory handle.
- */
-int lttng_directory_handle_unlink_file(
-               const struct lttng_directory_handle *handle,
-               const char *filename);
-
-/*
- * Unlink a file to a path relative to a directory handle as a given user.
- */
-int lttng_directory_handle_unlink_file_as_user(
-               const struct lttng_directory_handle *handle,
-               const char *filename,
-               const struct lttng_credentials *creds);
-
-/*
- * Rename a file from a path relative to a directory handle to a new
- * name relative to another directory handle.
- */
-int lttng_directory_handle_rename(
-               const struct lttng_directory_handle *old_handle,
-               const char *old_name,
-               const struct lttng_directory_handle *new_handle,
-               const char *new_name);
-
-/*
- * Rename a file from a path relative to a directory handle to a new
- * name relative to another directory handle as a given user.
- */
-int lttng_directory_handle_rename_as_user(
-               const struct lttng_directory_handle *old_handle,
-               const char *old_name,
-               const struct lttng_directory_handle *new_handle,
-               const char *new_name,
-               const struct lttng_credentials *creds);
-
-/*
- * Remove a subdirectory relative to a directory handle.
- */
-int lttng_directory_handle_remove_subdirectory(
-               const struct lttng_directory_handle *handle,
-               const char *name);
-
-/*
- * Remove a subdirectory relative to a directory handle as a given user.
- */
-int lttng_directory_handle_remove_subdirectory_as_user(
-               const struct lttng_directory_handle *handle,
-               const char *name,
-               const struct lttng_credentials *creds);
-
-/*
- * Remove a subdirectory and remove its contents if it only
- * consists in empty directories.
- * @flags: enum lttng_directory_handle_rmdir_recursive_flags
- */
-int lttng_directory_handle_remove_subdirectory_recursive(
-               const struct lttng_directory_handle *handle,
-               const char *name, int flags);
-
-/*
- * Remove a subdirectory and remove its contents if it only
- * consists in empty directories as a given user.
- * @flags: enum lttng_directory_handle_rmdir_recursive_flags
- */
-int lttng_directory_handle_remove_subdirectory_recursive_as_user(
-               const struct lttng_directory_handle *handle,
-               const char *name,
-               const struct lttng_credentials *creds,
-               int flags);
-
-/*
- * stat() a file relative to a directory handle.
- */
-int lttng_directory_handle_stat(
-               const struct lttng_directory_handle *handle,
-               const char *name,
-               struct stat *stat_buf);
-
-/*
- * Returns true if this directory handle is backed by a file
- * descriptor, false otherwise.
- */
-bool lttng_directory_handle_uses_fd(
-               const struct lttng_directory_handle *handle);
-
-/*
- * Compare two directory handles.
- *
- * Returns true if the two directory handles are equal, false otherwise.
- */
-bool lttng_directory_handle_equals(const struct lttng_directory_handle *lhs,
-               const struct lttng_directory_handle *rhs);
-
-
-#endif /* _COMPAT_PATH_HANDLE_H */
diff --git a/src/common/compat/directory-handle.hpp b/src/common/compat/directory-handle.hpp
new file mode 100644 (file)
index 0000000..c2c834e
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_DIRECTORY_HANDLE_H
+#define _COMPAT_DIRECTORY_HANDLE_H
+
+#include <common/credentials.hpp>
+#include <common/macros.hpp>
+#include <sys/stat.h>
+#include <urcu/ref.h>
+
+enum lttng_directory_handle_rmdir_recursive_flags {
+       LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG = (1U << 0),
+       LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG = (1U << 1),
+};
+
+/*
+ * Some platforms, such as Solaris 10, do not support directory file descriptors
+ * and their associated functions (*at(...)), which are defined in POSIX.2008.
+ *
+ * This wrapper provides a handle that is either a copy of a directory's path
+ * or a directory file descriptors, depending on the platform's capabilities.
+ */
+#ifdef HAVE_DIRFD
+
+struct lttng_directory_handle;
+
+typedef void (*lttng_directory_handle_destroy_cb)(
+               struct lttng_directory_handle *handle, void *data);
+
+struct lttng_directory_handle {
+       struct urcu_ref ref;
+       ino_t directory_inode;
+       int dirfd;
+       lttng_directory_handle_destroy_cb destroy_cb;
+       void *destroy_cb_data;
+};
+
+static inline
+int lttng_directory_handle_get_dirfd(
+               const struct lttng_directory_handle *handle)
+{
+       return handle->dirfd;
+}
+
+#else
+struct lttng_directory_handle {
+       struct urcu_ref ref;
+       char *base_path;
+};
+#endif
+
+/*
+ * Create a directory handle to the provided path. Passing a NULL path
+ * returns a handle to the current working directory.
+ *
+ * The reference to the directory handle must be released using
+ * lttng_directory_handle_put().
+ */
+struct lttng_directory_handle *lttng_directory_handle_create(
+               const char *path);
+
+/*
+ * Create a new directory handle to a path relative to an existing handle.
+ *
+ * The provided path must already exist. Note that the creation of a
+ * subdirectory and the creation of a handle are kept as separate operations
+ * to highlight the fact that there is an inherent race between the creation of
+ * a directory and the creation of a handle to it.
+ *
+ * Passing a NULL path effectively copies the original handle.
+ *
+ * The reference to the directory handle must be released using
+ * lttng_directory_handle_put().
+ */
+struct lttng_directory_handle *lttng_directory_handle_create_from_handle(
+               const char *path,
+               const struct lttng_directory_handle *ref_handle);
+
+/*
+ * Create a new directory handle from an existing directory fd.
+ *
+ * The new directory handle assumes the ownership of the directory fd.
+ * Note that this method should only be used in very specific cases, such as
+ * re-creating a directory handle from a dirfd passed over a unix socket.
+ *
+ * The reference to the directory handle must be released using
+ * lttng_directory_handle_put().
+ */
+struct lttng_directory_handle *lttng_directory_handle_create_from_dirfd(
+               int dirfd);
+
+/*
+ * Copy a directory handle.
+ *
+ * The reference to the directory handle must be released using
+ * lttng_directory_handle_put().
+ */
+struct lttng_directory_handle *lttng_directory_handle_copy(
+               const struct lttng_directory_handle *handle);
+
+/*
+ * Acquire a reference to a directory handle.
+ */
+bool lttng_directory_handle_get(struct lttng_directory_handle *handle);
+
+/*
+ * Release a reference to a directory handle.
+ */
+void lttng_directory_handle_put(struct lttng_directory_handle *handle);
+
+/*
+ * Create a subdirectory relative to a directory handle.
+ */
+int lttng_directory_handle_create_subdirectory(
+               const struct lttng_directory_handle *handle,
+               const char *subdirectory,
+               mode_t mode);
+
+/*
+ * Create a subdirectory relative to a directory handle
+ * as a given user.
+ */
+int lttng_directory_handle_create_subdirectory_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *subdirectory,
+               mode_t mode, const struct lttng_credentials *creds);
+
+/*
+ * Recursively create a directory relative to a directory handle.
+ */
+int lttng_directory_handle_create_subdirectory_recursive(
+               const struct lttng_directory_handle *handle,
+               const char *subdirectory_path,
+               mode_t mode);
+
+/*
+ * Recursively create a directory relative to a directory handle
+ * as a given user.
+ */
+int lttng_directory_handle_create_subdirectory_recursive_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *subdirectory_path,
+               mode_t mode, const struct lttng_credentials *creds);
+
+/*
+ * Open a file descriptor to a path relative to a directory handle.
+ */
+int lttng_directory_handle_open_file(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode);
+
+/*
+ * Open a file descriptor to a path relative to a directory handle
+ * as a given user.
+ */
+int lttng_directory_handle_open_file_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode,
+               const struct lttng_credentials *creds);
+
+/*
+ * Unlink a file to a path relative to a directory handle.
+ */
+int lttng_directory_handle_unlink_file(
+               const struct lttng_directory_handle *handle,
+               const char *filename);
+
+/*
+ * Unlink a file to a path relative to a directory handle as a given user.
+ */
+int lttng_directory_handle_unlink_file_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               const struct lttng_credentials *creds);
+
+/*
+ * Rename a file from a path relative to a directory handle to a new
+ * name relative to another directory handle.
+ */
+int lttng_directory_handle_rename(
+               const struct lttng_directory_handle *old_handle,
+               const char *old_name,
+               const struct lttng_directory_handle *new_handle,
+               const char *new_name);
+
+/*
+ * Rename a file from a path relative to a directory handle to a new
+ * name relative to another directory handle as a given user.
+ */
+int lttng_directory_handle_rename_as_user(
+               const struct lttng_directory_handle *old_handle,
+               const char *old_name,
+               const struct lttng_directory_handle *new_handle,
+               const char *new_name,
+               const struct lttng_credentials *creds);
+
+/*
+ * Remove a subdirectory relative to a directory handle.
+ */
+int lttng_directory_handle_remove_subdirectory(
+               const struct lttng_directory_handle *handle,
+               const char *name);
+
+/*
+ * Remove a subdirectory relative to a directory handle as a given user.
+ */
+int lttng_directory_handle_remove_subdirectory_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *name,
+               const struct lttng_credentials *creds);
+
+/*
+ * Remove a subdirectory and remove its contents if it only
+ * consists in empty directories.
+ * @flags: enum lttng_directory_handle_rmdir_recursive_flags
+ */
+int lttng_directory_handle_remove_subdirectory_recursive(
+               const struct lttng_directory_handle *handle,
+               const char *name, int flags);
+
+/*
+ * Remove a subdirectory and remove its contents if it only
+ * consists in empty directories as a given user.
+ * @flags: enum lttng_directory_handle_rmdir_recursive_flags
+ */
+int lttng_directory_handle_remove_subdirectory_recursive_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *name,
+               const struct lttng_credentials *creds,
+               int flags);
+
+/*
+ * stat() a file relative to a directory handle.
+ */
+int lttng_directory_handle_stat(
+               const struct lttng_directory_handle *handle,
+               const char *name,
+               struct stat *stat_buf);
+
+/*
+ * Returns true if this directory handle is backed by a file
+ * descriptor, false otherwise.
+ */
+bool lttng_directory_handle_uses_fd(
+               const struct lttng_directory_handle *handle);
+
+/*
+ * Compare two directory handles.
+ *
+ * Returns true if the two directory handles are equal, false otherwise.
+ */
+bool lttng_directory_handle_equals(const struct lttng_directory_handle *lhs,
+               const struct lttng_directory_handle *rhs);
+
+
+#endif /* _COMPAT_PATH_HANDLE_H */
diff --git a/src/common/compat/dirent.h b/src/common/compat/dirent.h
deleted file mode 100644 (file)
index b760ed2..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef _COMPAT_DIRENT_H
-#define _COMPAT_DIRENT_H
-
-#include <dirent.h>
-
-#ifdef HAVE_DIRFD
-static inline
-int lttng_dirfd(DIR *dir) {
-       return dirfd(dir);
-}
-#else
-# ifndef __XOPEN_OR_POSIX
-static inline
-int lttng_dirfd(DIR *dir) {
-       return dir->dd_fd;
-}
-# else
-static inline
-int lttng_dirfd(DIR *dir) {
-       return dir->d_fd;
-}
-# endif
-#endif
-
-#endif /* _COMPAT_DIRENT_H */
diff --git a/src/common/compat/dirent.hpp b/src/common/compat/dirent.hpp
new file mode 100644 (file)
index 0000000..b760ed2
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef _COMPAT_DIRENT_H
+#define _COMPAT_DIRENT_H
+
+#include <dirent.h>
+
+#ifdef HAVE_DIRFD
+static inline
+int lttng_dirfd(DIR *dir) {
+       return dirfd(dir);
+}
+#else
+# ifndef __XOPEN_OR_POSIX
+static inline
+int lttng_dirfd(DIR *dir) {
+       return dir->dd_fd;
+}
+# else
+static inline
+int lttng_dirfd(DIR *dir) {
+       return dir->d_fd;
+}
+# endif
+#endif
+
+#endif /* _COMPAT_DIRENT_H */
diff --git a/src/common/compat/endian.h b/src/common/compat/endian.h
deleted file mode 100644 (file)
index d808b40..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_ENDIAN_H
-#define _COMPAT_ENDIAN_H
-
-#if defined(__linux__) || defined(__CYGWIN__)
-#include <endian.h>
-#include <byteswap.h>
-
-/*
- * htobe/betoh are not defined for glibc <2.9, so add them
- * explicitly if they are missing.
- */
-#ifdef __USE_BSD
-/* Conversion interfaces. */
-# include <byteswap.h>
-
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-#  ifndef htobe16
-#   define htobe16(x) __bswap_16(x)
-#  endif
-#  ifndef htole16
-#   define htole16(x) (x)
-#  endif
-#  ifndef be16toh
-#   define be16toh(x) __bswap_16(x)
-#  endif
-#  ifndef le16toh
-#   define le16toh(x) (x)
-#  endif
-
-#  ifndef htobe32
-#   define htobe32(x) __bswap_32(x)
-#  endif
-#  ifndef htole32
-#   define htole32(x) (x)
-#  endif
-#  ifndef be32toh
-#   define be32toh(x) __bswap_32(x)
-#  endif
-#  ifndef le32toh
-#   define le32toh(x) (x)
-#  endif
-
-#  ifndef htobe64
-#   define htobe64(x) __bswap_64(x)
-#  endif
-#  ifndef htole64
-#   define htole64(x) (x)
-#  endif
-#  ifndef be64toh
-#   define be64toh(x) __bswap_64(x)
-#  endif
-#  ifndef le64toh
-#   define le64toh(x) (x)
-#  endif
-
-# else /* __BYTE_ORDER == __LITTLE_ENDIAN */
-#  ifndef htobe16
-#   define htobe16(x) (x)
-#  endif
-#  ifndef htole16
-#   define htole16(x) __bswap_16(x)
-#  endif
-#  ifndef be16toh
-#   define be16toh(x) (x)
-#  endif
-#  ifndef le16toh
-#   define le16toh(x) __bswap_16(x)
-#  endif
-
-#  ifndef htobe32
-#   define htobe32(x) (x)
-#  endif
-#  ifndef htole32
-#   define htole32(x) __bswap_32(x)
-#  endif
-#  ifndef be32toh
-#   define be32toh(x) (x)
-#  endif
-#  ifndef le32toh
-#   define le32toh(x) __bswap_32(x)
-#  endif
-
-#  ifndef htobe64
-#   define htobe64(x) (x)
-#  endif
-#  ifndef htole64
-#   define htole64(x) __bswap_64(x)
-#  endif
-#  ifndef be64toh
-#   define be64toh(x) (x)
-#  endif
-#  ifndef le64toh
-#   define le64toh(x) __bswap_64(x)
-#  endif
-
-# endif /* __BYTE_ORDER == __LITTLE_ENDIAN */
-#endif /* __USE_BSD */
-
-#elif defined(__FreeBSD__)
-#include <sys/endian.h>
-
-#define bswap_16(x)    bswap16(x)
-#define bswap_32(x)    bswap32(x)
-#define bswap_64(x)    bswap64(x)
-
-#elif defined(__sun__)
-#include <sys/byteorder.h>
-#ifndef __BIG_ENDIAN
-#define __BIG_ENDIAN 4321
-#endif /* __BIG_ENDIAN */
-#ifndef __LITTLE_ENDIAN
-#define __LITTLE_ENDIAN 1234
-#endif /* __LITTLE_ENDIAN */
-
-#ifdef _LITTLE_ENDIAN
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif /* _LITTLE_ENDIAN */
-#ifdef _BIG_ENDIAN
-#define __BYTE_ORDER __BIG_ENDIAN
-#endif /* _BIG_ENDIAN */
-
-#define LITTLE_ENDIAN  __LITTLE_ENDIAN
-#define BIG_ENDIAN     __BIG_ENDIAN
-#define PDP_ENDIAN     __PDP_ENDIAN
-#define BYTE_ORDER     __BYTE_ORDER
-
-#define betoh16(x) BE_16(x)
-#define letoh16(x) LE_16(x)
-#define betoh32(x) BE_32(x)
-#define letoh32(x) LE_32(x)
-#define betoh64(x) BE_64(x)
-#define letoh64(x) LE_64(x)
-#define htobe16(x) BE_16(x)
-#define be16toh(x) BE_16(x)
-#define htobe32(x) BE_32(x)
-#define be32toh(x) BE_32(x)
-#define htobe64(x) BE_64(x)
-#define be64toh(x) BE_64(x)
-
-#elif defined(__APPLE__)
-# include <machine/endian.h>
-# include <libkern/OSByteOrder.h>
-
-# if BYTE_ORDER == LITTLE_ENDIAN
-#  define htobe16(x) OSSwapConstInt16(x)
-#  define htole16(x) (x)
-#  define be16toh(x) OSSwapConstInt16(x)
-#  define le16toh(x) (x)
-
-#  define htobe32(x) OSSwapConstInt32(x)
-#  define htole32(x) (x)
-#  define be32toh(x) OSSwapConstInt32(x)
-#  define le32toh(x) (x)
-
-#  define htobe64(x) OSSwapConstInt64(x)
-#  define htole64(x) (x)
-#  define be64toh(x) OSSwapConstInt64(x)
-#  define le64toh(x) (x)
-
-# else /* BYTE_ORDER == LITTLE_ENDIAN */
-#  define htobe16(x) (x)
-#  define htole16(x) OSSwapConstInt16(x)
-#  define be16toh(x) (x)
-#  define le16toh(x) OSSwapConstInt16(x)
-
-#  define htobe32(x) (x)
-#  define htole32(x) OSSwapConstInt32(x)
-#  define be32toh(x) (x)
-#  define le32toh(x) OSSwapConstInt32(x)
-
-#  define htobe64(x) (x)
-#  define htole64(x) OSSwapConstInt64(x)
-#  define be64toh(x) (x)
-#  define le64toh(x) OSSwapConstInt64(x)
-# endif
-
-#else
-#error "Please add support for your OS."
-#endif
-
-#endif /* _COMPAT_ENDIAN_H */
diff --git a/src/common/compat/endian.hpp b/src/common/compat/endian.hpp
new file mode 100644 (file)
index 0000000..d808b40
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_ENDIAN_H
+#define _COMPAT_ENDIAN_H
+
+#if defined(__linux__) || defined(__CYGWIN__)
+#include <endian.h>
+#include <byteswap.h>
+
+/*
+ * htobe/betoh are not defined for glibc <2.9, so add them
+ * explicitly if they are missing.
+ */
+#ifdef __USE_BSD
+/* Conversion interfaces. */
+# include <byteswap.h>
+
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+#  ifndef htobe16
+#   define htobe16(x) __bswap_16(x)
+#  endif
+#  ifndef htole16
+#   define htole16(x) (x)
+#  endif
+#  ifndef be16toh
+#   define be16toh(x) __bswap_16(x)
+#  endif
+#  ifndef le16toh
+#   define le16toh(x) (x)
+#  endif
+
+#  ifndef htobe32
+#   define htobe32(x) __bswap_32(x)
+#  endif
+#  ifndef htole32
+#   define htole32(x) (x)
+#  endif
+#  ifndef be32toh
+#   define be32toh(x) __bswap_32(x)
+#  endif
+#  ifndef le32toh
+#   define le32toh(x) (x)
+#  endif
+
+#  ifndef htobe64
+#   define htobe64(x) __bswap_64(x)
+#  endif
+#  ifndef htole64
+#   define htole64(x) (x)
+#  endif
+#  ifndef be64toh
+#   define be64toh(x) __bswap_64(x)
+#  endif
+#  ifndef le64toh
+#   define le64toh(x) (x)
+#  endif
+
+# else /* __BYTE_ORDER == __LITTLE_ENDIAN */
+#  ifndef htobe16
+#   define htobe16(x) (x)
+#  endif
+#  ifndef htole16
+#   define htole16(x) __bswap_16(x)
+#  endif
+#  ifndef be16toh
+#   define be16toh(x) (x)
+#  endif
+#  ifndef le16toh
+#   define le16toh(x) __bswap_16(x)
+#  endif
+
+#  ifndef htobe32
+#   define htobe32(x) (x)
+#  endif
+#  ifndef htole32
+#   define htole32(x) __bswap_32(x)
+#  endif
+#  ifndef be32toh
+#   define be32toh(x) (x)
+#  endif
+#  ifndef le32toh
+#   define le32toh(x) __bswap_32(x)
+#  endif
+
+#  ifndef htobe64
+#   define htobe64(x) (x)
+#  endif
+#  ifndef htole64
+#   define htole64(x) __bswap_64(x)
+#  endif
+#  ifndef be64toh
+#   define be64toh(x) (x)
+#  endif
+#  ifndef le64toh
+#   define le64toh(x) __bswap_64(x)
+#  endif
+
+# endif /* __BYTE_ORDER == __LITTLE_ENDIAN */
+#endif /* __USE_BSD */
+
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>
+
+#define bswap_16(x)    bswap16(x)
+#define bswap_32(x)    bswap32(x)
+#define bswap_64(x)    bswap64(x)
+
+#elif defined(__sun__)
+#include <sys/byteorder.h>
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN 4321
+#endif /* __BIG_ENDIAN */
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif /* __LITTLE_ENDIAN */
+
+#ifdef _LITTLE_ENDIAN
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif /* _LITTLE_ENDIAN */
+#ifdef _BIG_ENDIAN
+#define __BYTE_ORDER __BIG_ENDIAN
+#endif /* _BIG_ENDIAN */
+
+#define LITTLE_ENDIAN  __LITTLE_ENDIAN
+#define BIG_ENDIAN     __BIG_ENDIAN
+#define PDP_ENDIAN     __PDP_ENDIAN
+#define BYTE_ORDER     __BYTE_ORDER
+
+#define betoh16(x) BE_16(x)
+#define letoh16(x) LE_16(x)
+#define betoh32(x) BE_32(x)
+#define letoh32(x) LE_32(x)
+#define betoh64(x) BE_64(x)
+#define letoh64(x) LE_64(x)
+#define htobe16(x) BE_16(x)
+#define be16toh(x) BE_16(x)
+#define htobe32(x) BE_32(x)
+#define be32toh(x) BE_32(x)
+#define htobe64(x) BE_64(x)
+#define be64toh(x) BE_64(x)
+
+#elif defined(__APPLE__)
+# include <machine/endian.h>
+# include <libkern/OSByteOrder.h>
+
+# if BYTE_ORDER == LITTLE_ENDIAN
+#  define htobe16(x) OSSwapConstInt16(x)
+#  define htole16(x) (x)
+#  define be16toh(x) OSSwapConstInt16(x)
+#  define le16toh(x) (x)
+
+#  define htobe32(x) OSSwapConstInt32(x)
+#  define htole32(x) (x)
+#  define be32toh(x) OSSwapConstInt32(x)
+#  define le32toh(x) (x)
+
+#  define htobe64(x) OSSwapConstInt64(x)
+#  define htole64(x) (x)
+#  define be64toh(x) OSSwapConstInt64(x)
+#  define le64toh(x) (x)
+
+# else /* BYTE_ORDER == LITTLE_ENDIAN */
+#  define htobe16(x) (x)
+#  define htole16(x) OSSwapConstInt16(x)
+#  define be16toh(x) (x)
+#  define le16toh(x) OSSwapConstInt16(x)
+
+#  define htobe32(x) (x)
+#  define htole32(x) OSSwapConstInt32(x)
+#  define be32toh(x) (x)
+#  define le32toh(x) OSSwapConstInt32(x)
+
+#  define htobe64(x) (x)
+#  define htole64(x) OSSwapConstInt64(x)
+#  define be64toh(x) (x)
+#  define le64toh(x) OSSwapConstInt64(x)
+# endif
+
+#else
+#error "Please add support for your OS."
+#endif
+
+#endif /* _COMPAT_ENDIAN_H */
diff --git a/src/common/compat/errno.h b/src/common/compat/errno.h
deleted file mode 100644 (file)
index 18cb847..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2020 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_ERRNO_H
-#define _COMPAT_ERRNO_H
-
-#include <errno.h>
-
-/* Missing on FreeBSD */
-#ifndef ENODATA
-#define ENODATA ENOATTR
-#endif
-
-#endif /* _COMPAT_ERRNO_H */
diff --git a/src/common/compat/errno.hpp b/src/common/compat/errno.hpp
new file mode 100644 (file)
index 0000000..18cb847
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2020 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_ERRNO_H
+#define _COMPAT_ERRNO_H
+
+#include <errno.h>
+
+/* Missing on FreeBSD */
+#ifndef ENODATA
+#define ENODATA ENOATTR
+#endif
+
+#endif /* _COMPAT_ERRNO_H */
diff --git a/src/common/compat/fcntl.h b/src/common/compat/fcntl.h
deleted file mode 100644 (file)
index b18e2f4..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_FCNTL_H
-#define _COMPAT_FCNTL_H
-
-#include <fcntl.h>
-#include <sys/types.h>
-
-#include <common/compat/errno.h>
-
-#if (defined(__CYGWIN__))
-typedef long long off64_t;
-#endif
-
-#if (defined(__FreeBSD__) || defined(__sun__))
-typedef off64_t loff_t;
-#endif
-
-#ifdef __linux__
-extern int compat_sync_file_range(int fd, off64_t offset, off64_t nbytes,
-               unsigned int flags);
-#define lttng_sync_file_range(fd, offset, nbytes, flags) \
-       compat_sync_file_range(fd, offset, nbytes, flags)
-
-#endif /* __linux__ */
-
-#if (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__))
-/*
- * Possible flags under Linux. Simply nullify them and avoid wrapper.
- */
-#define SYNC_FILE_RANGE_WAIT_AFTER    0
-#define SYNC_FILE_RANGE_WAIT_BEFORE   0
-#define SYNC_FILE_RANGE_WRITE         0
-
-static inline int lttng_sync_file_range(int fd, off64_t offset,
-               off64_t nbytes, unsigned int flags)
-{
-       return -ENOSYS;
-}
-#endif
-
-#if (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__))
-/*
- * Possible flags under Linux. Simply nullify them and avoid wrappers.
- */
-#define SPLICE_F_MOVE       0
-#define SPLICE_F_NONBLOCK   0
-#define SPLICE_F_MORE       0
-#define SPLICE_F_GIFT       0
-
-static inline ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out,
-               size_t len, unsigned int flags)
-{
-       return -ENOSYS;
-}
-#endif
-
-#if !(defined(__linux__) || defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__))
-#error "Please add support for your OS."
-#endif /* __linux__ , __FreeBSD__, __CYGWIN__, __sun__, __APPLE__ */
-
-#endif /* _COMPAT_FCNTL_H */
diff --git a/src/common/compat/fcntl.hpp b/src/common/compat/fcntl.hpp
new file mode 100644 (file)
index 0000000..ac9741a
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_FCNTL_H
+#define _COMPAT_FCNTL_H
+
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <common/compat/errno.hpp>
+
+#if (defined(__CYGWIN__))
+typedef long long off64_t;
+#endif
+
+#if (defined(__FreeBSD__) || defined(__sun__))
+typedef off64_t loff_t;
+#endif
+
+#ifdef __linux__
+extern int compat_sync_file_range(int fd, off64_t offset, off64_t nbytes,
+               unsigned int flags);
+#define lttng_sync_file_range(fd, offset, nbytes, flags) \
+       compat_sync_file_range(fd, offset, nbytes, flags)
+
+#endif /* __linux__ */
+
+#if (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__))
+/*
+ * Possible flags under Linux. Simply nullify them and avoid wrapper.
+ */
+#define SYNC_FILE_RANGE_WAIT_AFTER    0
+#define SYNC_FILE_RANGE_WAIT_BEFORE   0
+#define SYNC_FILE_RANGE_WRITE         0
+
+static inline int lttng_sync_file_range(int fd, off64_t offset,
+               off64_t nbytes, unsigned int flags)
+{
+       return -ENOSYS;
+}
+#endif
+
+#if (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__))
+/*
+ * Possible flags under Linux. Simply nullify them and avoid wrappers.
+ */
+#define SPLICE_F_MOVE       0
+#define SPLICE_F_NONBLOCK   0
+#define SPLICE_F_MORE       0
+#define SPLICE_F_GIFT       0
+
+static inline ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out,
+               size_t len, unsigned int flags)
+{
+       return -ENOSYS;
+}
+#endif
+
+#if !(defined(__linux__) || defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__))
+#error "Please add support for your OS."
+#endif /* __linux__ , __FreeBSD__, __CYGWIN__, __sun__, __APPLE__ */
+
+#endif /* _COMPAT_FCNTL_H */
diff --git a/src/common/compat/getenv.h b/src/common/compat/getenv.h
deleted file mode 100644 (file)
index 83feaee..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _COMPAT_GETENV_H
-#define _COMPAT_GETENV_H
-
-/*
- * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <common/error.h>
-
-static inline
-int lttng_is_setuid_setgid(void)
-{
-       return geteuid() != getuid() || getegid() != getgid();
-}
-
-static inline
-char *lttng_secure_getenv(const char *name)
-{
-       if (lttng_is_setuid_setgid()) {
-               WARN("Getting environment variable '%s' from setuid/setgid binary refused for security reasons.",
-                       name);
-               return NULL;
-       }
-       return getenv(name);
-}
-
-#endif /* _COMPAT_GETENV_H */
diff --git a/src/common/compat/getenv.hpp b/src/common/compat/getenv.hpp
new file mode 100644 (file)
index 0000000..2032f23
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _COMPAT_GETENV_H
+#define _COMPAT_GETENV_H
+
+/*
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <common/error.hpp>
+
+static inline
+int lttng_is_setuid_setgid(void)
+{
+       return geteuid() != getuid() || getegid() != getgid();
+}
+
+static inline
+char *lttng_secure_getenv(const char *name)
+{
+       if (lttng_is_setuid_setgid()) {
+               WARN("Getting environment variable '%s' from setuid/setgid binary refused for security reasons.",
+                       name);
+               return NULL;
+       }
+       return getenv(name);
+}
+
+#endif /* _COMPAT_GETENV_H */
diff --git a/src/common/compat/mman.h b/src/common/compat/mman.h
deleted file mode 100644 (file)
index 37d11fe..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_MMAN_H
-#define _COMPAT_MMAN_H
-
-#include <sys/mman.h>
-
-#ifdef __linux__
-
-#elif defined(__FreeBSD__)
-
-#define MAP_GROWSDOWN 0
-#define MAP_ANONYMOUS MAP_ANON
-
-#elif defined(__CYGWIN__) || defined(__sun__)
-
-#define MAP_GROWSDOWN 0
-
-#else
-#error "Please add support for your OS."
-#endif /* __linux__ */
-
-#endif /* _COMPAT_MMAN_H */
diff --git a/src/common/compat/mman.hpp b/src/common/compat/mman.hpp
new file mode 100644 (file)
index 0000000..37d11fe
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_MMAN_H
+#define _COMPAT_MMAN_H
+
+#include <sys/mman.h>
+
+#ifdef __linux__
+
+#elif defined(__FreeBSD__)
+
+#define MAP_GROWSDOWN 0
+#define MAP_ANONYMOUS MAP_ANON
+
+#elif defined(__CYGWIN__) || defined(__sun__)
+
+#define MAP_GROWSDOWN 0
+
+#else
+#error "Please add support for your OS."
+#endif /* __linux__ */
+
+#endif /* _COMPAT_MMAN_H */
diff --git a/src/common/compat/netdb.h b/src/common/compat/netdb.h
deleted file mode 100644 (file)
index a8bf7e2..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef _COMPAT_NETDB_H
-#define _COMPAT_NETDB_H
-
-#include <netdb.h>
-
-#ifdef HAVE_GETHOSTBYNAME2
-static inline
-struct hostent *lttng_gethostbyname2(const char *name, int af) {
-       return gethostbyname2(name, af);
-}
-#elif HAVE_GETIPNODEBYNAME
-static inline
-struct hostent *lttng_gethostbyname2(const char *name, int af) {
-       int unused;
-
-       return getipnodebyname(name, af, AI_DEFAULT, &unused);
-}
-#else
-# error "Missing compat for gethostbyname2()"
-#endif
-
-#endif /* _COMPAT_NETDB_H */
diff --git a/src/common/compat/netdb.hpp b/src/common/compat/netdb.hpp
new file mode 100644 (file)
index 0000000..a8bf7e2
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef _COMPAT_NETDB_H
+#define _COMPAT_NETDB_H
+
+#include <netdb.h>
+
+#ifdef HAVE_GETHOSTBYNAME2
+static inline
+struct hostent *lttng_gethostbyname2(const char *name, int af) {
+       return gethostbyname2(name, af);
+}
+#elif HAVE_GETIPNODEBYNAME
+static inline
+struct hostent *lttng_gethostbyname2(const char *name, int af) {
+       int unused;
+
+       return getipnodebyname(name, af, AI_DEFAULT, &unused);
+}
+#else
+# error "Missing compat for gethostbyname2()"
+#endif
+
+#endif /* _COMPAT_NETDB_H */
diff --git a/src/common/compat/path.h b/src/common/compat/path.h
deleted file mode 100644 (file)
index 5584e1b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_PATH_H
-#define _COMPAT_PATH_H
-
-/* Build platform's preferred path separator. */
-#if defined(_WIN32) || defined(__CYGWIN__)
-#define LTTNG_PATH_SEPARATOR '\\'
-#else
-#define LTTNG_PATH_SEPARATOR '/'
-#endif
-
-#endif /* _COMPAT_PATH_H */
diff --git a/src/common/compat/path.hpp b/src/common/compat/path.hpp
new file mode 100644 (file)
index 0000000..5584e1b
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_PATH_H
+#define _COMPAT_PATH_H
+
+/* Build platform's preferred path separator. */
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define LTTNG_PATH_SEPARATOR '\\'
+#else
+#define LTTNG_PATH_SEPARATOR '/'
+#endif
+
+#endif /* _COMPAT_PATH_H */
diff --git a/src/common/compat/paths.h b/src/common/compat/paths.h
deleted file mode 100644 (file)
index 7d50e59..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_PATHS_H
-#define _COMPAT_PATHS_H
-
-#ifdef HAVE_PATHS_H
-#include <paths.h>
-#else
-# define _PATH_DEVNULL "/dev/null"
-#endif
-
-#endif /* _COMPAT_PATHS_H */
diff --git a/src/common/compat/paths.hpp b/src/common/compat/paths.hpp
new file mode 100644 (file)
index 0000000..7d50e59
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_PATHS_H
+#define _COMPAT_PATHS_H
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#else
+# define _PATH_DEVNULL "/dev/null"
+#endif
+
+#endif /* _COMPAT_PATHS_H */
index 4254ff8bb674fb5bbd743a57c32b04612f574526..dfcfd10abf9f7a00ed92548fa8c065246880db18 100644 (file)
 #include <stdlib.h>
 #include <stdbool.h>
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/utils.h>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/utils.hpp>
 
-#include "poll.h"
+#include "poll.hpp"
 
 #if HAVE_EPOLL
 
diff --git a/src/common/compat/poll.h b/src/common/compat/poll.h
deleted file mode 100644 (file)
index e2a424a..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_POLL_H
-#define _LTT_POLL_H
-
-#include <string.h>
-#include <unistd.h>
-
-#include <common/common.h>
-
-/*
- * Used by lttng_poll_clean to free the events structure in a lttng_poll_event.
- */
-static inline void __lttng_poll_free(void *events)
-{
-       free(events);
-}
-
-/*
- * epoll(7) implementation.
- */
-#ifdef HAVE_EPOLL
-#include <sys/epoll.h>
-#include <stdio.h>
-#include <features.h>
-#include <common/compat/fcntl.h>
-
-/* See man epoll(7) for this define path */
-#define COMPAT_EPOLL_PROC_PATH "/proc/sys/fs/epoll/max_user_watches"
-
-enum {
-       /* Polling variables compatibility for epoll */
-       LPOLLIN = EPOLLIN,
-       LPOLLPRI = EPOLLPRI,
-       LPOLLOUT = EPOLLOUT,
-       LPOLLRDNORM = EPOLLRDNORM,
-       LPOLLRDBAND = EPOLLRDBAND,
-       LPOLLWRNORM = EPOLLWRNORM,
-       LPOLLWRBAND = EPOLLWRBAND,
-       LPOLLMSG = EPOLLMSG,
-       LPOLLERR = EPOLLERR,
-       LPOLLHUP = EPOLLHUP,
-       LPOLLNVAL = EPOLLHUP,
-       LPOLLRDHUP = EPOLLRDHUP,
-       /* Close on exec feature of epoll */
-#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
-       LTTNG_CLOEXEC = EPOLL_CLOEXEC,
-#else
-       /*
-        * EPOLL_CLOEXEC was added in glibc 2.8 (usually used in conjunction with
-        * epoll_create1(..)), but since neither EPOLL_CLOEXEC exists nor
-        * epoll_create1(..), we set it to FD_CLOEXEC so that we can pass it
-        * directly to fcntl(..) instead.
-        */
-       LTTNG_CLOEXEC = FD_CLOEXEC,
-#endif
-};
-
-struct compat_epoll_event {
-       int epfd;
-       uint32_t nb_fd;       /* Current number of fd in events */
-       uint32_t alloc_size; /* Size of events array */
-       uint32_t init_size;     /* Initial size of events array */
-       struct epoll_event *events;
-};
-#define lttng_poll_event compat_epoll_event
-
-static inline int __lttng_epoll_get_prev_fd(struct lttng_poll_event *events,
-               int index, uint32_t nb_fd)
-{
-       LTTNG_ASSERT(events);
-       LTTNG_ASSERT(index != nb_fd);
-
-       if (index == 0 || nb_fd == 0) {
-               return -1;
-       } else {
-               return events->events[index - 1].data.fd;
-       }
-}
-
-/*
- * For the following calls, consider 'e' to be a lttng_poll_event pointer and i
- * being the index of the events array.
- */
-#define LTTNG_POLL_GETFD(e, i) LTTNG_REF(e)->events[i].data.fd
-#define LTTNG_POLL_GETEV(e, i) LTTNG_REF(e)->events[i].events
-#define LTTNG_POLL_GETNB(e) LTTNG_REF(e)->nb_fd
-#define LTTNG_POLL_GETSZ(e) LTTNG_REF(e)->events_size
-#define LTTNG_POLL_GET_PREV_FD(e, i, nb_fd) \
-       __lttng_epoll_get_prev_fd(LTTNG_REF(e), i, nb_fd)
-
-/* Create the epoll set. */
-extern int compat_epoll_create(struct lttng_poll_event *events,
-               int size, int flags);
-#define lttng_poll_create(events, size, flags) \
-       compat_epoll_create(events, size, flags)
-
-#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
-static inline int compat_glibc_epoll_create(int size __attribute__((unused)),
-               int flags)
-{
-       return epoll_create1(flags);
-}
-#else
-static inline int compat_glibc_epoll_create(int size, int flags)
-{
-       /*
-        * epoll_create1 was added in glibc 2.9, but unfortunatly reverting to
-        * epoll_create(..) also means that we lose the possibility to
-        * directly set the EPOLL_CLOEXEC, so try and do it anyway but through
-        * fcntl(..).
-        */
-       int efd = epoll_create(size);
-       LTTNG_ASSERT(fcntl(efd, F_SETFD, flags) != -1);
-       return efd;
-}
-#endif
-
-/*
- * Wait on epoll set with the number of fd registered to the lttng_poll_event
- * data structure (events).
- */
-extern int compat_epoll_wait(struct lttng_poll_event *events, int timeout,
-               bool interruptible);
-#define lttng_poll_wait(events, timeout) \
-       compat_epoll_wait(events, timeout, false)
-#define lttng_poll_wait_interruptible(events, timeout) \
-       compat_epoll_wait(events, timeout, true)
-
-/*
- * Add a fd to the epoll set and resize the epoll_event structure if needed.
- */
-extern int compat_epoll_add(struct lttng_poll_event *events,
-               int fd, uint32_t req_events);
-#define lttng_poll_add(events, fd, req_events) \
-       compat_epoll_add(events, fd, req_events)
-
-/*
- * Remove a fd from the epoll set.
- */
-extern int compat_epoll_del(struct lttng_poll_event *events, int fd);
-#define lttng_poll_del(events, fd) \
-       compat_epoll_del(events, fd)
-
-/*
- * Modify an fd's events in the epoll set.
- */
-extern int compat_epoll_mod(struct lttng_poll_event *events,
-               int fd, uint32_t req_events);
-#define lttng_poll_mod(events, fd, req_events) \
-       compat_epoll_mod(events, fd, req_events)
-
-/*
- * Set up the poll set limits variable poll_max_size
- */
-extern int compat_epoll_set_max_size(void);
-#define lttng_poll_set_max_size() \
-       compat_epoll_set_max_size()
-
-/*
- * This function memset with zero the structure since it can be reused at each
- * round of a main loop. Being in a loop and using a non static number of fds,
- * this function must be called to insure coherent events with associted fds.
- */
-static inline void lttng_poll_reset(struct lttng_poll_event *events)
-{
-       if (events && events->events) {
-               memset(events->events, 0,
-                               events->nb_fd * sizeof(struct epoll_event));
-       }
-}
-
-/*
- * Initialize an already allocated poll event data structure. For epoll(), the
- * epfd is set to -1 to indicate that it's not usable.
- */
-static inline void lttng_poll_init(struct lttng_poll_event *events)
-{
-       memset(events, 0, sizeof(struct lttng_poll_event));
-       /* Set fd to -1 so if clean before created, we don't close 0. */
-       events->epfd = -1;
-}
-
-/*
- * Clean the events structure of a lttng_poll_event. It's the caller
- * responsability to free the lttng_poll_event memory.
- */
-static inline void lttng_poll_clean(struct lttng_poll_event *events)
-{
-       int ret;
-
-       if (!events) {
-               return;
-       }
-
-       if (events->epfd >= 0) {
-               ret = close(events->epfd);
-               if (ret) {
-                       PERROR("close");
-               }
-       }
-
-       __lttng_poll_free((void *) events->events);
-}
-
-#else  /* HAVE_EPOLL */
-/*
- * Fallback on poll(2) API
- */
-
-/* Needed for some poll event values */
-#ifndef __USE_XOPEN
-#define __USE_XOPEN
-#endif
-
-/* Needed for some poll event values */
-#ifndef __USE_GNU
-#define __USE_GNU
-#endif
-
-#include <poll.h>
-#include <stdint.h>
-
-enum {
-       /* Polling variables compatibility for poll */
-       LPOLLIN = POLLIN,
-       LPOLLPRI = POLLPRI,
-       LPOLLOUT = POLLOUT,
-       LPOLLRDNORM = POLLRDNORM,
-       LPOLLRDBAND = POLLRDBAND,
-       LPOLLWRNORM = POLLWRNORM,
-       LPOLLWRBAND = POLLWRBAND,
-#if __linux__
-       LPOLLMSG = POLLMSG,
-       LPOLLRDHUP = POLLRDHUP,
-#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__))
-       LPOLLMSG = 0,
-       LPOLLRDHUP = 0,
-#else
-#error "Please add support for your OS."
-#endif /* __linux__ */
-       LPOLLERR = POLLERR,
-       LPOLLHUP = POLLHUP | POLLNVAL,
-       /* Close on exec feature does not exist for poll(2) */
-       LTTNG_CLOEXEC = 0xdead,
-};
-
-struct compat_poll_event_array {
-       uint32_t nb_fd;       /* Current number of fd in events */
-       uint32_t alloc_size; /* Size of events array */
-       /* Initial size of the pollset. We never shrink below that. */
-       uint32_t init_size;
-       struct pollfd *events;
-};
-
-struct compat_poll_event {
-       /*
-        * Modified by the wait action. Updated using current fields if the
-        * need_update flag is set.
-        */
-       struct compat_poll_event_array wait;
-       /*
-        * This is modified by add/del actions being the _current_ flow of
-        * execution before a poll wait is done.
-        */
-       struct compat_poll_event_array current;
-
-       /* Indicate if wait.events need to be updated from current. */
-       int need_update:1;
-};
-#define lttng_poll_event compat_poll_event
-
-static inline int __lttng_poll_get_prev_fd(struct lttng_poll_event *events,
-               int index, uint32_t nb_fd)
-{
-       LTTNG_ASSERT(events);
-       LTTNG_ASSERT(index != nb_fd);
-
-       if (index == 0 || nb_fd == 0) {
-               return -1;
-       } else {
-               return events->current.events[index - 1].fd;
-       }
-}
-
-/*
- * For the following calls, consider 'e' to be a lttng_poll_event pointer and i
- * being the index of the events array.
- * LTTNG_POLL_GETNB is always used after lttng_poll_wait, thus we can use the
- * current list for test compatibility purposes.
- */
-#define LTTNG_POLL_GETFD(e, i) LTTNG_REF(e)->wait.events[i].fd
-#define LTTNG_POLL_GETEV(e, i) LTTNG_REF(e)->wait.events[i].revents
-#define LTTNG_POLL_GETNB(e) LTTNG_REF(e)->current.nb_fd
-#define LTTNG_POLL_GETSZ(e) LTTNG_REF(e)->wait.events_size
-#define LTTNG_POLL_GET_PREV_FD(e, i, nb_fd) \
-       __lttng_poll_get_prev_fd(LTTNG_REF(e), i, nb_fd)
-
-/*
- * Create a pollfd structure of size 'size'.
- */
-extern int compat_poll_create(struct lttng_poll_event *events, int size);
-#define lttng_poll_create(events, size, flags) \
-       compat_poll_create(events, size)
-
-/*
- * Wait on poll(2) event with nb_fd registered to the lttng_poll_event data
- * structure.
- */
-extern int compat_poll_wait(struct lttng_poll_event *events, int timeout,
-               bool interruptible);
-#define lttng_poll_wait(events, timeout) \
-       compat_poll_wait(events, timeout, false)
-#define lttng_poll_wait_interruptible(events, timeout) \
-       compat_poll_wait(events, timeout, true)
-
-/*
- * Add the fd to the pollfd structure. Resize if needed.
- */
-extern int compat_poll_add(struct lttng_poll_event *events,
-               int fd, uint32_t req_events);
-#define lttng_poll_add(events, fd, req_events) \
-       compat_poll_add(events, fd, req_events)
-
-/*
- * Remove the fd from the pollfd. Memory allocation is done to recreate a new
- * pollfd, data is copied from the old pollfd to the new and, finally, the old
- * one is freed().
- */
-extern int compat_poll_del(struct lttng_poll_event *events, int fd);
-#define lttng_poll_del(events, fd) \
-       compat_poll_del(events, fd)
-
-/*
- * Modify an fd's events in the poll set.
- */
-extern int compat_poll_mod(struct lttng_poll_event *events,
-               int fd, uint32_t req_events);
-#define lttng_poll_mod(events, fd, req_events) \
-       compat_poll_mod(events, fd, req_events)
-
-/*
- * Set up the poll set limits variable poll_max_size
- */
-extern int compat_poll_set_max_size(void);
-#define lttng_poll_set_max_size() \
-       compat_poll_set_max_size()
-
-/*
- * No need to reset a pollfd structure for poll(2)
- */
-static inline void lttng_poll_reset(struct lttng_poll_event *events)
-{}
-
-/*
- * Initialize an already allocated poll event data structure.
- */
-static inline void lttng_poll_init(struct lttng_poll_event *events)
-{
-       memset(events, 0, sizeof(struct lttng_poll_event));
-}
-
-/*
- * Clean the events structure of a lttng_poll_event. It's the caller
- * responsability to free the lttng_poll_event memory.
- */
-static inline void lttng_poll_clean(struct lttng_poll_event *events)
-{
-       if (events) {
-               __lttng_poll_free((void *) events->wait.events);
-               __lttng_poll_free((void *) events->current.events);
-       }
-}
-
-#endif /* HAVE_EPOLL */
-
-#endif /* _LTT_POLL_H */
diff --git a/src/common/compat/poll.hpp b/src/common/compat/poll.hpp
new file mode 100644 (file)
index 0000000..3eb0da5
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_POLL_H
+#define _LTT_POLL_H
+
+#include <string.h>
+#include <unistd.h>
+
+#include <common/common.hpp>
+
+/*
+ * Used by lttng_poll_clean to free the events structure in a lttng_poll_event.
+ */
+static inline void __lttng_poll_free(void *events)
+{
+       free(events);
+}
+
+/*
+ * epoll(7) implementation.
+ */
+#ifdef HAVE_EPOLL
+#include <sys/epoll.h>
+#include <stdio.h>
+#include <features.h>
+#include <common/compat/fcntl.hpp>
+
+/* See man epoll(7) for this define path */
+#define COMPAT_EPOLL_PROC_PATH "/proc/sys/fs/epoll/max_user_watches"
+
+enum {
+       /* Polling variables compatibility for epoll */
+       LPOLLIN = EPOLLIN,
+       LPOLLPRI = EPOLLPRI,
+       LPOLLOUT = EPOLLOUT,
+       LPOLLRDNORM = EPOLLRDNORM,
+       LPOLLRDBAND = EPOLLRDBAND,
+       LPOLLWRNORM = EPOLLWRNORM,
+       LPOLLWRBAND = EPOLLWRBAND,
+       LPOLLMSG = EPOLLMSG,
+       LPOLLERR = EPOLLERR,
+       LPOLLHUP = EPOLLHUP,
+       LPOLLNVAL = EPOLLHUP,
+       LPOLLRDHUP = EPOLLRDHUP,
+       /* Close on exec feature of epoll */
+#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
+       LTTNG_CLOEXEC = EPOLL_CLOEXEC,
+#else
+       /*
+        * EPOLL_CLOEXEC was added in glibc 2.8 (usually used in conjunction with
+        * epoll_create1(..)), but since neither EPOLL_CLOEXEC exists nor
+        * epoll_create1(..), we set it to FD_CLOEXEC so that we can pass it
+        * directly to fcntl(..) instead.
+        */
+       LTTNG_CLOEXEC = FD_CLOEXEC,
+#endif
+};
+
+struct compat_epoll_event {
+       int epfd;
+       uint32_t nb_fd;       /* Current number of fd in events */
+       uint32_t alloc_size; /* Size of events array */
+       uint32_t init_size;     /* Initial size of events array */
+       struct epoll_event *events;
+};
+#define lttng_poll_event compat_epoll_event
+
+static inline int __lttng_epoll_get_prev_fd(struct lttng_poll_event *events,
+               int index, uint32_t nb_fd)
+{
+       LTTNG_ASSERT(events);
+       LTTNG_ASSERT(index != nb_fd);
+
+       if (index == 0 || nb_fd == 0) {
+               return -1;
+       } else {
+               return events->events[index - 1].data.fd;
+       }
+}
+
+/*
+ * For the following calls, consider 'e' to be a lttng_poll_event pointer and i
+ * being the index of the events array.
+ */
+#define LTTNG_POLL_GETFD(e, i) LTTNG_REF(e)->events[i].data.fd
+#define LTTNG_POLL_GETEV(e, i) LTTNG_REF(e)->events[i].events
+#define LTTNG_POLL_GETNB(e) LTTNG_REF(e)->nb_fd
+#define LTTNG_POLL_GETSZ(e) LTTNG_REF(e)->events_size
+#define LTTNG_POLL_GET_PREV_FD(e, i, nb_fd) \
+       __lttng_epoll_get_prev_fd(LTTNG_REF(e), i, nb_fd)
+
+/* Create the epoll set. */
+extern int compat_epoll_create(struct lttng_poll_event *events,
+               int size, int flags);
+#define lttng_poll_create(events, size, flags) \
+       compat_epoll_create(events, size, flags)
+
+#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
+static inline int compat_glibc_epoll_create(int size __attribute__((unused)),
+               int flags)
+{
+       return epoll_create1(flags);
+}
+#else
+static inline int compat_glibc_epoll_create(int size, int flags)
+{
+       /*
+        * epoll_create1 was added in glibc 2.9, but unfortunatly reverting to
+        * epoll_create(..) also means that we lose the possibility to
+        * directly set the EPOLL_CLOEXEC, so try and do it anyway but through
+        * fcntl(..).
+        */
+       int efd = epoll_create(size);
+       LTTNG_ASSERT(fcntl(efd, F_SETFD, flags) != -1);
+       return efd;
+}
+#endif
+
+/*
+ * Wait on epoll set with the number of fd registered to the lttng_poll_event
+ * data structure (events).
+ */
+extern int compat_epoll_wait(struct lttng_poll_event *events, int timeout,
+               bool interruptible);
+#define lttng_poll_wait(events, timeout) \
+       compat_epoll_wait(events, timeout, false)
+#define lttng_poll_wait_interruptible(events, timeout) \
+       compat_epoll_wait(events, timeout, true)
+
+/*
+ * Add a fd to the epoll set and resize the epoll_event structure if needed.
+ */
+extern int compat_epoll_add(struct lttng_poll_event *events,
+               int fd, uint32_t req_events);
+#define lttng_poll_add(events, fd, req_events) \
+       compat_epoll_add(events, fd, req_events)
+
+/*
+ * Remove a fd from the epoll set.
+ */
+extern int compat_epoll_del(struct lttng_poll_event *events, int fd);
+#define lttng_poll_del(events, fd) \
+       compat_epoll_del(events, fd)
+
+/*
+ * Modify an fd's events in the epoll set.
+ */
+extern int compat_epoll_mod(struct lttng_poll_event *events,
+               int fd, uint32_t req_events);
+#define lttng_poll_mod(events, fd, req_events) \
+       compat_epoll_mod(events, fd, req_events)
+
+/*
+ * Set up the poll set limits variable poll_max_size
+ */
+extern int compat_epoll_set_max_size(void);
+#define lttng_poll_set_max_size() \
+       compat_epoll_set_max_size()
+
+/*
+ * This function memset with zero the structure since it can be reused at each
+ * round of a main loop. Being in a loop and using a non static number of fds,
+ * this function must be called to insure coherent events with associted fds.
+ */
+static inline void lttng_poll_reset(struct lttng_poll_event *events)
+{
+       if (events && events->events) {
+               memset(events->events, 0,
+                               events->nb_fd * sizeof(struct epoll_event));
+       }
+}
+
+/*
+ * Initialize an already allocated poll event data structure. For epoll(), the
+ * epfd is set to -1 to indicate that it's not usable.
+ */
+static inline void lttng_poll_init(struct lttng_poll_event *events)
+{
+       memset(events, 0, sizeof(struct lttng_poll_event));
+       /* Set fd to -1 so if clean before created, we don't close 0. */
+       events->epfd = -1;
+}
+
+/*
+ * Clean the events structure of a lttng_poll_event. It's the caller
+ * responsability to free the lttng_poll_event memory.
+ */
+static inline void lttng_poll_clean(struct lttng_poll_event *events)
+{
+       int ret;
+
+       if (!events) {
+               return;
+       }
+
+       if (events->epfd >= 0) {
+               ret = close(events->epfd);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
+
+       __lttng_poll_free((void *) events->events);
+}
+
+#else  /* HAVE_EPOLL */
+/*
+ * Fallback on poll(2) API
+ */
+
+/* Needed for some poll event values */
+#ifndef __USE_XOPEN
+#define __USE_XOPEN
+#endif
+
+/* Needed for some poll event values */
+#ifndef __USE_GNU
+#define __USE_GNU
+#endif
+
+#include <poll.h>
+#include <stdint.h>
+
+enum {
+       /* Polling variables compatibility for poll */
+       LPOLLIN = POLLIN,
+       LPOLLPRI = POLLPRI,
+       LPOLLOUT = POLLOUT,
+       LPOLLRDNORM = POLLRDNORM,
+       LPOLLRDBAND = POLLRDBAND,
+       LPOLLWRNORM = POLLWRNORM,
+       LPOLLWRBAND = POLLWRBAND,
+#if __linux__
+       LPOLLMSG = POLLMSG,
+       LPOLLRDHUP = POLLRDHUP,
+#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__))
+       LPOLLMSG = 0,
+       LPOLLRDHUP = 0,
+#else
+#error "Please add support for your OS."
+#endif /* __linux__ */
+       LPOLLERR = POLLERR,
+       LPOLLHUP = POLLHUP | POLLNVAL,
+       /* Close on exec feature does not exist for poll(2) */
+       LTTNG_CLOEXEC = 0xdead,
+};
+
+struct compat_poll_event_array {
+       uint32_t nb_fd;       /* Current number of fd in events */
+       uint32_t alloc_size; /* Size of events array */
+       /* Initial size of the pollset. We never shrink below that. */
+       uint32_t init_size;
+       struct pollfd *events;
+};
+
+struct compat_poll_event {
+       /*
+        * Modified by the wait action. Updated using current fields if the
+        * need_update flag is set.
+        */
+       struct compat_poll_event_array wait;
+       /*
+        * This is modified by add/del actions being the _current_ flow of
+        * execution before a poll wait is done.
+        */
+       struct compat_poll_event_array current;
+
+       /* Indicate if wait.events need to be updated from current. */
+       int need_update:1;
+};
+#define lttng_poll_event compat_poll_event
+
+static inline int __lttng_poll_get_prev_fd(struct lttng_poll_event *events,
+               int index, uint32_t nb_fd)
+{
+       LTTNG_ASSERT(events);
+       LTTNG_ASSERT(index != nb_fd);
+
+       if (index == 0 || nb_fd == 0) {
+               return -1;
+       } else {
+               return events->current.events[index - 1].fd;
+       }
+}
+
+/*
+ * For the following calls, consider 'e' to be a lttng_poll_event pointer and i
+ * being the index of the events array.
+ * LTTNG_POLL_GETNB is always used after lttng_poll_wait, thus we can use the
+ * current list for test compatibility purposes.
+ */
+#define LTTNG_POLL_GETFD(e, i) LTTNG_REF(e)->wait.events[i].fd
+#define LTTNG_POLL_GETEV(e, i) LTTNG_REF(e)->wait.events[i].revents
+#define LTTNG_POLL_GETNB(e) LTTNG_REF(e)->current.nb_fd
+#define LTTNG_POLL_GETSZ(e) LTTNG_REF(e)->wait.events_size
+#define LTTNG_POLL_GET_PREV_FD(e, i, nb_fd) \
+       __lttng_poll_get_prev_fd(LTTNG_REF(e), i, nb_fd)
+
+/*
+ * Create a pollfd structure of size 'size'.
+ */
+extern int compat_poll_create(struct lttng_poll_event *events, int size);
+#define lttng_poll_create(events, size, flags) \
+       compat_poll_create(events, size)
+
+/*
+ * Wait on poll(2) event with nb_fd registered to the lttng_poll_event data
+ * structure.
+ */
+extern int compat_poll_wait(struct lttng_poll_event *events, int timeout,
+               bool interruptible);
+#define lttng_poll_wait(events, timeout) \
+       compat_poll_wait(events, timeout, false)
+#define lttng_poll_wait_interruptible(events, timeout) \
+       compat_poll_wait(events, timeout, true)
+
+/*
+ * Add the fd to the pollfd structure. Resize if needed.
+ */
+extern int compat_poll_add(struct lttng_poll_event *events,
+               int fd, uint32_t req_events);
+#define lttng_poll_add(events, fd, req_events) \
+       compat_poll_add(events, fd, req_events)
+
+/*
+ * Remove the fd from the pollfd. Memory allocation is done to recreate a new
+ * pollfd, data is copied from the old pollfd to the new and, finally, the old
+ * one is freed().
+ */
+extern int compat_poll_del(struct lttng_poll_event *events, int fd);
+#define lttng_poll_del(events, fd) \
+       compat_poll_del(events, fd)
+
+/*
+ * Modify an fd's events in the poll set.
+ */
+extern int compat_poll_mod(struct lttng_poll_event *events,
+               int fd, uint32_t req_events);
+#define lttng_poll_mod(events, fd, req_events) \
+       compat_poll_mod(events, fd, req_events)
+
+/*
+ * Set up the poll set limits variable poll_max_size
+ */
+extern int compat_poll_set_max_size(void);
+#define lttng_poll_set_max_size() \
+       compat_poll_set_max_size()
+
+/*
+ * No need to reset a pollfd structure for poll(2)
+ */
+static inline void lttng_poll_reset(struct lttng_poll_event *events)
+{}
+
+/*
+ * Initialize an already allocated poll event data structure.
+ */
+static inline void lttng_poll_init(struct lttng_poll_event *events)
+{
+       memset(events, 0, sizeof(struct lttng_poll_event));
+}
+
+/*
+ * Clean the events structure of a lttng_poll_event. It's the caller
+ * responsability to free the lttng_poll_event memory.
+ */
+static inline void lttng_poll_clean(struct lttng_poll_event *events)
+{
+       if (events) {
+               __lttng_poll_free((void *) events->wait.events);
+               __lttng_poll_free((void *) events->current.events);
+       }
+}
+
+#endif /* HAVE_EPOLL */
+
+#endif /* _LTT_POLL_H */
diff --git a/src/common/compat/pthread.h b/src/common/compat/pthread.h
deleted file mode 100644 (file)
index bedfd91..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2020 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_PTHREAD_H
-#define _COMPAT_PTHREAD_H
-
-#include <pthread.h>
-#include <common/compat/errno.h>
-#include <string.h>
-
-#ifdef __FreeBSD__
-#include <pthread_np.h>
-#endif
-
-#define LTTNG_PTHREAD_NAMELEN 16
-
-#if defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID)
-static inline
-int lttng_pthread_setname_np(const char *name)
-{
-       /*
-        * Some implementations don't error out, replicate this behavior for
-        * consistency.
-        */
-       if (strnlen(name, LTTNG_PTHREAD_NAMELEN) >= LTTNG_PTHREAD_NAMELEN) {
-               return ERANGE;
-       }
-
-       return pthread_setname_np(pthread_self(), name);
-}
-#elif defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)
-static inline
-int lttng_pthread_setname_np(const char *name)
-{
-       return pthread_setname_np(name);
-}
-#elif defined(HAVE_PTHREAD_SET_NAME_NP_WITH_TID)
-
-static inline
-int lttng_pthread_setname_np(const char *name)
-{
-       /* Replicate pthread_setname_np's behavior. */
-       if (strnlen(name, LTTNG_PTHREAD_NAMELEN) >= LTTNG_PTHREAD_NAMELEN) {
-               return ERANGE;
-       }
-
-       pthread_set_name_np(pthread_self(), name);
-       return 0;
-}
-#elif defined(__linux__)
-
-/* Fallback on prtctl on Linux */
-#include <sys/prctl.h>
-
-static inline
-int lttng_pthread_setname_np(const char *name)
-{
-       /* Replicate pthread_setname_np's behavior. */
-       if (strnlen(name, LTTNG_UST_ABI_PROCNAME_LEN) >= LTTNG_UST_ABI_PROCNAME_LEN) {
-               return ERANGE;
-       }
-       return prctl(PR_SET_NAME, name, 0, 0, 0);
-}
-#else
-/*
- * For platforms without thread name support, do nothing.
- */
-static inline
-int lttng_pthread_setname_np(const char *name)
-{
-       return -ENOSYS;
-}
-#endif
-
-
-#if defined(HAVE_PTHREAD_GETNAME_NP_WITH_TID)
-static inline
-int lttng_pthread_getname_np(char *name, size_t len)
-{
-       return pthread_getname_np(pthread_self(), name, len);
-}
-#elif defined(HAVE_PTHREAD_GETNAME_NP_WITHOUT_TID)
-static inline
-int lttng_pthread_getname_np(char *name, size_t len)
-{
-       return pthread_getname_np(name, len);
-}
-#elif defined(HAVE_PTHREAD_GET_NAME_NP_WITH_TID)
-static inline
-int lttng_pthread_getname_np(char *name, size_t len)
-{
-       pthread_get_name_np(pthread_self(), name, len);
-       return 0;
-}
-#elif defined(__linux__)
-
-/* Fallback on prtctl on Linux */
-#include <sys/prctl.h>
-
-static inline
-int lttng_pthread_getname_np(char *name, size_t len)
-{
-       return prctl(PR_GET_NAME, name, 0, 0, 0);
-}
-#else
-/*
- * For platforms without thread name support, do nothing.
- */
-static inline
-int lttng_pthread_getname_np(char *name, size_t len)
-{
-       return -ENOSYS;
-}
-#endif
-
-#endif /* _COMPAT_PTHREAD_H */
diff --git a/src/common/compat/pthread.hpp b/src/common/compat/pthread.hpp
new file mode 100644 (file)
index 0000000..3de7a38
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2020 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_PTHREAD_H
+#define _COMPAT_PTHREAD_H
+
+#include <pthread.h>
+#include <common/compat/errno.hpp>
+#include <string.h>
+
+#ifdef __FreeBSD__
+#include <pthread_np.h>
+#endif
+
+#define LTTNG_PTHREAD_NAMELEN 16
+
+#if defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID)
+static inline
+int lttng_pthread_setname_np(const char *name)
+{
+       /*
+        * Some implementations don't error out, replicate this behavior for
+        * consistency.
+        */
+       if (strnlen(name, LTTNG_PTHREAD_NAMELEN) >= LTTNG_PTHREAD_NAMELEN) {
+               return ERANGE;
+       }
+
+       return pthread_setname_np(pthread_self(), name);
+}
+#elif defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)
+static inline
+int lttng_pthread_setname_np(const char *name)
+{
+       return pthread_setname_np(name);
+}
+#elif defined(HAVE_PTHREAD_SET_NAME_NP_WITH_TID)
+
+static inline
+int lttng_pthread_setname_np(const char *name)
+{
+       /* Replicate pthread_setname_np's behavior. */
+       if (strnlen(name, LTTNG_PTHREAD_NAMELEN) >= LTTNG_PTHREAD_NAMELEN) {
+               return ERANGE;
+       }
+
+       pthread_set_name_np(pthread_self(), name);
+       return 0;
+}
+#elif defined(__linux__)
+
+/* Fallback on prtctl on Linux */
+#include <sys/prctl.h>
+
+static inline
+int lttng_pthread_setname_np(const char *name)
+{
+       /* Replicate pthread_setname_np's behavior. */
+       if (strnlen(name, LTTNG_UST_ABI_PROCNAME_LEN) >= LTTNG_UST_ABI_PROCNAME_LEN) {
+               return ERANGE;
+       }
+       return prctl(PR_SET_NAME, name, 0, 0, 0);
+}
+#else
+/*
+ * For platforms without thread name support, do nothing.
+ */
+static inline
+int lttng_pthread_setname_np(const char *name)
+{
+       return -ENOSYS;
+}
+#endif
+
+
+#if defined(HAVE_PTHREAD_GETNAME_NP_WITH_TID)
+static inline
+int lttng_pthread_getname_np(char *name, size_t len)
+{
+       return pthread_getname_np(pthread_self(), name, len);
+}
+#elif defined(HAVE_PTHREAD_GETNAME_NP_WITHOUT_TID)
+static inline
+int lttng_pthread_getname_np(char *name, size_t len)
+{
+       return pthread_getname_np(name, len);
+}
+#elif defined(HAVE_PTHREAD_GET_NAME_NP_WITH_TID)
+static inline
+int lttng_pthread_getname_np(char *name, size_t len)
+{
+       pthread_get_name_np(pthread_self(), name, len);
+       return 0;
+}
+#elif defined(__linux__)
+
+/* Fallback on prtctl on Linux */
+#include <sys/prctl.h>
+
+static inline
+int lttng_pthread_getname_np(char *name, size_t len)
+{
+       return prctl(PR_GET_NAME, name, 0, 0, 0);
+}
+#else
+/*
+ * For platforms without thread name support, do nothing.
+ */
+static inline
+int lttng_pthread_getname_np(char *name, size_t len)
+{
+       return -ENOSYS;
+}
+#endif
+
+#endif /* _COMPAT_PTHREAD_H */
diff --git a/src/common/compat/socket.h b/src/common/compat/socket.h
deleted file mode 100644 (file)
index b5a3706..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMPAT_SOCKET_H
-#define _COMPAT_SOCKET_H
-
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include <common/macros.h>
-
-#ifndef MSG_NOSIGNAL
-# ifdef SO_NOSIGPIPE
-#   define MSG_NOSIGNAL SO_NOSIGPIPE
-# endif
-#endif
-
-#if defined(MSG_NOSIGNAL)
-static inline
-ssize_t lttng_recvmsg_nosigpipe(int sockfd, struct msghdr *msg)
-{
-       return recvmsg(sockfd, msg, MSG_NOSIGNAL);
-}
-#else
-
-#include <signal.h>
-#include <common/compat/errno.h>
-
-static inline
-ssize_t lttng_recvmsg_nosigpipe(int sockfd, struct msghdr *msg)
-{
-       ssize_t received;
-       int saved_err;
-       sigset_t sigpipe_set, pending_set, old_set;
-       int sigpipe_was_pending;
-
-       /*
-        * Discard the SIGPIPE from send(), not disturbing any SIGPIPE
-        * that might be already pending. If a bogus SIGPIPE is sent to
-        * the entire process concurrently by a malicious user, it may
-        * be simply discarded.
-        */
-       if (sigemptyset(&pending_set)) {
-               return -1;
-       }
-       /*
-        * sigpending returns the mask of signals that are _both_
-        * blocked for the thread _and_ pending for either the thread or
-        * the entire process.
-        */
-       if (sigpending(&pending_set)) {
-               return -1;
-       }
-       sigpipe_was_pending = sigismember(&pending_set, SIGPIPE);
-       /*
-        * If sigpipe was pending, it means it was already blocked, so
-        * no need to block it.
-        */
-       if (!sigpipe_was_pending) {
-               if (sigemptyset(&sigpipe_set)) {
-                       return -1;
-               }
-               if (sigaddset(&sigpipe_set, SIGPIPE)) {
-                       return -1;
-               }
-               if (pthread_sigmask(SIG_BLOCK, &sigpipe_set, &old_set)) {
-                       return -1;
-               }
-       }
-
-       /* Send and save errno. */
-       received = recvmsg(sockfd, msg, 0);
-       saved_err = errno;
-
-       if (received == -1 && errno == EPIPE && !sigpipe_was_pending) {
-               struct timespec timeout = { 0, 0 };
-               int ret;
-
-               do {
-                       ret = sigtimedwait(&sigpipe_set, NULL,
-                               &timeout);
-               } while (ret == -1 && errno == EINTR);
-       }
-       if (!sigpipe_was_pending) {
-               if (pthread_sigmask(SIG_SETMASK, &old_set, NULL)) {
-                       return -1;
-               }
-       }
-       /* Restore send() errno */
-       errno = saved_err;
-
-       return received;
-}
-#endif
-
-#ifdef __sun__
-
-# ifndef CMSG_ALIGN
-#  ifdef _CMSG_DATA_ALIGN
-#   define CMSG_ALIGN(len) _CMSG_DATA_ALIGN(len)
-#  else
-    /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
-#   define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & ~(sizeof (long) - 1))
-#  endif
-#  ifndef CMSG_SPACE
-#    define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + CMSG_ALIGN (len))
-#  endif
-#  ifndef CMSG_LEN
-#    define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
-#  endif
-# endif
-
-#include <ucred.h>
-
-static inline
-int getpeereid(int s, uid_t *euid, gid_t *gid)
-{
-       int ret = 0;
-       ucred_t *ucred = NULL;
-
-       ret = getpeerucred(s, &ucred);
-       if (ret == -1) {
-               goto end;
-       }
-
-       ret = ucred_geteuid(ucred);
-       if (ret == -1) {
-               goto free;
-       }
-       *euid = ret;
-
-       ret = ucred_getrgid(ucred);
-       if (ret == -1) {
-               goto free;
-       }
-       *gid = ret;
-
-       ret = 0;
-free:
-       ucred_free(ucred);
-end:
-       return ret;
-}
-#endif /* __sun__ */
-
-
-#if defined(__linux__) || defined(__CYGWIN__)
-
-#define LTTNG_SOCK_CREDS SCM_CREDENTIALS
-
-typedef struct ucred lttng_sock_cred;
-
-#define LTTNG_SOCK_SET_UID_CRED(c, u) LTTNG_REF(c)->uid = u
-#define LTTNG_SOCK_SET_GID_CRED(c, g) LTTNG_REF(c)->gid = g
-#define LTTNG_SOCK_SET_PID_CRED(c, p) LTTNG_REF(c)->pid = p
-
-#define LTTNG_SOCK_GET_UID_CRED(c) LTTNG_REF(c)->uid
-#define LTTNG_SOCK_GET_GID_CRED(c) LTTNG_REF(c)->gid
-#define LTTNG_SOCK_GET_PID_CRED(c) LTTNG_REF(c)->pid
-
-#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__))
-
-struct lttng_sock_cred {
-       uid_t uid;
-       gid_t gid;
-       pid_t pid;
-};
-
-typedef struct lttng_sock_cred lttng_sock_cred;
-
-#define LTTNG_SOCK_SET_UID_CRED(c, u) LTTNG_REF(c)->uid = u
-#define LTTNG_SOCK_SET_GID_CRED(c, g) LTTNG_REF(c)->gid = g
-#define LTTNG_SOCK_SET_PID_CRED(c, p) LTTNG_REF(c)->pid = p
-
-#define LTTNG_SOCK_GET_UID_CRED(c) LTTNG_REF(c)->uid
-#define LTTNG_SOCK_GET_GID_CRED(c) LTTNG_REF(c)->gid
-#define LTTNG_SOCK_GET_PID_CRED(c) LTTNG_REF(c)->pid
-
-#ifdef __APPLE__
-
-static inline
-int lttng_get_unix_socket_peer_pid(int socket_fd, pid_t *pid)
-{
-       socklen_t pid_len = (socklen_t) sizeof(*pid);
-
-       /* The getsockopt LOCAL_PEERPID option is available since macOS 10.8. */
-       return getsockopt(socket_fd, SOL_LOCAL, LOCAL_PEERPID, pid, &pid_len);
-}
-
-#elif defined(__sun__)
-
-/* Use the getpeerucreds interface on Solaris. */
-static inline
-int lttng_get_unix_socket_peer_pid(int socket_fd, pid_t *pid)
-{
-       int ret = 0;
-       ucred_t *ucred = NULL;
-
-       ret = getpeerucred(s, &ucred);
-       if (ret == -1) {
-               goto end;
-       }
-
-       ret = ucred_getpid(ucred);
-       if (ret == -1) {
-               goto free;
-       }
-
-       *pid = ret;
-       ret = 0;
-free:
-       ucred_free(ucred);
-end:
-       return ret;
-}
-
-#elif defined(__FreeBSD__)
-
-#include <sys/ucred.h>
-
-static inline
-int lttng_get_unix_socket_peer_pid(int socket_fd, pid_t *pid)
-{
-       int ret;
-       struct xucred sock_creds = {};
-
-       /* Only available in FreeBSD 13.0 and up. */
-       ret = getsockopt(socket_fd, SOL_LOCAL, LOCAL_PEERCRED, &sock_creds,
-                       &((socklen_t) {sizeof(sock_creds)}));
-       if (ret) {
-               goto end;
-       }
-
-       *pid = sock_creds.cr_pid;
-end:
-       return ret;
-}
-
-#endif /* __APPLE__ */
-
-
-static inline
-int lttng_get_unix_socket_peer_creds(int socket_fd, struct lttng_sock_cred *creds)
-{
-       int ret;
-
-       /* This is a BSD extension that is supported by Cygwin. */
-       ret = getpeereid(socket_fd, &creds->uid, &creds->gid);
-       if (ret) {
-               goto end;
-       }
-
-       /*
-        * Getting a peer's PID is a bit more troublesome as it is platform
-        * specific.
-        */
-       ret = lttng_get_unix_socket_peer_pid(socket_fd, &creds->pid);
-end:
-       return ret;
-}
-
-#else
-#error "Please add support for your OS."
-#endif /* __linux__ , __FreeBSD__, __APPLE__ */
-
-#endif /* _COMPAT_SOCKET_H */
diff --git a/src/common/compat/socket.hpp b/src/common/compat/socket.hpp
new file mode 100644 (file)
index 0000000..9bb66e8
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMPAT_SOCKET_H
+#define _COMPAT_SOCKET_H
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <common/macros.hpp>
+
+#ifndef MSG_NOSIGNAL
+# ifdef SO_NOSIGPIPE
+#   define MSG_NOSIGNAL SO_NOSIGPIPE
+# endif
+#endif
+
+#if defined(MSG_NOSIGNAL)
+static inline
+ssize_t lttng_recvmsg_nosigpipe(int sockfd, struct msghdr *msg)
+{
+       return recvmsg(sockfd, msg, MSG_NOSIGNAL);
+}
+#else
+
+#include <signal.h>
+#include <common/compat/errno.hpp>
+
+static inline
+ssize_t lttng_recvmsg_nosigpipe(int sockfd, struct msghdr *msg)
+{
+       ssize_t received;
+       int saved_err;
+       sigset_t sigpipe_set, pending_set, old_set;
+       int sigpipe_was_pending;
+
+       /*
+        * Discard the SIGPIPE from send(), not disturbing any SIGPIPE
+        * that might be already pending. If a bogus SIGPIPE is sent to
+        * the entire process concurrently by a malicious user, it may
+        * be simply discarded.
+        */
+       if (sigemptyset(&pending_set)) {
+               return -1;
+       }
+       /*
+        * sigpending returns the mask of signals that are _both_
+        * blocked for the thread _and_ pending for either the thread or
+        * the entire process.
+        */
+       if (sigpending(&pending_set)) {
+               return -1;
+       }
+       sigpipe_was_pending = sigismember(&pending_set, SIGPIPE);
+       /*
+        * If sigpipe was pending, it means it was already blocked, so
+        * no need to block it.
+        */
+       if (!sigpipe_was_pending) {
+               if (sigemptyset(&sigpipe_set)) {
+                       return -1;
+               }
+               if (sigaddset(&sigpipe_set, SIGPIPE)) {
+                       return -1;
+               }
+               if (pthread_sigmask(SIG_BLOCK, &sigpipe_set, &old_set)) {
+                       return -1;
+               }
+       }
+
+       /* Send and save errno. */
+       received = recvmsg(sockfd, msg, 0);
+       saved_err = errno;
+
+       if (received == -1 && errno == EPIPE && !sigpipe_was_pending) {
+               struct timespec timeout = { 0, 0 };
+               int ret;
+
+               do {
+                       ret = sigtimedwait(&sigpipe_set, NULL,
+                               &timeout);
+               } while (ret == -1 && errno == EINTR);
+       }
+       if (!sigpipe_was_pending) {
+               if (pthread_sigmask(SIG_SETMASK, &old_set, NULL)) {
+                       return -1;
+               }
+       }
+       /* Restore send() errno */
+       errno = saved_err;
+
+       return received;
+}
+#endif
+
+#ifdef __sun__
+
+# ifndef CMSG_ALIGN
+#  ifdef _CMSG_DATA_ALIGN
+#   define CMSG_ALIGN(len) _CMSG_DATA_ALIGN(len)
+#  else
+    /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
+#   define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & ~(sizeof (long) - 1))
+#  endif
+#  ifndef CMSG_SPACE
+#    define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + CMSG_ALIGN (len))
+#  endif
+#  ifndef CMSG_LEN
+#    define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
+#  endif
+# endif
+
+#include <ucred.h>
+
+static inline
+int getpeereid(int s, uid_t *euid, gid_t *gid)
+{
+       int ret = 0;
+       ucred_t *ucred = NULL;
+
+       ret = getpeerucred(s, &ucred);
+       if (ret == -1) {
+               goto end;
+       }
+
+       ret = ucred_geteuid(ucred);
+       if (ret == -1) {
+               goto free;
+       }
+       *euid = ret;
+
+       ret = ucred_getrgid(ucred);
+       if (ret == -1) {
+               goto free;
+       }
+       *gid = ret;
+
+       ret = 0;
+free:
+       ucred_free(ucred);
+end:
+       return ret;
+}
+#endif /* __sun__ */
+
+
+#if defined(__linux__) || defined(__CYGWIN__)
+
+#define LTTNG_SOCK_CREDS SCM_CREDENTIALS
+
+typedef struct ucred lttng_sock_cred;
+
+#define LTTNG_SOCK_SET_UID_CRED(c, u) LTTNG_REF(c)->uid = u
+#define LTTNG_SOCK_SET_GID_CRED(c, g) LTTNG_REF(c)->gid = g
+#define LTTNG_SOCK_SET_PID_CRED(c, p) LTTNG_REF(c)->pid = p
+
+#define LTTNG_SOCK_GET_UID_CRED(c) LTTNG_REF(c)->uid
+#define LTTNG_SOCK_GET_GID_CRED(c) LTTNG_REF(c)->gid
+#define LTTNG_SOCK_GET_PID_CRED(c) LTTNG_REF(c)->pid
+
+#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__))
+
+struct lttng_sock_cred {
+       uid_t uid;
+       gid_t gid;
+       pid_t pid;
+};
+
+typedef struct lttng_sock_cred lttng_sock_cred;
+
+#define LTTNG_SOCK_SET_UID_CRED(c, u) LTTNG_REF(c)->uid = u
+#define LTTNG_SOCK_SET_GID_CRED(c, g) LTTNG_REF(c)->gid = g
+#define LTTNG_SOCK_SET_PID_CRED(c, p) LTTNG_REF(c)->pid = p
+
+#define LTTNG_SOCK_GET_UID_CRED(c) LTTNG_REF(c)->uid
+#define LTTNG_SOCK_GET_GID_CRED(c) LTTNG_REF(c)->gid
+#define LTTNG_SOCK_GET_PID_CRED(c) LTTNG_REF(c)->pid
+
+#ifdef __APPLE__
+
+static inline
+int lttng_get_unix_socket_peer_pid(int socket_fd, pid_t *pid)
+{
+       socklen_t pid_len = (socklen_t) sizeof(*pid);
+
+       /* The getsockopt LOCAL_PEERPID option is available since macOS 10.8. */
+       return getsockopt(socket_fd, SOL_LOCAL, LOCAL_PEERPID, pid, &pid_len);
+}
+
+#elif defined(__sun__)
+
+/* Use the getpeerucreds interface on Solaris. */
+static inline
+int lttng_get_unix_socket_peer_pid(int socket_fd, pid_t *pid)
+{
+       int ret = 0;
+       ucred_t *ucred = NULL;
+
+       ret = getpeerucred(s, &ucred);
+       if (ret == -1) {
+               goto end;
+       }
+
+       ret = ucred_getpid(ucred);
+       if (ret == -1) {
+               goto free;
+       }
+
+       *pid = ret;
+       ret = 0;
+free:
+       ucred_free(ucred);
+end:
+       return ret;
+}
+
+#elif defined(__FreeBSD__)
+
+#include <sys/ucred.h>
+
+static inline
+int lttng_get_unix_socket_peer_pid(int socket_fd, pid_t *pid)
+{
+       int ret;
+       struct xucred sock_creds = {};
+
+       /* Only available in FreeBSD 13.0 and up. */
+       ret = getsockopt(socket_fd, SOL_LOCAL, LOCAL_PEERCRED, &sock_creds,
+                       &((socklen_t) {sizeof(sock_creds)}));
+       if (ret) {
+               goto end;
+       }
+
+       *pid = sock_creds.cr_pid;
+end:
+       return ret;
+}
+
+#endif /* __APPLE__ */
+
+
+static inline
+int lttng_get_unix_socket_peer_creds(int socket_fd, struct lttng_sock_cred *creds)
+{
+       int ret;
+
+       /* This is a BSD extension that is supported by Cygwin. */
+       ret = getpeereid(socket_fd, &creds->uid, &creds->gid);
+       if (ret) {
+               goto end;
+       }
+
+       /*
+        * Getting a peer's PID is a bit more troublesome as it is platform
+        * specific.
+        */
+       ret = lttng_get_unix_socket_peer_pid(socket_fd, &creds->pid);
+end:
+       return ret;
+}
+
+#else
+#error "Please add support for your OS."
+#endif /* __linux__ , __FreeBSD__, __APPLE__ */
+
+#endif /* _COMPAT_SOCKET_H */
diff --git a/src/common/compat/string.h b/src/common/compat/string.h
deleted file mode 100644 (file)
index fd4f2f0..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
- * Copyright (C) 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef _COMPAT_STRING_H
-#define _COMPAT_STRING_H
-
-#include <string.h>
-#include <stdlib.h>
-
-#ifdef HAVE_STRNLEN
-static inline
-size_t lttng_strnlen(const char *str, size_t max)
-{
-       return strnlen(str, max);
-}
-#else
-static inline
-size_t lttng_strnlen(const char *str, size_t max)
-{
-       size_t ret;
-       const char *end;
-
-       end = (const char *) memchr(str, 0, max);
-
-       if (end) {
-               ret = (size_t) (end - str);
-       } else {
-               ret = max;
-       }
-
-       return ret;
-}
-#endif /* HAVE_STRNLEN */
-
-#ifdef HAVE_STRNDUP
-static inline
-char *lttng_strndup(const char *s, size_t n)
-{
-       return strndup(s, n);
-}
-#else
-static inline
-char *lttng_strndup(const char *s, size_t n)
-{
-       char *ret;
-       size_t navail;
-
-       if (!s) {
-               ret = NULL;
-               goto end;
-       }
-
-       /* min() */
-       navail = strlen(s) + 1;
-       if ((n + 1) < navail) {
-               navail = n + 1;
-       }
-
-       ret = (char *) malloc(navail);
-       if (!ret) {
-               goto end;
-       }
-
-       memcpy(ret, s, navail);
-       ret[navail - 1] = '\0';
-end:
-       return ret;
-}
-#endif /* HAVE_STRNDUP */
-
-#ifdef HAVE_FLS
-static inline int lttng_fls(int val)
-{
-       return fls(val);
-}
-#else
-static inline int lttng_fls(int val)
-{
-       int r = 32;
-       unsigned int x = (unsigned int) val;
-
-       if (!x)
-               return 0;
-       if (!(x & 0xFFFF0000U)) {
-               x <<= 16;
-               r -= 16;
-       }
-       if (!(x & 0xFF000000U)) {
-               x <<= 8;
-               r -= 8;
-       }
-       if (!(x & 0xF0000000U)) {
-               x <<= 4;
-               r -= 4;
-       }
-       if (!(x & 0xC0000000U)) {
-               x <<= 2;
-               r -= 2;
-       }
-       if (!(x & 0x80000000U)) {
-               r -= 1;
-       }
-       return r;
-}
-#endif /* HAVE_FLS */
-
-#if HAVE_MEMRCHR
-static inline
-void *lttng_memrchr(const void *s, int c, size_t n)
-{
-       return (void *) memrchr(s, c, n);
-}
-#else
-static inline
-void *lttng_memrchr(const void *s, int c, size_t n)
-{
-       int i;
-       const char *str = (const char *) s;
-       for (i = n-1; i >= 0; i--) {
-               if (str[i] == (char)c) {
-                       return (void *)(str+i);
-               }
-       }
-       return NULL;
-}
-#endif /* HAVE_MEMRCHR */
-
-#endif /* _COMPAT_STRING_H */
diff --git a/src/common/compat/string.hpp b/src/common/compat/string.hpp
new file mode 100644 (file)
index 0000000..fd4f2f0
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 Michael Jeanson <mjeanson@efficios.com>
+ * Copyright (C) 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef _COMPAT_STRING_H
+#define _COMPAT_STRING_H
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRNLEN
+static inline
+size_t lttng_strnlen(const char *str, size_t max)
+{
+       return strnlen(str, max);
+}
+#else
+static inline
+size_t lttng_strnlen(const char *str, size_t max)
+{
+       size_t ret;
+       const char *end;
+
+       end = (const char *) memchr(str, 0, max);
+
+       if (end) {
+               ret = (size_t) (end - str);
+       } else {
+               ret = max;
+       }
+
+       return ret;
+}
+#endif /* HAVE_STRNLEN */
+
+#ifdef HAVE_STRNDUP
+static inline
+char *lttng_strndup(const char *s, size_t n)
+{
+       return strndup(s, n);
+}
+#else
+static inline
+char *lttng_strndup(const char *s, size_t n)
+{
+       char *ret;
+       size_t navail;
+
+       if (!s) {
+               ret = NULL;
+               goto end;
+       }
+
+       /* min() */
+       navail = strlen(s) + 1;
+       if ((n + 1) < navail) {
+               navail = n + 1;
+       }
+
+       ret = (char *) malloc(navail);
+       if (!ret) {
+               goto end;
+       }
+
+       memcpy(ret, s, navail);
+       ret[navail - 1] = '\0';
+end:
+       return ret;
+}
+#endif /* HAVE_STRNDUP */
+
+#ifdef HAVE_FLS
+static inline int lttng_fls(int val)
+{
+       return fls(val);
+}
+#else
+static inline int lttng_fls(int val)
+{
+       int r = 32;
+       unsigned int x = (unsigned int) val;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xFFFF0000U)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xFF000000U)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xF0000000U)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xC0000000U)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000U)) {
+               r -= 1;
+       }
+       return r;
+}
+#endif /* HAVE_FLS */
+
+#if HAVE_MEMRCHR
+static inline
+void *lttng_memrchr(const void *s, int c, size_t n)
+{
+       return (void *) memrchr(s, c, n);
+}
+#else
+static inline
+void *lttng_memrchr(const void *s, int c, size_t n)
+{
+       int i;
+       const char *str = (const char *) s;
+       for (i = n-1; i >= 0; i--) {
+               if (str[i] == (char)c) {
+                       return (void *)(str+i);
+               }
+       }
+       return NULL;
+}
+#endif /* HAVE_MEMRCHR */
+
+#endif /* _COMPAT_STRING_H */
diff --git a/src/common/compat/tid.h b/src/common/compat/tid.h
deleted file mode 100644 (file)
index 4a6ff74..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2012 (C) Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef LTTNG_TID_H
-#define LTTNG_TID_H
-
-#ifdef __linux__
-#include <syscall.h>
-#endif
-
-#if defined(__NR_gettid)
-
-#include <unistd.h>
-static inline pid_t lttng_gettid(void)
-{
-       return syscall(__NR_gettid);
-}
-
-#else
-
-#include <sys/types.h>
-#include <unistd.h>
-
-/* Fall-back on getpid for tid if not available. */
-static inline pid_t lttng_gettid(void)
-{
-       return getpid();
-}
-
-#endif
-
-#endif /* LTTNG_TID_H */
diff --git a/src/common/compat/tid.hpp b/src/common/compat/tid.hpp
new file mode 100644 (file)
index 0000000..4a6ff74
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 (C) Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef LTTNG_TID_H
+#define LTTNG_TID_H
+
+#ifdef __linux__
+#include <syscall.h>
+#endif
+
+#if defined(__NR_gettid)
+
+#include <unistd.h>
+static inline pid_t lttng_gettid(void)
+{
+       return syscall(__NR_gettid);
+}
+
+#else
+
+#include <sys/types.h>
+#include <unistd.h>
+
+/* Fall-back on getpid for tid if not available. */
+static inline pid_t lttng_gettid(void)
+{
+       return getpid();
+}
+
+#endif
+
+#endif /* LTTNG_TID_H */
diff --git a/src/common/compat/time.h b/src/common/compat/time.h
deleted file mode 100644 (file)
index 72a9aff..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2016 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef _COMPAT_TIME_H
-#define _COMPAT_TIME_H
-
-#include <time.h>
-
-#ifdef __APPLE__
-
-typedef uint64_t timer_t;
-
-#include <mach/mach.h>
-#include <mach/clock.h>
-#include <common/compat/errno.h>
-
-#undef NSEC_PER_SEC
-#undef NSEC_PER_MSEC
-#undef NSEC_PER_USEC
-#undef USEC_PER_SEC
-
-#endif /* __APPLE__ */
-
-/* macOS/OS X 10.12 (Sierra) and up provide clock_gettime() */
-#if defined(__APPLE__) && !defined(LTTNG_HAVE_CLOCK_GETTIME)
-
-typedef int clockid_t;
-#define CLOCK_REALTIME CALENDAR_CLOCK
-#define CLOCK_MONOTONIC SYSTEM_CLOCK
-
-static inline
-int lttng_clock_gettime(clockid_t clk_id, struct timespec *tp)
-{
-       int ret = 0;
-       clock_serv_t clock;
-       mach_timespec_t now;
-
-       if (clk_id != CLOCK_REALTIME && clk_id != CLOCK_MONOTONIC) {
-               ret = -1;
-               errno = EINVAL;
-               goto end;
-       }
-
-       host_get_clock_service(mach_host_self(), clk_id, &clock);
-
-       ret = clock_get_time(clock, &now);
-       if (ret != KERN_SUCCESS) {
-               ret = -1;
-               goto deallocate;
-       }
-
-       tp->tv_sec = now.tv_sec;
-       tp->tv_nsec = now.tv_nsec;
-
-deallocate:
-       mach_port_deallocate(mach_task_self(), clock);
-end:
-       return ret;
-}
-
-#else /* __APPLE__ && !LTTNG_HAVE_CLOCK_GETTIME */
-
-static inline
-int lttng_clock_gettime(clockid_t clk_id, struct timespec *tp)
-{
-       return clock_gettime(clk_id, tp);
-}
-
-#endif /* __APPLE__ && !LTTNG_HAVE_CLOCK_GETTIME */
-
-#endif /* _COMPAT_TIME_H */
diff --git a/src/common/compat/time.hpp b/src/common/compat/time.hpp
new file mode 100644 (file)
index 0000000..37f472a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef _COMPAT_TIME_H
+#define _COMPAT_TIME_H
+
+#include <time.h>
+
+#ifdef __APPLE__
+
+typedef uint64_t timer_t;
+
+#include <mach/mach.h>
+#include <mach/clock.h>
+#include <common/compat/errno.hpp>
+
+#undef NSEC_PER_SEC
+#undef NSEC_PER_MSEC
+#undef NSEC_PER_USEC
+#undef USEC_PER_SEC
+
+#endif /* __APPLE__ */
+
+/* macOS/OS X 10.12 (Sierra) and up provide clock_gettime() */
+#if defined(__APPLE__) && !defined(LTTNG_HAVE_CLOCK_GETTIME)
+
+typedef int clockid_t;
+#define CLOCK_REALTIME CALENDAR_CLOCK
+#define CLOCK_MONOTONIC SYSTEM_CLOCK
+
+static inline
+int lttng_clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+       int ret = 0;
+       clock_serv_t clock;
+       mach_timespec_t now;
+
+       if (clk_id != CLOCK_REALTIME && clk_id != CLOCK_MONOTONIC) {
+               ret = -1;
+               errno = EINVAL;
+               goto end;
+       }
+
+       host_get_clock_service(mach_host_self(), clk_id, &clock);
+
+       ret = clock_get_time(clock, &now);
+       if (ret != KERN_SUCCESS) {
+               ret = -1;
+               goto deallocate;
+       }
+
+       tp->tv_sec = now.tv_sec;
+       tp->tv_nsec = now.tv_nsec;
+
+deallocate:
+       mach_port_deallocate(mach_task_self(), clock);
+end:
+       return ret;
+}
+
+#else /* __APPLE__ && !LTTNG_HAVE_CLOCK_GETTIME */
+
+static inline
+int lttng_clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+       return clock_gettime(clk_id, tp);
+}
+
+#endif /* __APPLE__ && !LTTNG_HAVE_CLOCK_GETTIME */
+
+#endif /* _COMPAT_TIME_H */
index fa28db65b9ad3deca1b4944258da77f7342676dc..b1d001dc4ae599332546a61eab3940a13a58ad4a 100644 (file)
@@ -5,12 +5,12 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
 #include <float.h>
-#include <lttng/condition/buffer-usage-internal.h>
-#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/buffer-usage-internal.hpp>
+#include <lttng/condition/condition-internal.hpp>
 #include <math.h>
 #include <time.h>
 
index 18b756dce4c489e2a88f8ef318c366c03c41ce2e..525932eb2f06d43dcbf183e2239a8a7ed7dbe641 100644 (file)
@@ -5,17 +5,17 @@
  *
  */
 
-#include <common/buffer-view.h>
-#include <common/dynamic-buffer.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <lttng/condition/buffer-usage-internal.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule-matches-internal.h>
-#include <lttng/condition/session-consumed-size-internal.h>
-#include <lttng/condition/session-rotation-internal.h>
-#include <lttng/error-query-internal.h>
+#include <common/buffer-view.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/condition/buffer-usage-internal.hpp>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/event-rule-matches-internal.hpp>
+#include <lttng/condition/session-consumed-size-internal.hpp>
+#include <lttng/condition/session-rotation-internal.hpp>
+#include <lttng/error-query-internal.hpp>
 #include <stdbool.h>
 
 enum lttng_condition_type lttng_condition_get_type(
index 3e7776f46cbd5d5449cfed4af2482a7d83031bdc..033dbca48a040b46131d7b9b5615e6f06e7e946f 100644 (file)
@@ -5,18 +5,18 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
 #include <inttypes.h>
 #include <limits.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/event-rule-matches-internal.hpp>
 #include <lttng/condition/event-rule-matches.h>
-#include <lttng/event-expr-internal.h>
+#include <lttng/event-expr-internal.hpp>
 #include <lttng/event-expr.h>
-#include <lttng/event-field-value-internal.h>
-#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-field-value-internal.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
 #include <lttng/lttng-error.h>
 #include <stdbool.h>
 #include <stdint.h>
index 86a7f332a513c9cb469c9003f776da703dc5952f..8bc70abf61fab875ff67f87944dac9de7895b62e 100644 (file)
@@ -5,12 +5,12 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
 #include <float.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/session-consumed-size-internal.h>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/session-consumed-size-internal.hpp>
 #include <lttng/constant.h>
 #include <math.h>
 #include <time.h>
index 7e59895f99812c9e28ff12e10f7382d0d782f6b1..da7739b2acd45467d65968ce19cff34372370734 100644 (file)
@@ -5,12 +5,12 @@
  *
  */
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/session-rotation-internal.h>
-#include <lttng/location-internal.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/session-rotation-internal.hpp>
+#include <lttng/location-internal.hpp>
 #include <stdbool.h>
 
 static
diff --git a/src/common/config/Makefile.am b/src/common/config/Makefile.am
deleted file mode 100644 (file)
index a273523..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libconfig.la
-
-libconfig_la_SOURCES = \
-       config-internal.h \
-       config-session-abi.h \
-       session-config.cpp \
-       session-config.h
-libconfig_la_CPPFLAGS = $(libxml2_CFLAGS) $(AM_CPPFLAGS)
-libconfig_la_LIBADD = ${libxml2_LIBS}
-
-xmldir = $(datadir)/xml/lttng
-dist_xml_DATA = session.xsd
-EXTRA_DIST = session.xsd
-
-all-local:
-       @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
-               for script in $(EXTRA_DIST); do \
-               cp -f $(srcdir)/$$script $(builddir); \
-               done; \
-       fi
-
-clean-local:
-       @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
-               for script in $(EXTRA_DIST); do \
-               rm -f $(builddir)/$$script; \
-               done; \
-       fi
diff --git a/src/common/config/config-internal.h b/src/common/config/config-internal.h
deleted file mode 100644 (file)
index ee632ef..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <libxml/xmlwriter.h>
-#include <stdio.h>
-
-struct config_writer {
-       xmlTextWriterPtr writer;
-};
diff --git a/src/common/config/config-internal.hpp b/src/common/config/config-internal.hpp
new file mode 100644 (file)
index 0000000..ee632ef
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <libxml/xmlwriter.h>
+#include <stdio.h>
+
+struct config_writer {
+       xmlTextWriterPtr writer;
+};
diff --git a/src/common/config/config-session-abi.h b/src/common/config/config-session-abi.h
deleted file mode 100644 (file)
index 6c903ef..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef CONFIG_SESSION_INTERNAL_H
-#define CONFIG_SESSION_INTERNAL_H
-
-#include <lttng/lttng-export.h>
-
-extern const char * const config_element_all;
-LTTNG_EXPORT extern const char * const config_element_channel;
-LTTNG_EXPORT extern const char * const config_element_channels;
-LTTNG_EXPORT extern const char * const config_element_domain;
-LTTNG_EXPORT extern const char * const config_element_domains;
-LTTNG_EXPORT extern const char * const config_element_event;
-LTTNG_EXPORT extern const char * const config_element_events;
-LTTNG_EXPORT extern const char * const config_element_context;
-LTTNG_EXPORT extern const char * const config_element_contexts;
-LTTNG_EXPORT extern const char * const config_element_attributes;
-LTTNG_EXPORT extern const char * const config_element_exclusion;
-LTTNG_EXPORT extern const char * const config_element_exclusions;
-LTTNG_EXPORT extern const char * const config_element_function_attributes;
-LTTNG_EXPORT extern const char * const config_element_probe_attributes;
-LTTNG_EXPORT extern const char * const config_element_symbol_name;
-LTTNG_EXPORT extern const char * const config_element_address;
-LTTNG_EXPORT extern const char * const config_element_offset;
-extern const char * const config_element_userspace_probe_lookup;
-extern const char * const config_element_userspace_probe_lookup_function_default;
-extern const char * const config_element_userspace_probe_lookup_function_elf;
-extern const char * const config_element_userspace_probe_lookup_tracepoint_sdt;
-extern const char * const config_element_userspace_probe_location_binary_path;
-extern const char * const config_element_userspace_probe_function_attributes;
-extern const char * const config_element_userspace_probe_function_location_function_name;
-extern const char * const config_element_userspace_probe_tracepoint_attributes;
-extern const char * const config_element_userspace_probe_tracepoint_location_provider_name;
-extern const char * const config_element_userspace_probe_tracepoint_location_probe_name;
-extern const char * const config_element_name;
-LTTNG_EXPORT extern const char * const config_element_enabled;
-LTTNG_EXPORT extern const char * const config_element_overwrite_mode;
-LTTNG_EXPORT extern const char * const config_element_subbuf_size;
-LTTNG_EXPORT extern const char * const config_element_num_subbuf;
-LTTNG_EXPORT extern const char * const config_element_switch_timer_interval;
-LTTNG_EXPORT extern const char * const config_element_read_timer_interval;
-extern const char * const config_element_monitor_timer_interval;
-extern const char * const config_element_blocking_timeout;
-LTTNG_EXPORT extern const char * const config_element_output;
-LTTNG_EXPORT extern const char * const config_element_output_type;
-LTTNG_EXPORT extern const char * const config_element_tracefile_size;
-LTTNG_EXPORT extern const char * const config_element_tracefile_count;
-LTTNG_EXPORT extern const char * const config_element_live_timer_interval;
-extern const char * const config_element_discarded_events;
-extern const char * const config_element_lost_packets;
-LTTNG_EXPORT extern const char * const config_element_type;
-LTTNG_EXPORT extern const char * const config_element_buffer_type;
-LTTNG_EXPORT extern const char * const config_element_session;
-LTTNG_EXPORT extern const char * const config_element_sessions;
-extern const char * const config_element_context_perf;
-extern const char * const config_element_context_app;
-extern const char * const config_element_context_app_provider_name;
-extern const char * const config_element_context_app_ctx_name;
-LTTNG_EXPORT extern const char * const config_element_config;
-LTTNG_EXPORT extern const char * const config_element_started;
-LTTNG_EXPORT extern const char * const config_element_snapshot_mode;
-LTTNG_EXPORT extern const char * const config_element_loglevel;
-LTTNG_EXPORT extern const char * const config_element_loglevel_type;
-LTTNG_EXPORT extern const char * const config_element_filter;
-extern const char * const config_element_filter_expression;
-LTTNG_EXPORT extern const char * const config_element_snapshot_outputs;
-LTTNG_EXPORT extern const char * const config_element_consumer_output;
-LTTNG_EXPORT extern const char * const config_element_destination;
-LTTNG_EXPORT extern const char * const config_element_path;
-LTTNG_EXPORT extern const char * const config_element_net_output;
-LTTNG_EXPORT extern const char * const config_element_control_uri;
-LTTNG_EXPORT extern const char * const config_element_data_uri;
-LTTNG_EXPORT extern const char * const config_element_max_size;
-LTTNG_EXPORT extern const char * const config_element_pid;
-extern const char * const config_element_process_attr_id;
-LTTNG_EXPORT extern const char * const config_element_pids;
-LTTNG_EXPORT extern const char * const config_element_name;
-LTTNG_EXPORT extern const char * const config_element_shared_memory_path;
-extern const char * const config_element_process_attr_tracker_pid;
-extern const char * const config_element_process_attr_tracker_vpid;
-extern const char * const config_element_process_attr_tracker_uid;
-extern const char * const config_element_process_attr_tracker_vuid;
-extern const char * const config_element_process_attr_tracker_gid;
-extern const char * const config_element_process_attr_tracker_vgid;
-extern const char * const config_element_process_attr_trackers;
-extern const char * const config_element_process_attr_values;
-extern const char * const config_element_process_attr_value_type;
-extern const char * const config_element_process_attr_pid_value;
-extern const char * const config_element_process_attr_vpid_value;
-extern const char * const config_element_process_attr_uid_value;
-extern const char * const config_element_process_attr_vuid_value;
-extern const char * const config_element_process_attr_gid_value;
-extern const char * const config_element_process_attr_vgid_value;
-extern const char * const config_element_process_attr_tracker_type;
-extern const char * const config_element_rotation_timer_interval;
-extern const char * const config_element_rotation_size;
-extern const char * const config_element_rotation_schedule;
-
-LTTNG_EXPORT extern const char * const config_domain_type_kernel;
-LTTNG_EXPORT extern const char * const config_domain_type_ust;
-LTTNG_EXPORT extern const char * const config_domain_type_jul;
-LTTNG_EXPORT extern const char * const config_domain_type_log4j;
-LTTNG_EXPORT extern const char * const config_domain_type_python;
-
-LTTNG_EXPORT extern const char * const config_buffer_type_per_pid;
-LTTNG_EXPORT extern const char * const config_buffer_type_per_uid;
-LTTNG_EXPORT extern const char * const config_buffer_type_global;
-
-LTTNG_EXPORT extern const char * const config_overwrite_mode_discard;
-LTTNG_EXPORT extern const char * const config_overwrite_mode_overwrite;
-
-LTTNG_EXPORT extern const char * const config_output_type_splice;
-LTTNG_EXPORT extern const char * const config_output_type_mmap;
-
-LTTNG_EXPORT extern const char * const config_loglevel_type_all;
-LTTNG_EXPORT extern const char * const config_loglevel_type_range;
-LTTNG_EXPORT extern const char * const config_loglevel_type_single;
-
-LTTNG_EXPORT extern const char * const config_event_type_all;
-LTTNG_EXPORT extern const char * const config_event_type_tracepoint;
-LTTNG_EXPORT extern const char * const config_event_type_probe;
-extern const char * const config_event_type_userspace_probe;
-LTTNG_EXPORT extern const char * const config_event_type_function;
-LTTNG_EXPORT extern const char * const config_event_type_function_entry;
-LTTNG_EXPORT extern const char * const config_event_type_noop;
-LTTNG_EXPORT extern const char * const config_event_type_syscall;
-LTTNG_EXPORT extern const char * const config_event_type_kprobe;
-LTTNG_EXPORT extern const char * const config_event_type_kretprobe;
-
-LTTNG_EXPORT extern const char * const config_event_context_pid;
-LTTNG_EXPORT extern const char * const config_event_context_procname;
-LTTNG_EXPORT extern const char * const config_event_context_prio;
-LTTNG_EXPORT extern const char * const config_event_context_nice;
-LTTNG_EXPORT extern const char * const config_event_context_vpid;
-LTTNG_EXPORT extern const char * const config_event_context_tid;
-LTTNG_EXPORT extern const char * const config_event_context_vtid;
-LTTNG_EXPORT extern const char * const config_event_context_ppid;
-LTTNG_EXPORT extern const char * const config_event_context_vppid;
-LTTNG_EXPORT extern const char * const config_event_context_pthread_id;
-LTTNG_EXPORT extern const char * const config_event_context_hostname;
-LTTNG_EXPORT extern const char * const config_event_context_ip;
-LTTNG_EXPORT extern const char * const config_event_context_perf_thread_counter;
-extern const char * const config_event_context_app;
-extern const char * const config_event_context_interruptible;
-extern const char * const config_event_context_preemptible;
-extern const char * const config_event_context_need_reschedule;
-extern const char * const config_event_context_migratable;
-extern const char * const config_event_context_callstack_user;
-extern const char * const config_event_context_callstack_kernel;
-
-extern const char * const config_element_rotation_schedules;
-extern const char * const config_element_rotation_schedule_periodic;
-extern const char * const config_element_rotation_schedule_periodic_time_us;
-extern const char * const config_element_rotation_schedule_size_threshold;
-extern const char * const config_element_rotation_schedule_size_threshold_bytes;
-extern const char * const config_event_context_cgroup_ns;
-extern const char * const config_event_context_ipc_ns;
-extern const char * const config_event_context_mnt_ns;
-extern const char * const config_event_context_net_ns;
-extern const char * const config_event_context_pid_ns;
-extern const char * const config_event_context_time_ns;
-extern const char * const config_event_context_user_ns;
-extern const char * const config_event_context_uts_ns;
-extern const char * const config_event_context_uid;
-extern const char * const config_event_context_euid;
-extern const char * const config_event_context_suid;
-extern const char * const config_event_context_gid;
-extern const char * const config_event_context_egid;
-extern const char * const config_event_context_sgid;
-extern const char * const config_event_context_vuid;
-extern const char * const config_event_context_veuid;
-extern const char * const config_event_context_vsuid;
-extern const char * const config_event_context_vgid;
-extern const char * const config_event_context_vegid;
-extern const char * const config_event_context_vsgid;
-
-#endif /* CONFIG_SESSION_INTERNAL_H */
diff --git a/src/common/config/config-session-abi.hpp b/src/common/config/config-session-abi.hpp
new file mode 100644 (file)
index 0000000..6c903ef
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef CONFIG_SESSION_INTERNAL_H
+#define CONFIG_SESSION_INTERNAL_H
+
+#include <lttng/lttng-export.h>
+
+extern const char * const config_element_all;
+LTTNG_EXPORT extern const char * const config_element_channel;
+LTTNG_EXPORT extern const char * const config_element_channels;
+LTTNG_EXPORT extern const char * const config_element_domain;
+LTTNG_EXPORT extern const char * const config_element_domains;
+LTTNG_EXPORT extern const char * const config_element_event;
+LTTNG_EXPORT extern const char * const config_element_events;
+LTTNG_EXPORT extern const char * const config_element_context;
+LTTNG_EXPORT extern const char * const config_element_contexts;
+LTTNG_EXPORT extern const char * const config_element_attributes;
+LTTNG_EXPORT extern const char * const config_element_exclusion;
+LTTNG_EXPORT extern const char * const config_element_exclusions;
+LTTNG_EXPORT extern const char * const config_element_function_attributes;
+LTTNG_EXPORT extern const char * const config_element_probe_attributes;
+LTTNG_EXPORT extern const char * const config_element_symbol_name;
+LTTNG_EXPORT extern const char * const config_element_address;
+LTTNG_EXPORT extern const char * const config_element_offset;
+extern const char * const config_element_userspace_probe_lookup;
+extern const char * const config_element_userspace_probe_lookup_function_default;
+extern const char * const config_element_userspace_probe_lookup_function_elf;
+extern const char * const config_element_userspace_probe_lookup_tracepoint_sdt;
+extern const char * const config_element_userspace_probe_location_binary_path;
+extern const char * const config_element_userspace_probe_function_attributes;
+extern const char * const config_element_userspace_probe_function_location_function_name;
+extern const char * const config_element_userspace_probe_tracepoint_attributes;
+extern const char * const config_element_userspace_probe_tracepoint_location_provider_name;
+extern const char * const config_element_userspace_probe_tracepoint_location_probe_name;
+extern const char * const config_element_name;
+LTTNG_EXPORT extern const char * const config_element_enabled;
+LTTNG_EXPORT extern const char * const config_element_overwrite_mode;
+LTTNG_EXPORT extern const char * const config_element_subbuf_size;
+LTTNG_EXPORT extern const char * const config_element_num_subbuf;
+LTTNG_EXPORT extern const char * const config_element_switch_timer_interval;
+LTTNG_EXPORT extern const char * const config_element_read_timer_interval;
+extern const char * const config_element_monitor_timer_interval;
+extern const char * const config_element_blocking_timeout;
+LTTNG_EXPORT extern const char * const config_element_output;
+LTTNG_EXPORT extern const char * const config_element_output_type;
+LTTNG_EXPORT extern const char * const config_element_tracefile_size;
+LTTNG_EXPORT extern const char * const config_element_tracefile_count;
+LTTNG_EXPORT extern const char * const config_element_live_timer_interval;
+extern const char * const config_element_discarded_events;
+extern const char * const config_element_lost_packets;
+LTTNG_EXPORT extern const char * const config_element_type;
+LTTNG_EXPORT extern const char * const config_element_buffer_type;
+LTTNG_EXPORT extern const char * const config_element_session;
+LTTNG_EXPORT extern const char * const config_element_sessions;
+extern const char * const config_element_context_perf;
+extern const char * const config_element_context_app;
+extern const char * const config_element_context_app_provider_name;
+extern const char * const config_element_context_app_ctx_name;
+LTTNG_EXPORT extern const char * const config_element_config;
+LTTNG_EXPORT extern const char * const config_element_started;
+LTTNG_EXPORT extern const char * const config_element_snapshot_mode;
+LTTNG_EXPORT extern const char * const config_element_loglevel;
+LTTNG_EXPORT extern const char * const config_element_loglevel_type;
+LTTNG_EXPORT extern const char * const config_element_filter;
+extern const char * const config_element_filter_expression;
+LTTNG_EXPORT extern const char * const config_element_snapshot_outputs;
+LTTNG_EXPORT extern const char * const config_element_consumer_output;
+LTTNG_EXPORT extern const char * const config_element_destination;
+LTTNG_EXPORT extern const char * const config_element_path;
+LTTNG_EXPORT extern const char * const config_element_net_output;
+LTTNG_EXPORT extern const char * const config_element_control_uri;
+LTTNG_EXPORT extern const char * const config_element_data_uri;
+LTTNG_EXPORT extern const char * const config_element_max_size;
+LTTNG_EXPORT extern const char * const config_element_pid;
+extern const char * const config_element_process_attr_id;
+LTTNG_EXPORT extern const char * const config_element_pids;
+LTTNG_EXPORT extern const char * const config_element_name;
+LTTNG_EXPORT extern const char * const config_element_shared_memory_path;
+extern const char * const config_element_process_attr_tracker_pid;
+extern const char * const config_element_process_attr_tracker_vpid;
+extern const char * const config_element_process_attr_tracker_uid;
+extern const char * const config_element_process_attr_tracker_vuid;
+extern const char * const config_element_process_attr_tracker_gid;
+extern const char * const config_element_process_attr_tracker_vgid;
+extern const char * const config_element_process_attr_trackers;
+extern const char * const config_element_process_attr_values;
+extern const char * const config_element_process_attr_value_type;
+extern const char * const config_element_process_attr_pid_value;
+extern const char * const config_element_process_attr_vpid_value;
+extern const char * const config_element_process_attr_uid_value;
+extern const char * const config_element_process_attr_vuid_value;
+extern const char * const config_element_process_attr_gid_value;
+extern const char * const config_element_process_attr_vgid_value;
+extern const char * const config_element_process_attr_tracker_type;
+extern const char * const config_element_rotation_timer_interval;
+extern const char * const config_element_rotation_size;
+extern const char * const config_element_rotation_schedule;
+
+LTTNG_EXPORT extern const char * const config_domain_type_kernel;
+LTTNG_EXPORT extern const char * const config_domain_type_ust;
+LTTNG_EXPORT extern const char * const config_domain_type_jul;
+LTTNG_EXPORT extern const char * const config_domain_type_log4j;
+LTTNG_EXPORT extern const char * const config_domain_type_python;
+
+LTTNG_EXPORT extern const char * const config_buffer_type_per_pid;
+LTTNG_EXPORT extern const char * const config_buffer_type_per_uid;
+LTTNG_EXPORT extern const char * const config_buffer_type_global;
+
+LTTNG_EXPORT extern const char * const config_overwrite_mode_discard;
+LTTNG_EXPORT extern const char * const config_overwrite_mode_overwrite;
+
+LTTNG_EXPORT extern const char * const config_output_type_splice;
+LTTNG_EXPORT extern const char * const config_output_type_mmap;
+
+LTTNG_EXPORT extern const char * const config_loglevel_type_all;
+LTTNG_EXPORT extern const char * const config_loglevel_type_range;
+LTTNG_EXPORT extern const char * const config_loglevel_type_single;
+
+LTTNG_EXPORT extern const char * const config_event_type_all;
+LTTNG_EXPORT extern const char * const config_event_type_tracepoint;
+LTTNG_EXPORT extern const char * const config_event_type_probe;
+extern const char * const config_event_type_userspace_probe;
+LTTNG_EXPORT extern const char * const config_event_type_function;
+LTTNG_EXPORT extern const char * const config_event_type_function_entry;
+LTTNG_EXPORT extern const char * const config_event_type_noop;
+LTTNG_EXPORT extern const char * const config_event_type_syscall;
+LTTNG_EXPORT extern const char * const config_event_type_kprobe;
+LTTNG_EXPORT extern const char * const config_event_type_kretprobe;
+
+LTTNG_EXPORT extern const char * const config_event_context_pid;
+LTTNG_EXPORT extern const char * const config_event_context_procname;
+LTTNG_EXPORT extern const char * const config_event_context_prio;
+LTTNG_EXPORT extern const char * const config_event_context_nice;
+LTTNG_EXPORT extern const char * const config_event_context_vpid;
+LTTNG_EXPORT extern const char * const config_event_context_tid;
+LTTNG_EXPORT extern const char * const config_event_context_vtid;
+LTTNG_EXPORT extern const char * const config_event_context_ppid;
+LTTNG_EXPORT extern const char * const config_event_context_vppid;
+LTTNG_EXPORT extern const char * const config_event_context_pthread_id;
+LTTNG_EXPORT extern const char * const config_event_context_hostname;
+LTTNG_EXPORT extern const char * const config_event_context_ip;
+LTTNG_EXPORT extern const char * const config_event_context_perf_thread_counter;
+extern const char * const config_event_context_app;
+extern const char * const config_event_context_interruptible;
+extern const char * const config_event_context_preemptible;
+extern const char * const config_event_context_need_reschedule;
+extern const char * const config_event_context_migratable;
+extern const char * const config_event_context_callstack_user;
+extern const char * const config_event_context_callstack_kernel;
+
+extern const char * const config_element_rotation_schedules;
+extern const char * const config_element_rotation_schedule_periodic;
+extern const char * const config_element_rotation_schedule_periodic_time_us;
+extern const char * const config_element_rotation_schedule_size_threshold;
+extern const char * const config_element_rotation_schedule_size_threshold_bytes;
+extern const char * const config_event_context_cgroup_ns;
+extern const char * const config_event_context_ipc_ns;
+extern const char * const config_event_context_mnt_ns;
+extern const char * const config_event_context_net_ns;
+extern const char * const config_event_context_pid_ns;
+extern const char * const config_event_context_time_ns;
+extern const char * const config_event_context_user_ns;
+extern const char * const config_event_context_uts_ns;
+extern const char * const config_event_context_uid;
+extern const char * const config_event_context_euid;
+extern const char * const config_event_context_suid;
+extern const char * const config_event_context_gid;
+extern const char * const config_event_context_egid;
+extern const char * const config_event_context_sgid;
+extern const char * const config_event_context_vuid;
+extern const char * const config_event_context_veuid;
+extern const char * const config_event_context_vsuid;
+extern const char * const config_event_context_vgid;
+extern const char * const config_event_context_vegid;
+extern const char * const config_event_context_vsgid;
+
+#endif /* CONFIG_SESSION_INTERNAL_H */
index c1256985ad737f3374ccf6aefd43dd7cd4f9496f..32ff8e2f22fc45617387f50a05be77aa76a56ac5 100644 (file)
 #include <sys/stat.h>
 #include <stdbool.h>
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/utils.h>
-#include <common/dynamic-buffer.h>
-#include <common/compat/getenv.h>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/utils.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/compat/getenv.hpp>
 #include <lttng/lttng-error.h>
 #include <libxml/parser.h>
 #include <libxml/valid.h>
@@ -34,8 +34,8 @@
 #include <lttng/rotation.h>
 #include <lttng/userspace-probe.h>
 
-#include "session-config.h"
-#include "config-internal.h"
+#include "session-config.hpp"
+#include "config-internal.hpp"
 
 #define CONFIG_USERSPACE_PROBE_LOOKUP_METHOD_NAME_MAX_LEN 7
 
diff --git a/src/common/config/session-config.h b/src/common/config/session-config.h
deleted file mode 100644 (file)
index b97c5ad..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-
-#include <common/config/config-session-abi.h>
-#include <common/macros.h>
-#include <stdint.h>
-
-struct config_load_session_override_attr {
-       char *path_url;
-       char *ctrl_url;
-       char *data_url;
-       char *session_name;
-};
-
-/* Instance of a configuration writer. */
-struct config_writer;
-
-/*
- * Create an instance of a configuration writer.
- *
- * fd_output File to which the XML content must be written. fd_output is
- * owned by the caller.
- *
- * indent If other than 0 the XML will be pretty printed
- * with indentation and newline.
- *
- * Returns an instance of a configuration writer on success, NULL on
- * error.
- */
-struct config_writer *config_writer_create(int fd_output, int indent);
-
-/*
- * Destroy an instance of a configuration writer.
- *
- * writer An instance of a configuration writer.
- *
- * Returns zero if the XML document could be closed cleanly. Negative values
- * indicate an error.
- */
-int config_writer_destroy(struct config_writer *writer);
-
-/*
- * Open an element tag.
- *
- * writer An instance of a configuration writer.
- *
- * element_name Element tag name.
- *
- * Returns zero if the XML element could be opened.
- * Negative values indicate an error.
- */
-int config_writer_open_element(struct config_writer *writer,
-               const char *element_name);
-
-/*
- * Write an element tag attribute.
- *
- * writer An instance of a configuration writer.
- *
- * name Attribute name.
- *
- * Returns zero if the XML element's attribute could be written.
- * Negative values indicate an error.
- */
-int config_writer_write_attribute(struct config_writer *writer,
-               const char *name, const char *value);
-
-/*
- * Close the current element tag.
- *
- * writer An instance of a configuration writer.
- *
- * Returns zero if the XML document could be closed cleanly.
- * Negative values indicate an error.
- */
-int config_writer_close_element(struct config_writer *writer);
-
-/*
- * Write an element of type unsigned int.
- *
- * writer An instance of a configuration writer.
- *
- * element_name Element name.
- *
- * value Unsigned int value of the element
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int config_writer_write_element_unsigned_int(struct config_writer *writer,
-               const char *element_name, uint64_t value);
-
-/*
- * Write an element of type signed int.
- *
- * writer An instance of a configuration writer.
- *
- * element_name Element name.
- *
- * value Signed int value of the element
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int config_writer_write_element_signed_int(struct config_writer *writer,
-               const char *element_name, int64_t value);
-
-/*
- * Write an element of type boolean.
- *
- * writer An instance of a configuration writer.
- *
- * element_name Element name.
- *
- * value Boolean value of the element
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int config_writer_write_element_bool(struct config_writer *writer,
-               const char *element_name, int value);
-
-/*
- * Write an element of type string.
- *
- * writer An instance of a configuration writer.
- *
- * element_name Element name.
- *
- * value String value of the element
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int config_writer_write_element_string(struct config_writer *writer,
-               const char *element_name, const char *value);
-
-/*
- * Write an element of type double.
- *
- * writer An instance of a configuration writer.
- *
- * element_name Element name.
- *
- * value Double value of the element
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int config_writer_write_element_double(struct config_writer *writer,
-               const char *element_name,
-               double value);
-
-/*
- * Load session configurations from a file.
- *
- * path Path to an LTTng session configuration file. All *.lttng files
- * will be loaded if path is a directory. If path is NULL, the default
- * paths will be searched in the following order:
- *     1) $HOME/.lttng/sessions
- *     2) /etc/lttng/sessions
- *
- * session_name Name of the session to load. Will load all
- * sessions from path if NULL.
- *
- * overwrite Overwrite current session configuration if it exists.
- * autoload Tell to load the auto session(s).
- * overrides The override attribute structure specifying override parameters.
- *
- * Returns zero if the session could be loaded successfully. Returns
- * a negative LTTNG_ERR code on error.
- */
-int config_load_session(const char *path, const char *session_name,
-               int overwrite, unsigned int autoload,
-               const struct config_load_session_override_attr *overrides);
-
-#endif /* _CONFIG_H */
diff --git a/src/common/config/session-config.hpp b/src/common/config/session-config.hpp
new file mode 100644 (file)
index 0000000..66897ca
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+#include <common/config/config-session-abi.hpp>
+#include <common/macros.hpp>
+#include <stdint.h>
+
+struct config_load_session_override_attr {
+       char *path_url;
+       char *ctrl_url;
+       char *data_url;
+       char *session_name;
+};
+
+/* Instance of a configuration writer. */
+struct config_writer;
+
+/*
+ * Create an instance of a configuration writer.
+ *
+ * fd_output File to which the XML content must be written. fd_output is
+ * owned by the caller.
+ *
+ * indent If other than 0 the XML will be pretty printed
+ * with indentation and newline.
+ *
+ * Returns an instance of a configuration writer on success, NULL on
+ * error.
+ */
+struct config_writer *config_writer_create(int fd_output, int indent);
+
+/*
+ * Destroy an instance of a configuration writer.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * Returns zero if the XML document could be closed cleanly. Negative values
+ * indicate an error.
+ */
+int config_writer_destroy(struct config_writer *writer);
+
+/*
+ * Open an element tag.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * element_name Element tag name.
+ *
+ * Returns zero if the XML element could be opened.
+ * Negative values indicate an error.
+ */
+int config_writer_open_element(struct config_writer *writer,
+               const char *element_name);
+
+/*
+ * Write an element tag attribute.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * name Attribute name.
+ *
+ * Returns zero if the XML element's attribute could be written.
+ * Negative values indicate an error.
+ */
+int config_writer_write_attribute(struct config_writer *writer,
+               const char *name, const char *value);
+
+/*
+ * Close the current element tag.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int config_writer_close_element(struct config_writer *writer);
+
+/*
+ * Write an element of type unsigned int.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * element_name Element name.
+ *
+ * value Unsigned int value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int config_writer_write_element_unsigned_int(struct config_writer *writer,
+               const char *element_name, uint64_t value);
+
+/*
+ * Write an element of type signed int.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * element_name Element name.
+ *
+ * value Signed int value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int config_writer_write_element_signed_int(struct config_writer *writer,
+               const char *element_name, int64_t value);
+
+/*
+ * Write an element of type boolean.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * element_name Element name.
+ *
+ * value Boolean value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int config_writer_write_element_bool(struct config_writer *writer,
+               const char *element_name, int value);
+
+/*
+ * Write an element of type string.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * element_name Element name.
+ *
+ * value String value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int config_writer_write_element_string(struct config_writer *writer,
+               const char *element_name, const char *value);
+
+/*
+ * Write an element of type double.
+ *
+ * writer An instance of a configuration writer.
+ *
+ * element_name Element name.
+ *
+ * value Double value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int config_writer_write_element_double(struct config_writer *writer,
+               const char *element_name,
+               double value);
+
+/*
+ * Load session configurations from a file.
+ *
+ * path Path to an LTTng session configuration file. All *.lttng files
+ * will be loaded if path is a directory. If path is NULL, the default
+ * paths will be searched in the following order:
+ *     1) $HOME/.lttng/sessions
+ *     2) /etc/lttng/sessions
+ *
+ * session_name Name of the session to load. Will load all
+ * sessions from path if NULL.
+ *
+ * overwrite Overwrite current session configuration if it exists.
+ * autoload Tell to load the auto session(s).
+ * overrides The override attribute structure specifying override parameters.
+ *
+ * Returns zero if the session could be loaded successfully. Returns
+ * a negative LTTNG_ERR code on error.
+ */
+int config_load_session(const char *path, const char *session_name,
+               int overwrite, unsigned int autoload,
+               const struct config_load_session_override_attr *overrides);
+
+#endif /* _CONFIG_H */
diff --git a/src/common/config/session.xsd b/src/common/config/session.xsd
deleted file mode 100644 (file)
index 986fb2d..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
-
-SPDX-License-Identifier: MIT
-
--->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
-elementFormDefault="qualified" version="2.12">
-
-<xs:simpleType name="name_type">
-       <xs:restriction base="xs:string">
-               <xs:maxLength value="255"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<xs:simpleType name="uint64_type">
-       <xs:restriction base="xs:integer">
-               <xs:minInclusive value="0"/>
-               <xs:maxInclusive value="18446744073709551615"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<xs:simpleType name="uint32_type">
-       <xs:restriction base="xs:integer">
-               <xs:minInclusive value="0"/>
-               <xs:maxInclusive value="4294967295"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<!--
-Maps to the range allowed for blocking timeout: -1 (block forever),
-0 (do not block), positive integer value (blocking time in usec) limited
-by its signed 32-bit representation when converted to msec.
--->
-<xs:simpleType name="blocking_timeout_type">
-       <xs:restriction base="xs:integer">
-               <xs:minInclusive value="-1" />
-               <xs:maxInclusive value="2147483648000" />
-       </xs:restriction>
-</xs:simpleType>
-
-<xs:simpleType name="channel_overwrite_mode_type">
-       <xs:restriction base="xs:string">
-               <xs:enumeration value="DISCARD"/>
-               <xs:enumeration value="OVERWRITE"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<!-- Maps to the lttng_event_output enum -->
-<xs:simpleType name="event_output_type">
-       <xs:restriction base="xs:string">
-               <xs:enumeration value="SPLICE"/>
-               <xs:enumeration value="MMAP"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<!-- Maps to the lttng_loglevel_type enum -->
-<xs:simpleType name="loglevel_type">
-       <xs:restriction base="xs:string">
-               <xs:enumeration value="ALL"/>
-               <xs:enumeration value="RANGE"/>
-               <xs:enumeration value="SINGLE"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<!-- Maps to the lttng_event_type enum -->
-<xs:simpleType name="event_type_type">
-       <xs:restriction base="xs:string">
-               <xs:enumeration value="ALL"/>
-               <xs:enumeration value="TRACEPOINT"/>
-               <xs:enumeration value="PROBE"/>
-               <xs:enumeration value="USERSPACE_PROBE"/>
-               <xs:enumeration value="FUNCTION"/>
-               <xs:enumeration value="FUNCTION_ENTRY"/>
-               <xs:enumeration value="NOOP"/>
-               <xs:enumeration value="SYSCALL"/>
-               <xs:enumeration value="KPROBE"/>
-               <xs:enumeration value="KRETPROBE"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<xs:complexType name="event_probe_attributes_type">
-       <xs:all>
-               <xs:element name="symbol_name" type="name_type" minOccurs="0"/>
-               <xs:element name="address" type="uint64_type" minOccurs="0"/>
-               <xs:element name="offset" type="uint64_type" minOccurs="0"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:simpleType name="userspace_probe_lookup_method">
-       <xs:restriction base="xs:string">
-               <xs:enumeration value="DEFAULT"/>
-               <xs:enumeration value="ELF"/>
-               <xs:enumeration value="SDT"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<xs:complexType name="event_userspace_probe_function_attributes_type">
-       <xs:all>
-               <xs:element name="lookup_method" type="userspace_probe_lookup_method"/>
-               <xs:element name="binary_path" type="xs:string"/>
-               <xs:element name="function_name" type="xs:string"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="event_userspace_probe_tracepoint_attributes_type">
-       <xs:all>
-               <xs:element name="lookup_method" type="userspace_probe_lookup_method"/>
-               <xs:element name="binary_path" type="xs:string"/>
-               <xs:element name="probe_name" type="xs:string"/>
-               <xs:element name="provider_name" type="xs:string"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="event_ftrace_attributes_type">
-       <xs:all>
-               <xs:element name="symbol_name" type="name_type"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="event_attributes_type">
-       <xs:choice>
-               <xs:element name="probe_attributes" type="event_probe_attributes_type"/>
-               <xs:element name="function_attributes" type="event_ftrace_attributes_type"/>
-               <xs:element name="userspace_probe_function_attributes" type="event_userspace_probe_function_attributes_type"/>
-               <xs:element name="userspace_probe_tracepoint_attributes" type="event_userspace_probe_tracepoint_attributes_type"/>
-       </xs:choice>
-</xs:complexType>
-
-<xs:complexType name="event_exclusion_list_type">
-       <xs:sequence>
-               <xs:element name="exclusion" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
-       </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="event_type">
-       <xs:all>
-               <xs:element name="name" type="name_type" minOccurs="0"/>
-               <xs:element name="enabled" type="xs:boolean" default="true" minOccurs="0"/>
-               <xs:element name="type" type="event_type_type" default="TRACEPOINT" minOccurs="0"/>
-               <xs:element name="loglevel_type" type="loglevel_type" default="ALL" minOccurs="0"/>
-               <xs:element name="loglevel" type="xs:int" default="-1" minOccurs="0"/>
-               <xs:element name="filter" type="xs:string" minOccurs="0"/>
-               <xs:element name="exclusions" type="event_exclusion_list_type" minOccurs="0"/>
-               <xs:element name="attributes" type="event_attributes_type" minOccurs="0"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="event_list_type">
-       <xs:sequence>
-               <xs:element name="event" type="event_type" minOccurs="0" maxOccurs="unbounded"/>
-       </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="event_perf_context_type">
-       <xs:all>
-               <xs:element name="type" type="uint32_type"/>
-               <xs:element name="config" type="uint64_type"/>
-               <xs:element name="name" type="name_type"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="event_app_context_type">
-       <xs:all>
-         <xs:element name="provider_name" type="xs:string"/>
-         <xs:element name="ctx_name" type="xs:string"/>
-       </xs:all>
-</xs:complexType>
-
-<!-- Maps to the lttng_event_context_type enum -->
-<xs:simpleType name="event_context_type_type">
-       <xs:restriction base="xs:string">
-               <xs:enumeration value="PID"/>
-               <xs:enumeration value="PROCNAME"/>
-               <xs:enumeration value="PRIO"/>
-               <xs:enumeration value="NICE"/>
-               <xs:enumeration value="VPID"/>
-               <xs:enumeration value="TID"/>
-               <xs:enumeration value="VTID"/>
-               <xs:enumeration value="PPID"/>
-               <xs:enumeration value="VPPID"/>
-               <xs:enumeration value="PTHREAD_ID"/>
-               <xs:enumeration value="HOSTNAME"/>
-               <xs:enumeration value="IP"/>
-               <xs:enumeration value="APP"/>
-               <xs:enumeration value="INTERRUPTIBLE" />
-               <xs:enumeration value="PREEMPTIBLE" />
-               <xs:enumeration value="NEED_RESCHEDULE" />
-               <xs:enumeration value="MIGRATABLE" />
-               <xs:enumeration value="CALLSTACK_USER" />
-               <xs:enumeration value="CALLSTACK_KERNEL" />
-       </xs:restriction>
-</xs:simpleType>
-
-<xs:complexType name="event_context_type">
-       <xs:choice>
-               <xs:element name="type" type="event_context_type_type"/>
-               <xs:element name="perf" type="event_perf_context_type"/>
-               <xs:element name="app" type="event_app_context_type"/>
-       </xs:choice>
-</xs:complexType>
-
-<xs:complexType name="event_context_list_type">
-       <xs:sequence>
-               <xs:element name="context" type="event_context_type" minOccurs="0" maxOccurs="unbounded"/>
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to struct lttng_channel -->
-<xs:complexType name="channel_type">
-       <xs:all>
-               <xs:element name="name" type="name_type"/>
-               <xs:element name="enabled" type="xs:boolean" default="true" minOccurs="0"/>
-               <xs:element name="overwrite_mode" type="channel_overwrite_mode_type" default="DISCARD" minOccurs="0"/>
-               <xs:element name="subbuffer_size" type="uint64_type" minOccurs="0"/> <!-- bytes -->
-               <xs:element name="subbuffer_count" type="uint64_type" default="4" minOccurs="0"/>
-               <xs:element name="switch_timer_interval" type="uint32_type" default="0" minOccurs="0"/>  <!-- usec -->
-               <xs:element name="read_timer_interval" type="uint32_type"/>  <!-- usec -->
-               <xs:element name="blocking_timeout" type="blocking_timeout_type" default="0" minOccurs="0" /> <!-- usec -->
-               <xs:element name="output_type" type="event_output_type"/>
-               <xs:element name="tracefile_size" type="uint64_type" default="0" minOccurs="0"/> <!-- bytes -->
-               <xs:element name="tracefile_count" type="uint64_type" default="0" minOccurs="0"/>
-               <xs:element name="live_timer_interval" type="uint32_type" default="0" minOccurs="0"/> <!-- usec -->
-               <xs:element name="events" type="event_list_type" minOccurs="0"/>
-               <xs:element name="contexts" type="event_context_list_type" minOccurs="0"/>
-               <xs:element name="monitor_timer_interval" type="uint64_type" default="0" minOccurs="0"/>  <!-- usec -->
-       </xs:all>
-</xs:complexType>
-
-<!-- Maps to the lttng_domain_type enum -->
-<xs:simpleType name="domain_type_type">
-       <xs:restriction base="xs:string">
-               <xs:enumeration value="KERNEL"/>
-               <xs:enumeration value="UST"/>
-               <xs:enumeration value="JUL"/>
-               <xs:enumeration value="LOG4J"/>
-               <xs:enumeration value="PYTHON"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<!-- Maps to the lttng_buffer_type enum -->
-<xs:simpleType name="domain_buffer_type">
-       <xs:restriction base="xs:string">
-               <xs:enumeration value="PER_PID"/>
-               <xs:enumeration value="PER_UID"/>
-               <xs:enumeration value="GLOBAL"/>
-       </xs:restriction>
-</xs:simpleType>
-
-<xs:complexType name="channel_list_type">
-       <xs:sequence>
-               <xs:element name="channel" type="channel_type" minOccurs="0" maxOccurs="unbounded" />
-       </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="pid_value_type">
-       <xs:choice minOccurs="0">
-               <xs:element name="id" type="xs:integer" />
-       </xs:choice>
-</xs:complexType>
-
-<!-- Maps to a list of pid_process_attr_values-->
-<xs:complexType name="pid_process_attr_values_type">
-       <xs:sequence>
-               <xs:choice minOccurs="0" maxOccurs="unbounded" >
-                       <xs:element name="pid" type="pid_value_type" />
-               </xs:choice>
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to a pid_process_attr_tracker-->
-<xs:complexType name="pid_process_attr_tracker_type">
-       <xs:all>
-               <xs:element name="process_attr_values" type="pid_process_attr_values_type" />
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="vpid_value_type">
-       <xs:all>
-               <xs:element name="id" type="xs:integer" />
-       </xs:all>
-</xs:complexType>
-
-<!-- Maps to a list of vpid_process_attr_values-->
-<xs:complexType name="vpid_process_attr_values_type">
-       <xs:sequence>
-               <xs:element name="vpid" type="vpid_value_type" minOccurs="0" maxOccurs="unbounded" />
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to a pid_process_attr_tracker-->
-<xs:complexType name="vpid_process_attr_tracker_type">
-       <xs:all>
-               <xs:element name="process_attr_values" type="vpid_process_attr_values_type" />
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="uid_value_type">
-       <xs:choice>
-               <xs:element name="id" type="xs:integer" />
-               <xs:element name="name" type="xs:string" />
-       </xs:choice>
-</xs:complexType>
-
-<!-- Maps to a list of uid_process_attr_values-->
-<xs:complexType name="uid_process_attr_values_type">
-       <xs:sequence>
-               <xs:element name="uid" type="uid_value_type" minOccurs="0" maxOccurs="unbounded" />
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to a uid_process_attr_tracker-->
-<xs:complexType name="uid_process_attr_tracker_type">
-       <xs:all>
-               <xs:element name="process_attr_values" type="uid_process_attr_values_type" />
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="vuid_value_type">
-       <xs:choice>
-               <xs:element name="id" type="xs:integer" />
-               <xs:element name="name" type="xs:string" />
-       </xs:choice>
-</xs:complexType>
-
-<!-- Maps to a list of vuid_process_attr_values-->
-<xs:complexType name="vuid_process_attr_values_type">
-       <xs:sequence>
-               <xs:element name="vuid" type="vuid_value_type" minOccurs="0" maxOccurs="unbounded" />
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to a vuid_process_attr_tracker-->
-<xs:complexType name="vuid_process_attr_tracker_type">
-       <xs:all>
-               <xs:element name="process_attr_values" type="vuid_process_attr_values_type" />
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="gid_value_type">
-       <xs:choice>
-               <xs:element name="id" type="xs:integer" />
-               <xs:element name="name" type="xs:string" />
-       </xs:choice>
-</xs:complexType>
-
-<!-- Maps to a list of gid_process_attr_values-->
-<xs:complexType name="gid_process_attr_values_type">
-       <xs:sequence>
-               <xs:element name="gid" type="gid_value_type" minOccurs="0" maxOccurs="unbounded" />
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to a gid_process_attr_tracker-->
-<xs:complexType name="gid_process_attr_tracker_type">
-       <xs:all>
-               <xs:element name="process_attr_values" type="gid_process_attr_values_type" />
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="vgid_value_type">
-       <xs:choice>
-               <xs:element name="id" type="xs:integer" />
-               <xs:element name="name" type="xs:string" />
-       </xs:choice>
-</xs:complexType>
-
-<!-- Maps to a list of vgid_process_attr_values-->
-<xs:complexType name="vgid_process_attr_values_type">
-       <xs:sequence>
-               <xs:element name="vgid" type="vgid_value_type" minOccurs="0" maxOccurs="unbounded" />
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to a vgid_process_attr_tracker-->
-<xs:complexType name="vgid_process_attr_tracker_type">
-       <xs:all>
-               <xs:element name="process_attr_values" type="vgid_process_attr_values_type" />
-       </xs:all>
-</xs:complexType>
-
-<!-- Maps to a list of trackers-->
-<xs:complexType name="process_attr_tracker_type">
-       <xs:sequence>
-               <xs:choice minOccurs="0" maxOccurs="unbounded" >
-                       <xs:element name="pid_process_attr_tracker" type="pid_process_attr_tracker_type" maxOccurs="1" />
-                       <xs:element name="vpid_process_attr_tracker" type="vpid_process_attr_tracker_type" maxOccurs="1" />
-                       <xs:element name="uid_process_attr_tracker" type="uid_process_attr_tracker_type" maxOccurs="1" />
-                       <xs:element name="vuid_process_attr_tracker" type="vuid_process_attr_tracker_type" maxOccurs="1" />
-                       <xs:element name="gid_process_attr_tracker" type="gid_process_attr_tracker_type" maxOccurs="1" />
-                       <xs:element name="vgid_process_attr_tracker" type="vgid_process_attr_tracker_type" maxOccurs="1" />
-               </xs:choice>
-       </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="pid_target_type">
-       <xs:all>
-               <xs:element name="pid" type="xs:integer" />
-       </xs:all>
-</xs:complexType>
-
-<!-- Maps to a list of pid_targets (legacy)-->
-<xs:complexType name="targets_type">
-       <xs:sequence>
-               <xs:choice>
-                       <xs:element name="pid_target" type="pid_target_type" minOccurs="0" maxOccurs="unbounded" />
-               </xs:choice>
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to a pid_tracker (legacy)-->
-<xs:complexType name="pid_tracker_type">
-       <xs:all>
-               <xs:element name="targets" type="targets_type" />
-       </xs:all>
-</xs:complexType>
-
-<!-- Maps to a list of trackers (legacy)-->
-<xs:complexType name="trackers_type">
-       <xs:sequence minOccurs="0" maxOccurs="unbounded">
-               <xs:element name="pid_tracker" type="pid_tracker_type" maxOccurs="1" />
-       </xs:sequence>
-</xs:complexType>
-
-<!-- Maps to struct lttng_domain, contains channels and pid_process_attr_tracker -->
-<xs:complexType name="domain_type">
-       <xs:all>
-               <xs:element name="type" type="domain_type_type"/>
-               <xs:element name="buffer_type" type="domain_buffer_type"/>
-               <xs:element name="channels" type="channel_list_type" minOccurs="0"/>
-               <xs:element name="process_attr_trackers" type="process_attr_tracker_type" minOccurs="0"/>
-               <!-- Support of legacy tracker specification -->
-               <xs:element name="trackers" type="trackers_type" minOccurs="0"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="periodic_rotation_schedule_type">
-       <xs:all>
-               <xs:element name="time_us" type="uint64_type" minOccurs="0" />
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="size_threshold_rotation_schedule_type">
-       <xs:all>
-               <xs:element name="bytes" type="uint64_type" minOccurs="0" />
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="rotation_schedule_type">
-       <xs:sequence>
-               <xs:choice maxOccurs="unbounded">
-                       <xs:element name="periodic" type="periodic_rotation_schedule_type" maxOccurs="unbounded" />
-                       <xs:element name="size_threshold" type="size_threshold_rotation_schedule_type" maxOccurs="unbounded" />
-               </xs:choice>
-       </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="session_attributes_type">
-       <xs:all>
-               <xs:element name="snapshot_mode" type="xs:boolean" minOccurs="0"/>
-               <xs:element name="live_timer_interval" type="uint32_type" minOccurs="0"/> <!-- usec -->
-               <xs:element name="rotation_schedules" type="rotation_schedule_type" minOccurs="0" />
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="domain_list_type">
-       <xs:sequence>
-               <xs:element name="domain" type="domain_type" minOccurs="0" maxOccurs="unbounded"/>
-       </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="net_output_type">
-       <xs:all>
-               <xs:element name="control_uri" type="xs:string"/>
-               <xs:element name="data_uri" type="xs:string"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="destination_type">
-       <xs:choice>
-               <xs:element name="path" type="xs:string"/>
-               <xs:element name="net_output" type="net_output_type"/>
-       </xs:choice>
-</xs:complexType>
-
-<xs:complexType name="consumer_output_type">
-       <xs:all>
-               <xs:element name="enabled" type="xs:boolean" default="true"/>
-               <xs:element name="destination" type="destination_type"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="snapshot_output_type">
-       <xs:all>
-               <xs:element name="name" type="name_type"/>
-               <xs:element name="max_size" type="uint64_type"/>
-               <xs:element name="consumer_output" type="consumer_output_type"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:complexType name="snapshot_output_list_type">
-       <xs:sequence>
-               <xs:element name="output" type="snapshot_output_type" minOccurs="0" maxOccurs="unbounded"/>
-       </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="session_output_type">
-       <xs:choice>
-               <xs:element name="snapshot_outputs" type="snapshot_output_list_type"/>
-               <xs:element name="consumer_output" type="consumer_output_type"/>
-       </xs:choice>
-</xs:complexType>
-
-<xs:complexType name="session_type">
-       <xs:all>
-               <xs:element name="name" type="name_type"/>
-               <xs:element name="shared_memory_path" type="xs:string" minOccurs="0"/>
-               <xs:element name="domains" type="domain_list_type" minOccurs="0"/>
-               <xs:element name="started" type="xs:boolean" default="0" minOccurs="0"/>
-               <xs:element name="attributes" type="session_attributes_type" minOccurs="0"/>
-               <xs:element name="output" type="session_output_type" minOccurs="0"/>
-       </xs:all>
-</xs:complexType>
-
-<xs:element name="sessions">
-       <xs:complexType>
-               <xs:sequence>
-                       <xs:element name="session" type="session_type" maxOccurs="unbounded"/>
-               </xs:sequence>
-       </xs:complexType>
-</xs:element>
-
-</xs:schema>
diff --git a/src/common/consumer/Makefile.am b/src/common/consumer/Makefile.am
deleted file mode 100644 (file)
index ba3ecf1..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libconsumer.la
-
-noinst_HEADERS = consumer-metadata-cache.h consumer-timer.h \
-                consumer-testpoint.h
-
-libconsumer_la_SOURCES = \
-       consumer.cpp \
-       consumer.h \
-       consumer-metadata-cache.cpp \
-       consumer-stream.cpp \
-       consumer-stream.h \
-       consumer-timer.cpp \
-       metadata-bucket.cpp \
-       metadata-bucket.h
-
-libconsumer_la_LIBADD = \
-               $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \
-               $(top_builddir)/src/common/kernel-consumer/libkernel-consumer.la \
-               $(top_builddir)/src/common/hashtable/libhashtable.la \
-               $(top_builddir)/src/common/compat/libcompat.la \
-               $(top_builddir)/src/common/relayd/librelayd.la
-
-if HAVE_LIBLTTNG_UST_CTL
-libconsumer_la_LIBADD += \
-               $(top_builddir)/src/common/ust-consumer/libust-consumer.la
-endif
index fdda6be8b5f4027a94cb14597a0a8f2aa855764f..a810c7dab9eea84bbac194d6f1afa304603ee100 100644 (file)
 #include <unistd.h>
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/utils.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/ust-consumer/ust-consumer.h>
-#include <common/consumer/consumer.h>
+#include <common/common.hpp>
+#include <common/utils.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/ust-consumer/ust-consumer.hpp>
+#include <common/consumer/consumer.hpp>
 
-#include "consumer-metadata-cache.h"
+#include "consumer-metadata-cache.hpp"
 
 enum metadata_cache_update_version_status {
        METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED,
diff --git a/src/common/consumer/consumer-metadata-cache.h b/src/common/consumer/consumer-metadata-cache.h
deleted file mode 100644 (file)
index b8f4efa..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef CONSUMER_METADATA_CACHE_H
-#define CONSUMER_METADATA_CACHE_H
-
-#include <common/consumer/consumer.h>
-#include <common/dynamic-buffer.h>
-
-enum consumer_metadata_cache_write_status {
-       CONSUMER_METADATA_CACHE_WRITE_STATUS_ERROR = -1,
-       /*
-        * New metadata content was appended to the cache successfully.
-        * Previously available content remains valid.
-        */
-       CONSUMER_METADATA_CACHE_WRITE_STATUS_APPENDED_CONTENT = 0,
-       /*
-        * The new content pushed to the cache invalidated the content that
-        * was already present. The contents of the cache should be re-read.
-        */
-       CONSUMER_METADATA_CACHE_WRITE_STATUS_INVALIDATED,
-       /*
-        * A metadata cache write can simply overwrite an already existing
-        * section of the cache (and it should be a write-through with identical
-        * data). From the caller's standpoint, there is no change to the state
-        * of the cache.
-        */
-       CONSUMER_METADATA_CACHE_WRITE_STATUS_NO_CHANGE,
-};
-
-struct consumer_metadata_cache {
-       /* Current version of the metadata cache. */
-       uint64_t version;
-       /*
-        * Size is the upper-limit of data written inside the buffer.
-        * All cached data is contiguous.
-        */
-       struct lttng_dynamic_buffer contents;
-       /*
-        * Lock to update the metadata cache and push into the ring_buffer
-        * (lttng_ust_ctl_write_metadata_to_channel).
-        *
-        * This is nested INSIDE the consumer_data lock.
-        */
-       pthread_mutex_t lock;
-};
-
-enum consumer_metadata_cache_write_status
-consumer_metadata_cache_write(struct consumer_metadata_cache *cache,
-               unsigned int offset, unsigned int len, uint64_t version,
-               const char *data);
-int consumer_metadata_cache_allocate(struct lttng_consumer_channel *channel);
-void consumer_metadata_cache_destroy(struct lttng_consumer_channel *channel);
-int consumer_metadata_cache_flushed(struct lttng_consumer_channel *channel,
-               uint64_t offset, int timer);
-
-#endif /* CONSUMER_METADATA_CACHE_H */
diff --git a/src/common/consumer/consumer-metadata-cache.hpp b/src/common/consumer/consumer-metadata-cache.hpp
new file mode 100644 (file)
index 0000000..6e60e5c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef CONSUMER_METADATA_CACHE_H
+#define CONSUMER_METADATA_CACHE_H
+
+#include <common/consumer/consumer.hpp>
+#include <common/dynamic-buffer.hpp>
+
+enum consumer_metadata_cache_write_status {
+       CONSUMER_METADATA_CACHE_WRITE_STATUS_ERROR = -1,
+       /*
+        * New metadata content was appended to the cache successfully.
+        * Previously available content remains valid.
+        */
+       CONSUMER_METADATA_CACHE_WRITE_STATUS_APPENDED_CONTENT = 0,
+       /*
+        * The new content pushed to the cache invalidated the content that
+        * was already present. The contents of the cache should be re-read.
+        */
+       CONSUMER_METADATA_CACHE_WRITE_STATUS_INVALIDATED,
+       /*
+        * A metadata cache write can simply overwrite an already existing
+        * section of the cache (and it should be a write-through with identical
+        * data). From the caller's standpoint, there is no change to the state
+        * of the cache.
+        */
+       CONSUMER_METADATA_CACHE_WRITE_STATUS_NO_CHANGE,
+};
+
+struct consumer_metadata_cache {
+       /* Current version of the metadata cache. */
+       uint64_t version;
+       /*
+        * Size is the upper-limit of data written inside the buffer.
+        * All cached data is contiguous.
+        */
+       struct lttng_dynamic_buffer contents;
+       /*
+        * Lock to update the metadata cache and push into the ring_buffer
+        * (lttng_ust_ctl_write_metadata_to_channel).
+        *
+        * This is nested INSIDE the consumer_data lock.
+        */
+       pthread_mutex_t lock;
+};
+
+enum consumer_metadata_cache_write_status
+consumer_metadata_cache_write(struct consumer_metadata_cache *cache,
+               unsigned int offset, unsigned int len, uint64_t version,
+               const char *data);
+int consumer_metadata_cache_allocate(struct lttng_consumer_channel *channel);
+void consumer_metadata_cache_destroy(struct lttng_consumer_channel *channel);
+int consumer_metadata_cache_flushed(struct lttng_consumer_channel *channel,
+               uint64_t offset, int timer);
+
+#endif /* CONSUMER_METADATA_CACHE_H */
index f9807cb0173f4bf6f4a7c0e9f838afb4631c16ec..09aba5625e320dc7b9df2bbf8a35e747473725ee 100644 (file)
 #include <sys/mman.h>
 #include <unistd.h>
 
-#include <common/common.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/consumer/consumer.h>
-#include <common/consumer/consumer.h>
-#include <common/consumer/metadata-bucket.h>
-#include <common/consumer/metadata-bucket.h>
-#include <common/index/index.h>
-#include <common/kernel-consumer/kernel-consumer.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/macros.h>
-#include <common/relayd/relayd.h>
-#include <common/ust-consumer/ust-consumer.h>
-#include <common/utils.h>
-
-#include "consumer-stream.h"
+#include <common/common.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/consumer/metadata-bucket.hpp>
+#include <common/consumer/metadata-bucket.hpp>
+#include <common/index/index.hpp>
+#include <common/kernel-consumer/kernel-consumer.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/macros.hpp>
+#include <common/relayd/relayd.hpp>
+#include <common/ust-consumer/ust-consumer.hpp>
+#include <common/utils.hpp>
+
+#include "consumer-stream.hpp"
 
 /*
  * RCU call to free stream. MUST only be used with call_rcu().
diff --git a/src/common/consumer/consumer-stream.h b/src/common/consumer/consumer-stream.h
deleted file mode 100644 (file)
index c9af63c..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_CONSUMER_STREAM_H
-#define LTTNG_CONSUMER_STREAM_H
-
-#include "consumer.h"
-
-enum consumer_stream_open_packet_status {
-       CONSUMER_STREAM_OPEN_PACKET_STATUS_OPENED,
-       CONSUMER_STREAM_OPEN_PACKET_STATUS_NO_SPACE,
-       CONSUMER_STREAM_OPEN_PACKET_STATUS_ERROR,
-};
-
-/*
- * Create a consumer stream.
- *
- * The channel lock MUST be acquired.
- */
-struct lttng_consumer_stream *consumer_stream_create(
-               struct lttng_consumer_channel *channel,
-               uint64_t channel_key,
-               uint64_t stream_key,
-               const char *channel_name,
-               uint64_t relayd_id,
-               uint64_t session_id,
-               struct lttng_trace_chunk *trace_chunk,
-               int cpu,
-               int *alloc_ret,
-               enum consumer_channel_type type,
-               unsigned int monitor);
-
-/*
- * Close stream's file descriptors and, if needed, close stream also on the
- * relayd side.
- *
- * The stream lock MUST be acquired.
- * The consumer data lock MUST be acquired.
- */
-void consumer_stream_close(struct lttng_consumer_stream *stream);
-
-/*
- * Close stream on the relayd side. This call can destroy a relayd if the
- * conditions are met.
- *
- * A RCU read side lock MUST be acquired if the relayd object was looked up in
- * a hash table before calling this.
- */
-void consumer_stream_relayd_close(struct lttng_consumer_stream *stream,
-               struct consumer_relayd_sock_pair *relayd);
-
-/*
- * Delete the stream from all possible hash tables.
- *
- * The consumer data lock MUST be acquired.
- */
-void consumer_stream_delete(struct lttng_consumer_stream *stream,
-               struct lttng_ht *ht);
-
-/*
- * Free the given stream within a RCU call.
- */
-void consumer_stream_free(struct lttng_consumer_stream *stream);
-
-/*
- * Destroy a stream completely. This will delete, close and free the stream.
- * Once return, the stream is NO longer usable. Its channel may get destroyed
- * if conditions are met.
- *
- * This MUST be called WITHOUT the consumer data and stream lock acquired.
- */
-void consumer_stream_destroy(struct lttng_consumer_stream *stream,
-               struct lttng_ht *ht);
-
-/*
- * Destroy the stream's buffers on the tracer side. This is also called in a
- * stream destroy.
- */
-void consumer_stream_destroy_buffers(struct lttng_consumer_stream *stream);
-
-/*
- * Write index of a specific stream either on the relayd or local disk.
- */
-int consumer_stream_write_index(struct lttng_consumer_stream *stream,
-               struct ctf_packet_index *index);
-
-int consumer_stream_sync_metadata(struct lttng_consumer_local_data *ctx,
-               uint64_t session_id);
-
-/*
- * Create the output files of a local stream.
- *
- * This must be called with the channel's and the stream's lock held.
- */
-int consumer_stream_create_output_files(struct lttng_consumer_stream *stream,
-               bool create_index);
-
-/*
- * Rotate the output files of a local stream. This will change the
- * active output files of both the binary and index in accordance
- * with the stream's configuration (stream file count).
- *
- * This must be called with the channel's and the stream's lock held.
- */
-int consumer_stream_rotate_output_files(struct lttng_consumer_stream *stream);
-
-/*
- * Indicates whether or not a stream is logically deleted. A deleted stream
- * should no longer be used; its existence is only garanteed by the RCU lock
- * held by the caller.
- *
- * This function must be called with the RCU read side lock held.
- */
-bool consumer_stream_is_deleted(struct lttng_consumer_stream *stream);
-
-/*
- * Enable metadata bucketization. This must only be enabled if the tracer
- * provides a reliable metadata `coherent` flag.
- *
- * This must be called on initialization before any subbuffer is consumed.
- */
-int consumer_stream_enable_metadata_bucketization(
-               struct lttng_consumer_stream *stream);
-
-/*
- * Set the version of a metadata stream (i.e. following a metadata
- * regeneration).
- *
- * Changing the version of a metadata stream will cause any bucketized metadata
- * to be discarded and will mark the metadata stream for future `reset`.
- */
-void consumer_stream_metadata_set_version(
-               struct lttng_consumer_stream *stream, uint64_t new_version);
-
-/*
- * Set the version of a metadata stream (i.e. following a metadata
- * regeneration).
- *
- * Changing the version of a metadata stream will cause any bucketized metadata
- * to be discarded and will mark the metadata stream for future `reset`.
- */
-void consumer_stream_metadata_set_version(
-               struct lttng_consumer_stream *stream, uint64_t new_version);
-
-/*
- * Attempt to open a packet in a stream.
- *
- * This function must be called with the stream and channel locks held.
- */
-enum consumer_stream_open_packet_status consumer_stream_open_packet(
-               struct lttng_consumer_stream *stream);
-
-/*
- * Flush a stream's buffer.
- *
- * producer_active: if true, causes a flush to occur only if there is
- * content present in the current sub-buffer. If false, forces a flush to take
- * place (otherwise known as "flush_empty").
- *
- * This function must be called with the stream and channel locks held.
- */
-int consumer_stream_flush_buffer(struct lttng_consumer_stream *stream,
-               bool producer_active);
-
-#endif /* LTTNG_CONSUMER_STREAM_H */
diff --git a/src/common/consumer/consumer-stream.hpp b/src/common/consumer/consumer-stream.hpp
new file mode 100644 (file)
index 0000000..a243ff5
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_CONSUMER_STREAM_H
+#define LTTNG_CONSUMER_STREAM_H
+
+#include "consumer.hpp"
+
+enum consumer_stream_open_packet_status {
+       CONSUMER_STREAM_OPEN_PACKET_STATUS_OPENED,
+       CONSUMER_STREAM_OPEN_PACKET_STATUS_NO_SPACE,
+       CONSUMER_STREAM_OPEN_PACKET_STATUS_ERROR,
+};
+
+/*
+ * Create a consumer stream.
+ *
+ * The channel lock MUST be acquired.
+ */
+struct lttng_consumer_stream *consumer_stream_create(
+               struct lttng_consumer_channel *channel,
+               uint64_t channel_key,
+               uint64_t stream_key,
+               const char *channel_name,
+               uint64_t relayd_id,
+               uint64_t session_id,
+               struct lttng_trace_chunk *trace_chunk,
+               int cpu,
+               int *alloc_ret,
+               enum consumer_channel_type type,
+               unsigned int monitor);
+
+/*
+ * Close stream's file descriptors and, if needed, close stream also on the
+ * relayd side.
+ *
+ * The stream lock MUST be acquired.
+ * The consumer data lock MUST be acquired.
+ */
+void consumer_stream_close(struct lttng_consumer_stream *stream);
+
+/*
+ * Close stream on the relayd side. This call can destroy a relayd if the
+ * conditions are met.
+ *
+ * A RCU read side lock MUST be acquired if the relayd object was looked up in
+ * a hash table before calling this.
+ */
+void consumer_stream_relayd_close(struct lttng_consumer_stream *stream,
+               struct consumer_relayd_sock_pair *relayd);
+
+/*
+ * Delete the stream from all possible hash tables.
+ *
+ * The consumer data lock MUST be acquired.
+ */
+void consumer_stream_delete(struct lttng_consumer_stream *stream,
+               struct lttng_ht *ht);
+
+/*
+ * Free the given stream within a RCU call.
+ */
+void consumer_stream_free(struct lttng_consumer_stream *stream);
+
+/*
+ * Destroy a stream completely. This will delete, close and free the stream.
+ * Once return, the stream is NO longer usable. Its channel may get destroyed
+ * if conditions are met.
+ *
+ * This MUST be called WITHOUT the consumer data and stream lock acquired.
+ */
+void consumer_stream_destroy(struct lttng_consumer_stream *stream,
+               struct lttng_ht *ht);
+
+/*
+ * Destroy the stream's buffers on the tracer side. This is also called in a
+ * stream destroy.
+ */
+void consumer_stream_destroy_buffers(struct lttng_consumer_stream *stream);
+
+/*
+ * Write index of a specific stream either on the relayd or local disk.
+ */
+int consumer_stream_write_index(struct lttng_consumer_stream *stream,
+               struct ctf_packet_index *index);
+
+int consumer_stream_sync_metadata(struct lttng_consumer_local_data *ctx,
+               uint64_t session_id);
+
+/*
+ * Create the output files of a local stream.
+ *
+ * This must be called with the channel's and the stream's lock held.
+ */
+int consumer_stream_create_output_files(struct lttng_consumer_stream *stream,
+               bool create_index);
+
+/*
+ * Rotate the output files of a local stream. This will change the
+ * active output files of both the binary and index in accordance
+ * with the stream's configuration (stream file count).
+ *
+ * This must be called with the channel's and the stream's lock held.
+ */
+int consumer_stream_rotate_output_files(struct lttng_consumer_stream *stream);
+
+/*
+ * Indicates whether or not a stream is logically deleted. A deleted stream
+ * should no longer be used; its existence is only garanteed by the RCU lock
+ * held by the caller.
+ *
+ * This function must be called with the RCU read side lock held.
+ */
+bool consumer_stream_is_deleted(struct lttng_consumer_stream *stream);
+
+/*
+ * Enable metadata bucketization. This must only be enabled if the tracer
+ * provides a reliable metadata `coherent` flag.
+ *
+ * This must be called on initialization before any subbuffer is consumed.
+ */
+int consumer_stream_enable_metadata_bucketization(
+               struct lttng_consumer_stream *stream);
+
+/*
+ * Set the version of a metadata stream (i.e. following a metadata
+ * regeneration).
+ *
+ * Changing the version of a metadata stream will cause any bucketized metadata
+ * to be discarded and will mark the metadata stream for future `reset`.
+ */
+void consumer_stream_metadata_set_version(
+               struct lttng_consumer_stream *stream, uint64_t new_version);
+
+/*
+ * Set the version of a metadata stream (i.e. following a metadata
+ * regeneration).
+ *
+ * Changing the version of a metadata stream will cause any bucketized metadata
+ * to be discarded and will mark the metadata stream for future `reset`.
+ */
+void consumer_stream_metadata_set_version(
+               struct lttng_consumer_stream *stream, uint64_t new_version);
+
+/*
+ * Attempt to open a packet in a stream.
+ *
+ * This function must be called with the stream and channel locks held.
+ */
+enum consumer_stream_open_packet_status consumer_stream_open_packet(
+               struct lttng_consumer_stream *stream);
+
+/*
+ * Flush a stream's buffer.
+ *
+ * producer_active: if true, causes a flush to occur only if there is
+ * content present in the current sub-buffer. If false, forces a flush to take
+ * place (otherwise known as "flush_empty").
+ *
+ * This function must be called with the stream and channel locks held.
+ */
+int consumer_stream_flush_buffer(struct lttng_consumer_stream *stream,
+               bool producer_active);
+
+#endif /* LTTNG_CONSUMER_STREAM_H */
diff --git a/src/common/consumer/consumer-testpoint.h b/src/common/consumer/consumer-testpoint.h
deleted file mode 100644 (file)
index 7373522..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef CONSUMERD_TESTPOINT_H
-#define CONSUMERD_TESTPOINT_H
-
-/*
- * Copyright (C) 2012 Christian Babeux <christian.babeux@efficios.com>
- * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <common/testpoint/testpoint.h>
-
-/* Testpoints, internal use only */
-TESTPOINT_DECL(consumerd_thread_channel);
-TESTPOINT_DECL(consumerd_thread_metadata);
-TESTPOINT_DECL(consumerd_thread_data);
-TESTPOINT_DECL(consumerd_thread_data_poll);
-TESTPOINT_DECL(consumerd_thread_sessiond);
-TESTPOINT_DECL(consumerd_thread_metadata_timer);
-
-#endif /* CONSUMERD_TESTPOINT_H */
diff --git a/src/common/consumer/consumer-testpoint.hpp b/src/common/consumer/consumer-testpoint.hpp
new file mode 100644 (file)
index 0000000..90b66a9
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef CONSUMERD_TESTPOINT_H
+#define CONSUMERD_TESTPOINT_H
+
+/*
+ * Copyright (C) 2012 Christian Babeux <christian.babeux@efficios.com>
+ * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <common/testpoint/testpoint.hpp>
+
+/* Testpoints, internal use only */
+TESTPOINT_DECL(consumerd_thread_channel);
+TESTPOINT_DECL(consumerd_thread_metadata);
+TESTPOINT_DECL(consumerd_thread_data);
+TESTPOINT_DECL(consumerd_thread_data_poll);
+TESTPOINT_DECL(consumerd_thread_sessiond);
+TESTPOINT_DECL(consumerd_thread_metadata_timer);
+
+#endif /* CONSUMERD_TESTPOINT_H */
index f6cb60c3b4e36912cc666709d29220e87fe1253a..80c7adfdf2045512f3c8d0b377ef14e67f359629 100644 (file)
 #include <inttypes.h>
 #include <signal.h>
 
-#include <bin/lttng-consumerd/health-consumerd.h>
-#include <common/common.h>
-#include <common/compat/endian.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/kernel-consumer/kernel-consumer.h>
-#include <common/consumer/consumer-stream.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/consumer/consumer-testpoint.h>
-#include <common/ust-consumer/ust-consumer.h>
+#include <bin/lttng-consumerd/health-consumerd.hpp>
+#include <common/common.hpp>
+#include <common/compat/endian.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/kernel-consumer/kernel-consumer.hpp>
+#include <common/consumer/consumer-stream.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/consumer/consumer-testpoint.hpp>
+#include <common/ust-consumer/ust-consumer.hpp>
 
 typedef int (*sample_positions_cb)(struct lttng_consumer_stream *stream);
 typedef int (*get_consumed_cb)(struct lttng_consumer_stream *stream,
diff --git a/src/common/consumer/consumer-timer.h b/src/common/consumer/consumer-timer.h
deleted file mode 100644 (file)
index 8575144..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef CONSUMER_TIMER_H
-#define CONSUMER_TIMER_H
-
-#include <pthread.h>
-
-#include "consumer.h"
-
-#define LTTNG_CONSUMER_SIG_SWITCH      SIGRTMIN + 10
-#define LTTNG_CONSUMER_SIG_TEARDOWN    SIGRTMIN + 11
-#define LTTNG_CONSUMER_SIG_LIVE                SIGRTMIN + 12
-#define LTTNG_CONSUMER_SIG_MONITOR     SIGRTMIN + 13
-#define LTTNG_CONSUMER_SIG_EXIT                SIGRTMIN + 14
-
-#define CLOCKID CLOCK_MONOTONIC
-
-/*
- * Handle timer teardown race wrt memory free of private data by consumer
- * signals are handled by a single thread, which permits a synchronization
- * point between handling of each signal. Internal lock ensures mutual
- * exclusion.
- */
-struct timer_signal_data {
-       pthread_t tid;  /* thread id managing signals */
-       int setup_done;
-       int qs_done;
-       pthread_mutex_t lock;
-};
-
-void consumer_timer_switch_start(struct lttng_consumer_channel *channel,
-               unsigned int switch_timer_interval_us);
-void consumer_timer_switch_stop(struct lttng_consumer_channel *channel);
-void consumer_timer_live_start(struct lttng_consumer_channel *channel,
-               unsigned int live_timer_interval_us);
-void consumer_timer_live_stop(struct lttng_consumer_channel *channel);
-int consumer_timer_monitor_start(struct lttng_consumer_channel *channel,
-               unsigned int monitor_timer_interval_us);
-int consumer_timer_monitor_stop(struct lttng_consumer_channel *channel);
-void *consumer_timer_thread(void *data);
-int consumer_signal_init(void);
-
-int consumer_flush_kernel_index(struct lttng_consumer_stream *stream);
-int consumer_flush_ust_index(struct lttng_consumer_stream *stream);
-
-int consumer_timer_thread_get_channel_monitor_pipe(void);
-int consumer_timer_thread_set_channel_monitor_pipe(int fd);
-
-#endif /* CONSUMER_TIMER_H */
diff --git a/src/common/consumer/consumer-timer.hpp b/src/common/consumer/consumer-timer.hpp
new file mode 100644 (file)
index 0000000..0496fdf
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef CONSUMER_TIMER_H
+#define CONSUMER_TIMER_H
+
+#include <pthread.h>
+
+#include "consumer.hpp"
+
+#define LTTNG_CONSUMER_SIG_SWITCH      SIGRTMIN + 10
+#define LTTNG_CONSUMER_SIG_TEARDOWN    SIGRTMIN + 11
+#define LTTNG_CONSUMER_SIG_LIVE                SIGRTMIN + 12
+#define LTTNG_CONSUMER_SIG_MONITOR     SIGRTMIN + 13
+#define LTTNG_CONSUMER_SIG_EXIT                SIGRTMIN + 14
+
+#define CLOCKID CLOCK_MONOTONIC
+
+/*
+ * Handle timer teardown race wrt memory free of private data by consumer
+ * signals are handled by a single thread, which permits a synchronization
+ * point between handling of each signal. Internal lock ensures mutual
+ * exclusion.
+ */
+struct timer_signal_data {
+       pthread_t tid;  /* thread id managing signals */
+       int setup_done;
+       int qs_done;
+       pthread_mutex_t lock;
+};
+
+void consumer_timer_switch_start(struct lttng_consumer_channel *channel,
+               unsigned int switch_timer_interval_us);
+void consumer_timer_switch_stop(struct lttng_consumer_channel *channel);
+void consumer_timer_live_start(struct lttng_consumer_channel *channel,
+               unsigned int live_timer_interval_us);
+void consumer_timer_live_stop(struct lttng_consumer_channel *channel);
+int consumer_timer_monitor_start(struct lttng_consumer_channel *channel,
+               unsigned int monitor_timer_interval_us);
+int consumer_timer_monitor_stop(struct lttng_consumer_channel *channel);
+void *consumer_timer_thread(void *data);
+int consumer_signal_init(void);
+
+int consumer_flush_kernel_index(struct lttng_consumer_stream *stream);
+int consumer_flush_ust_index(struct lttng_consumer_stream *stream);
+
+int consumer_timer_thread_get_channel_monitor_pipe(void);
+int consumer_timer_thread_set_channel_monitor_pipe(int fd);
+
+#endif /* CONSUMER_TIMER_H */
index fb5aeae7bc094873d01bdaefcd967b4055a8bf25..790f74fddcd27b7166880bb63acf9cf5111bf3b4 100644 (file)
@@ -7,7 +7,7 @@
  *
  */
 
-#include "common/index/ctf-index.h"
+#include "common/index/ctf-index.hpp"
 #define _LGPL_SOURCE
 #include <poll.h>
 #include <pthread.h>
 #include <inttypes.h>
 #include <signal.h>
 
-#include <bin/lttng-consumerd/health-consumerd.h>
-#include <common/common.h>
-#include <common/utils.h>
-#include <common/time.h>
-#include <common/compat/poll.h>
-#include <common/compat/endian.h>
-#include <common/index/index.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/sessiond-comm/relayd.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/kernel-consumer/kernel-consumer.h>
-#include <common/relayd/relayd.h>
-#include <common/ust-consumer/ust-consumer.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/consumer/consumer.h>
-#include <common/consumer/consumer-stream.h>
-#include <common/consumer/consumer-testpoint.h>
-#include <common/align.h>
-#include <common/consumer/consumer-metadata-cache.h>
-#include <common/trace-chunk.h>
-#include <common/trace-chunk-registry.h>
-#include <common/string-utils/format.h>
-#include <common/dynamic-array.h>
+#include <bin/lttng-consumerd/health-consumerd.hpp>
+#include <common/common.hpp>
+#include <common/utils.hpp>
+#include <common/time.hpp>
+#include <common/compat/poll.hpp>
+#include <common/compat/endian.hpp>
+#include <common/index/index.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/kernel-consumer/kernel-consumer.hpp>
+#include <common/relayd/relayd.hpp>
+#include <common/ust-consumer/ust-consumer.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/consumer/consumer-stream.hpp>
+#include <common/consumer/consumer-testpoint.hpp>
+#include <common/align.hpp>
+#include <common/consumer/consumer-metadata-cache.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/trace-chunk-registry.hpp>
+#include <common/string-utils/format.hpp>
+#include <common/dynamic-array.hpp>
 
 lttng_consumer_global_data the_consumer_data;
 
diff --git a/src/common/consumer/consumer.h b/src/common/consumer/consumer.h
deleted file mode 100644 (file)
index 737f2a4..0000000
+++ /dev/null
@@ -1,1076 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LIB_CONSUMER_H
-#define LIB_CONSUMER_H
-
-#include <limits.h>
-#include <poll.h>
-#include <unistd.h>
-#include <urcu/list.h>
-
-#include <lttng/lttng.h>
-
-#include <common/hashtable/hashtable.h>
-#include <common/compat/fcntl.h>
-#include <common/uuid.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/pipe.h>
-#include <common/index/ctf-index.h>
-#include <common/trace-chunk-registry.h>
-#include <common/credentials.h>
-#include <common/buffer-view.h>
-#include <common/dynamic-array.h>
-
-struct lttng_consumer_local_data;
-
-/* Commands for consumer */
-enum lttng_consumer_command {
-       LTTNG_CONSUMER_ADD_CHANNEL,
-       LTTNG_CONSUMER_ADD_STREAM,
-       /* pause, delete, active depending on fd state */
-       LTTNG_CONSUMER_UPDATE_STREAM,
-       /* inform the consumer to quit when all fd has hang up */
-       LTTNG_CONSUMER_STOP,    /* deprecated */
-       LTTNG_CONSUMER_ADD_RELAYD_SOCKET,
-       /* Inform the consumer to kill a specific relayd connection */
-       LTTNG_CONSUMER_DESTROY_RELAYD,
-       /* Return to the sessiond if there is data pending for a session */
-       LTTNG_CONSUMER_DATA_PENDING,
-       /* Consumer creates a channel and returns it to sessiond. */
-       LTTNG_CONSUMER_ASK_CHANNEL_CREATION,
-       LTTNG_CONSUMER_GET_CHANNEL,
-       LTTNG_CONSUMER_DESTROY_CHANNEL,
-       LTTNG_CONSUMER_PUSH_METADATA,
-       LTTNG_CONSUMER_CLOSE_METADATA,
-       LTTNG_CONSUMER_SETUP_METADATA,
-       LTTNG_CONSUMER_FLUSH_CHANNEL,
-       LTTNG_CONSUMER_SNAPSHOT_CHANNEL,
-       LTTNG_CONSUMER_SNAPSHOT_METADATA,
-       LTTNG_CONSUMER_STREAMS_SENT,
-       LTTNG_CONSUMER_DISCARDED_EVENTS,
-       LTTNG_CONSUMER_LOST_PACKETS,
-       LTTNG_CONSUMER_CLEAR_QUIESCENT_CHANNEL,
-       LTTNG_CONSUMER_SET_CHANNEL_MONITOR_PIPE,
-       LTTNG_CONSUMER_ROTATE_CHANNEL,
-       LTTNG_CONSUMER_INIT,
-       LTTNG_CONSUMER_CREATE_TRACE_CHUNK,
-       LTTNG_CONSUMER_CLOSE_TRACE_CHUNK,
-       LTTNG_CONSUMER_TRACE_CHUNK_EXISTS,
-       LTTNG_CONSUMER_CLEAR_CHANNEL,
-       LTTNG_CONSUMER_OPEN_CHANNEL_PACKETS,
-};
-
-enum lttng_consumer_type {
-       LTTNG_CONSUMER_UNKNOWN = 0,
-       LTTNG_CONSUMER_KERNEL,
-       LTTNG_CONSUMER64_UST,
-       LTTNG_CONSUMER32_UST,
-};
-
-enum consumer_endpoint_status {
-       CONSUMER_ENDPOINT_ACTIVE,
-       CONSUMER_ENDPOINT_INACTIVE,
-};
-
-enum consumer_channel_output {
-       CONSUMER_CHANNEL_MMAP   = 0,
-       CONSUMER_CHANNEL_SPLICE = 1,
-};
-
-enum consumer_channel_type {
-       CONSUMER_CHANNEL_TYPE_METADATA  = 0,
-       CONSUMER_CHANNEL_TYPE_DATA      = 1,
-};
-
-enum sync_metadata_status {
-       SYNC_METADATA_STATUS_NEW_DATA,
-       SYNC_METADATA_STATUS_NO_DATA,
-       SYNC_METADATA_STATUS_ERROR,
-};
-
-extern struct lttng_consumer_global_data the_consumer_data;
-
-struct stream_list {
-       struct cds_list_head head;
-       unsigned int count;
-};
-
-/* Stub. */
-struct consumer_metadata_cache;
-
-struct lttng_consumer_channel {
-       /* Is the channel published in the channel hash tables? */
-       bool is_published;
-       /*
-        * Was the channel deleted (logically) and waiting to be reclaimed?
-        * If this flag is set, no modification that is not cleaned-up by the
-        * RCU reclamation callback should be made
-        */
-       bool is_deleted;
-       /* HT node used for consumer_data.channel_ht */
-       struct lttng_ht_node_u64 node;
-       /* HT node used for consumer_data.channels_by_session_id_ht */
-       struct lttng_ht_node_u64 channels_by_session_id_ht_node;
-       /* Indexed key. Incremented value in the consumer. */
-       uint64_t key;
-       /* Number of streams referencing this channel */
-       int refcount;
-       /* Tracing session id on the session daemon side. */
-       uint64_t session_id;
-       /* Current trace chunk of the session in which this channel exists. */
-       struct lttng_trace_chunk *trace_chunk;
-       /*
-        * Session id when requesting metadata to the session daemon for
-        * a session with per-PID buffers.
-        */
-       uint64_t session_id_per_pid;
-       /*
-        * In the case of local streams, this field contains the channel's
-        * output path; a path relative to the session's output path.
-        *   e.g. ust/uid/1000/64-bit
-        *
-        * In the case of remote streams, the contents of this field depends
-        * on the version of the relay daemon peer. For 2.11+ peers, the
-        * contents are the same as in the local case. However, for legacy
-        * peers, this contains a path of the form:
-        *   /hostname/session_path/ust/uid/1000/64-bit
-        */
-       char pathname[PATH_MAX];
-       /* Channel name. */
-       char name[LTTNG_SYMBOL_NAME_LEN];
-       /* Relayd id of the channel. -1ULL if it does not apply. */
-       uint64_t relayd_id;
-       /*
-        * Number of streams NOT initialized yet. This is used in order to not
-        * delete this channel if streams are getting initialized.
-        */
-       unsigned int nb_init_stream_left;
-       /* Output type (mmap or splice). */
-       enum consumer_channel_output output;
-       /* Channel type for stream */
-       enum consumer_channel_type type;
-
-       /* For UST */
-       uid_t ust_app_uid;      /* Application UID. */
-       struct lttng_ust_ctl_consumer_channel *uchan;
-       unsigned char uuid[LTTNG_UUID_STR_LEN];
-       /*
-        * Temporary stream list used to store the streams once created and waiting
-        * to be sent to the session daemon by receiving the
-        * LTTNG_CONSUMER_GET_CHANNEL.
-        */
-       struct stream_list streams;
-
-       /*
-        * Set if the channel is metadata. We keep a reference to the stream
-        * because we have to flush data once pushed by the session daemon. For a
-        * regular channel, this is always set to NULL.
-        */
-       struct lttng_consumer_stream *metadata_stream;
-
-       /* for UST */
-       int wait_fd;
-       /* Node within channel thread ht */
-       struct lttng_ht_node_u64 wait_fd_node;
-
-       /* Metadata cache is metadata channel */
-       struct consumer_metadata_cache *metadata_cache;
-
-       /* For UST metadata periodical flush */
-       int switch_timer_enabled;
-       timer_t switch_timer;
-       int switch_timer_error;
-
-       /* For the live mode */
-       int live_timer_enabled;
-       timer_t live_timer;
-       int live_timer_error;
-       /* Channel is part of a live session ? */
-       bool is_live;
-
-       /* For channel monitoring timer. */
-       int monitor_timer_enabled;
-       timer_t monitor_timer;
-
-       /* On-disk circular buffer */
-       uint64_t tracefile_size;
-       uint64_t tracefile_count;
-       /*
-        * Monitor or not the streams of this channel meaning this indicates if the
-        * streams should be sent to the data/metadata thread or added to the no
-        * monitor list of the channel.
-        */
-       unsigned int monitor;
-
-       /*
-        * Channel lock.
-        *
-        * This lock protects against concurrent update of channel.
-        *
-        * This is nested INSIDE the consumer data lock.
-        * This is nested OUTSIDE the channel timer lock.
-        * This is nested OUTSIDE the metadata cache lock.
-        * This is nested OUTSIDE stream lock.
-        * This is nested OUTSIDE consumer_relayd_sock_pair lock.
-        */
-       pthread_mutex_t lock;
-
-       /*
-        * Channel teardown lock.
-        *
-        * This lock protect against teardown of channel. It is _never_
-        * taken by the timer handler.
-        *
-        * This is nested INSIDE the consumer data lock.
-        * This is nested INSIDE the channel lock.
-        * This is nested OUTSIDE the metadata cache lock.
-        * This is nested OUTSIDE stream lock.
-        * This is nested OUTSIDE consumer_relayd_sock_pair lock.
-        */
-       pthread_mutex_t timer_lock;
-
-       /* Timer value in usec for live streaming. */
-       unsigned int live_timer_interval;
-
-       int *stream_fds;
-       int nr_stream_fds;
-       char root_shm_path[PATH_MAX];
-       char shm_path[PATH_MAX];
-       /* Only set for UST channels. */
-       LTTNG_OPTIONAL(struct lttng_credentials) buffer_credentials;
-       /* Total number of discarded events for that channel. */
-       uint64_t discarded_events;
-       /* Total number of missed packets due to overwriting (overwrite). */
-       uint64_t lost_packets;
-
-       bool streams_sent_to_relayd;
-};
-
-struct stream_subbuffer {
-       union {
-               /*
-                * CONSUMER_CHANNEL_SPLICE
-                * No ownership assumed.
-                */
-               int fd;
-               /* CONSUMER_CHANNEL_MMAP */
-               struct lttng_buffer_view buffer;
-       } buffer;
-       union {
-               /*
-                * Common members are fine to access through either
-                * union entries (as per C11, Common Initial Sequence).
-                */
-               struct {
-                       unsigned long subbuf_size;
-                       unsigned long padded_subbuf_size;
-                       uint64_t version;
-                       /*
-                        * Left unset when unsupported.
-                        *
-                        * Indicates that this is the last sub-buffer of
-                        * a series of sub-buffer that makes-up a coherent
-                        * (parseable) unit of metadata.
-                        */
-                       LTTNG_OPTIONAL(bool) coherent;
-               } metadata;
-               struct {
-                       unsigned long subbuf_size;
-                       unsigned long padded_subbuf_size;
-                       uint64_t packet_size;
-                       uint64_t content_size;
-                       uint64_t timestamp_begin;
-                       uint64_t timestamp_end;
-                       uint64_t events_discarded;
-                       /* Left unset when unsupported. */
-                       LTTNG_OPTIONAL(uint64_t) sequence_number;
-                       uint64_t stream_id;
-                       /* Left unset when unsupported. */
-                       LTTNG_OPTIONAL(uint64_t) stream_instance_id;
-               } data;
-       } info;
-};
-
-enum get_next_subbuffer_status {
-       GET_NEXT_SUBBUFFER_STATUS_OK,
-       GET_NEXT_SUBBUFFER_STATUS_NO_DATA,
-       GET_NEXT_SUBBUFFER_STATUS_ERROR,
-};
-
-/*
- * Perform any operation required to acknowledge
- * the wake-up of a consumer stream (e.g. consume a byte on a wake-up pipe).
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef int (*on_wake_up_cb)(struct lttng_consumer_stream *);
-
-/*
- * Perform any operation required before a consumer stream is put
- * to sleep before awaiting a data availability notification.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef int (*on_sleep_cb)(struct lttng_consumer_stream *,
-               struct lttng_consumer_local_data *);
-
-/*
- * Acquire the subbuffer at the current 'consumed' position.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef enum get_next_subbuffer_status (*get_next_subbuffer_cb)(
-               struct lttng_consumer_stream *, struct stream_subbuffer *);
-
-/*
- * Populate the stream_subbuffer's info member. The info to populate
- * depends on the type (metadata/data) of the stream.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef int (*extract_subbuffer_info_cb)(
-               struct lttng_consumer_stream *, struct stream_subbuffer *);
-
-/*
- * Invoked after a subbuffer's info has been filled.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef int (*pre_consume_subbuffer_cb)(struct lttng_consumer_stream *,
-               const struct stream_subbuffer *);
-
-/*
- * Consume subbuffer contents.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef ssize_t (*consume_subbuffer_cb)(struct lttng_consumer_local_data *,
-               struct lttng_consumer_stream *,
-               const struct stream_subbuffer *);
-
-/*
- * Release the current subbuffer and advance the 'consumed' position by
- * one subbuffer.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef int (*put_next_subbuffer_cb)(struct lttng_consumer_stream *,
-               struct stream_subbuffer *);
-
-/*
- * Invoked after consuming a subbuffer.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef int (*post_consume_cb)(struct lttng_consumer_stream *,
-               const struct stream_subbuffer *,
-               struct lttng_consumer_local_data *);
-
-/*
- * Send a live beacon if no data is available.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef int (*send_live_beacon_cb)(struct lttng_consumer_stream *);
-
-/*
- * Lock the stream and channel locks and any other stream-type specific
- * lock that need to be acquired during the processing of an
- * availability notification.
- */
-typedef void (*lock_cb)(struct lttng_consumer_stream *);
-
-/*
- * Unlock the stream and channel locks and any other stream-type specific
- * lock before sleeping until the next availability notification.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef void (*unlock_cb)(struct lttng_consumer_stream *);
-
-/*
- * Assert that the stream and channel lock and any other stream type specific
- * lock that need to be acquired during the processing of a read_subbuffer
- * operation is acquired.
- */
-typedef void (*assert_locked_cb)(struct lttng_consumer_stream *);
-
-/*
- * Invoked when a subbuffer's metadata version does not match the last
- * known metadata version.
- *
- * Stream and channel locks are acquired during this call.
- */
-typedef void (*reset_metadata_cb)(struct lttng_consumer_stream *);
-
-/*
- * Internal representation of the streams, sessiond_key is used to identify
- * uniquely a stream.
- */
-struct lttng_consumer_stream {
-       /* HT node used by the data_ht and metadata_ht */
-       struct lttng_ht_node_u64 node;
-       /* stream indexed per channel key node */
-       struct lttng_ht_node_u64 node_channel_id;
-       /* HT node used in consumer_data.stream_list_ht */
-       struct lttng_ht_node_u64 node_session_id;
-       /* Pointer to associated channel. */
-       struct lttng_consumer_channel *chan;
-       /*
-        * Current trace chunk. Holds a reference to the trace chunk.
-        * `chunk` can be NULL when a stream is not associated to a chunk, e.g.
-        * when it was created in the context of a no-output session.
-        */
-       struct lttng_trace_chunk *trace_chunk;
-
-       /* Key by which the stream is indexed for 'node'. */
-       uint64_t key;
-       /*
-        * File descriptor of the data output file. This can be either a file or a
-        * socket fd for relayd streaming.
-        */
-       int out_fd; /* output file to write the data */
-       /* Write position in the output file descriptor */
-       off_t out_fd_offset;
-       /* Amount of bytes written to the output */
-       uint64_t output_written;
-       int shm_fd_is_copy;
-       int data_read;
-       int hangup_flush_done;
-
-       /*
-        * Whether the stream is in a "complete" state (e.g. it does not have a
-        * partially written sub-buffer.
-        *
-        * Initialized to "false" on stream creation (first packet is empty).
-        *
-        * The various transitions of the quiescent state are:
-        *     - On "start" tracing: set to false, since the stream is not
-        *       "complete".
-        *     - On "stop" tracing: if !quiescent -> flush FINAL (update
-        *       timestamp_end), and set to true; the stream has entered a
-        *       complete/quiescent state.
-        *     - On "destroy" or stream/application hang-up: if !quiescent ->
-        *       flush FINAL, and set to true.
-        *
-        * NOTE: Update and read are protected by the stream lock.
-        */
-       bool quiescent;
-
-       /*
-        * True if the sequence number is not available (lttng-modules < 2.8).
-        */
-       bool sequence_number_unavailable;
-
-       /*
-        * metadata_timer_lock protects flags waiting_on_metadata and
-        * missed_metadata_flush.
-        */
-       pthread_mutex_t metadata_timer_lock;
-       /*
-        * Flag set when awaiting metadata to be pushed. Used in the
-        * timer thread to skip waiting on the stream (and stream lock) to
-        * ensure we can proceed to flushing metadata in live mode.
-        */
-       bool waiting_on_metadata;
-       /* Raised when a timer misses a metadata flush. */
-       bool missed_metadata_flush;
-
-       enum lttng_event_output output;
-       /* Maximum subbuffer size (in bytes). */
-       unsigned long max_sb_size;
-
-       /*
-        * Still used by the kernel for MMAP output. For UST, the ustctl getter is
-        * used for the mmap base and offset.
-        */
-       void *mmap_base;
-       unsigned long mmap_len;
-
-       /* For UST */
-
-       int wait_fd;
-       /* Network sequence number. Indicating on which relayd socket it goes. */
-       uint64_t net_seq_idx;
-       /*
-        * Indicate if this stream was successfully sent to a relayd. This is set
-        * after the refcount of the relayd is incremented and is checked when the
-        * stream is closed before decrementing the refcount in order to avoid an
-        * unbalanced state.
-        */
-       unsigned int sent_to_relayd;
-
-       /* Identify if the stream is the metadata */
-       unsigned int metadata_flag;
-       /*
-        * Last known metadata version, reset the metadata file in case
-        * of change.
-        */
-       uint64_t metadata_version;
-       /* Used when the stream is set for network streaming */
-       uint64_t relayd_stream_id;
-       /*
-        * When sending a stream packet to a relayd, this number is used to track
-        * the packet sent by the consumer and seen by the relayd. When sending the
-        * data header to the relayd, this number is sent and if the transmission
-        * was successful, it is incremented.
-        *
-        * Even if the full data is not fully transmitted it won't matter since
-        * only two possible error can happen after that where either the relayd
-        * died or a read error is detected on the stream making this value useless
-        * after that.
-        *
-        * This value SHOULD be read/updated atomically or with the lock acquired.
-        */
-       uint64_t next_net_seq_num;
-       /*
-        * Lock to use the stream FDs since they are used between threads.
-        *
-        * This is nested INSIDE the consumer_data lock.
-        * This is nested INSIDE the channel lock.
-        * This is nested INSIDE the channel timer lock.
-        * This is nested OUTSIDE the metadata cache lock.
-        * This is nested OUTSIDE consumer_relayd_sock_pair lock.
-        */
-       pthread_mutex_t lock;
-       /* Tracing session id */
-       uint64_t session_id;
-       /*
-        * Indicates if the stream end point is still active or not (network
-        * streaming or local file system). The thread "owning" the stream is
-        * handling this status and can be notified of a state change through the
-        * consumer data appropriate pipe.
-        */
-       enum consumer_endpoint_status endpoint_status;
-       /* Stream name. Format is: <channel_name>_<cpu_number> */
-       char name[LTTNG_SYMBOL_NAME_LEN];
-       /* Internal state of libustctl. */
-       struct lttng_ust_ctl_consumer_stream *ustream;
-       struct cds_list_head send_node;
-       /* On-disk circular buffer */
-       uint64_t tracefile_size_current;
-       uint64_t tracefile_count_current;
-       /*
-        * Monitor or not the streams of this channel meaning this indicates if the
-        * streams should be sent to the data/metadata thread or added to the no
-        * monitor list of the channel.
-        */
-       unsigned int monitor;
-       /*
-        * Indicate if the stream is globally visible meaning that it has been
-        * added to the multiple hash tables. If *not* set, NO lock should be
-        * acquired in the destroy path.
-        */
-       unsigned int globally_visible;
-       /*
-        * Pipe to wake up the metadata poll thread when the UST metadata
-        * cache is updated.
-        */
-       int ust_metadata_poll_pipe[2];
-       /*
-        * How much metadata was read from the metadata cache and sent
-        * to the channel.
-        */
-       uint64_t ust_metadata_pushed;
-       /*
-        * Copy of the last discarded event value to detect the overflow of
-        * the counter.
-        */
-       uint64_t last_discarded_events;
-       /* Copy of the sequence number of the last packet extracted. */
-       uint64_t last_sequence_number;
-       /*
-        * Index file object of the index file for this stream.
-        */
-       struct lttng_index_file *index_file;
-
-       /*
-        * Local pipe to extract data when using splice.
-        */
-       int splice_pipe[2];
-
-       /*
-        * Rendez-vous point between data and metadata stream in live mode.
-        */
-       pthread_cond_t metadata_rdv;
-       pthread_mutex_t metadata_rdv_lock;
-
-       /*
-        * rotate_position represents the packet sequence number of the last
-        * packet which belongs to the current trace chunk prior to the rotation.
-        * When that position is reached, this tracefile can be closed and a
-        * new one is created in channel_read_only_attributes.path.
-        */
-       uint64_t rotate_position;
-
-       /* Whether or not a packet was opened during the current trace chunk. */
-       bool opened_packet_in_current_trace_chunk;
-
-       /*
-        * Read-only copies of channel values. We cannot safely access the
-        * channel from a stream, so we need to have a local copy of these
-        * fields in the stream object. These fields should be removed from
-        * the stream objects when we introduce refcounting.
-        */
-       struct {
-               uint64_t tracefile_size;
-       } channel_read_only_attributes;
-
-       /*
-        * Flag to inform the data or metadata thread that a stream is
-        * ready to be rotated.
-        */
-       bool rotate_ready;
-
-       /* Indicate if the stream still has some data to be read. */
-       unsigned int has_data:1;
-       /*
-        * Inform the consumer or relay to reset the metadata
-        * file before writing in it (regeneration).
-        */
-       unsigned int reset_metadata_flag:1;
-       struct {
-               /*
-                * Invoked in the order of declaration.
-                * See callback type definitions.
-                */
-               lock_cb lock;
-               on_wake_up_cb on_wake_up;
-               get_next_subbuffer_cb get_next_subbuffer;
-               extract_subbuffer_info_cb extract_subbuffer_info;
-               pre_consume_subbuffer_cb pre_consume_subbuffer;
-               reset_metadata_cb reset_metadata;
-               consume_subbuffer_cb consume_subbuffer;
-               put_next_subbuffer_cb put_next_subbuffer;
-               struct lttng_dynamic_array post_consume_cbs;
-               send_live_beacon_cb send_live_beacon;
-               on_sleep_cb on_sleep;
-               unlock_cb unlock;
-               assert_locked_cb assert_locked;
-       } read_subbuffer_ops;
-       struct metadata_bucket *metadata_bucket;
-};
-
-/*
- * Internal representation of a relayd socket pair.
- */
-struct consumer_relayd_sock_pair {
-       /* Network sequence number. */
-       uint64_t net_seq_idx;
-       /* Number of stream associated with this relayd */
-       int refcount;
-
-       /*
-        * This flag indicates whether or not we should destroy this object. The
-        * destruction should ONLY occurs when this flag is set and the refcount is
-        * set to zero.
-        */
-       unsigned int destroy_flag;
-
-       /*
-        * Mutex protecting the control socket to avoid out of order packets
-        * between threads sending data to the relayd. Since metadata data is sent
-        * over that socket, at least two sendmsg() are needed (header + data)
-        * creating a race for packets to overlap between threads using it.
-        *
-        * This is nested INSIDE the consumer_data lock.
-        * This is nested INSIDE the stream lock.
-        */
-       pthread_mutex_t ctrl_sock_mutex;
-
-       /* Control socket. Command and metadata are passed over it */
-       struct lttcomm_relayd_sock control_sock;
-
-       /*
-        * We don't need a mutex at this point since we only splice or write single
-        * large chunk of data with a header appended at the begining. Moreover,
-        * this socket is for now only used in a single thread.
-        */
-       struct lttcomm_relayd_sock data_sock;
-       struct lttng_ht_node_u64 node;
-
-       /* Session id on both sides for the sockets. */
-       uint64_t relayd_session_id;
-       uint64_t sessiond_session_id;
-       struct lttng_consumer_local_data *ctx;
-};
-
-/*
- * UST consumer local data to the program. One or more instance per
- * process.
- */
-struct lttng_consumer_local_data {
-       /*
-        * Function to call when data is available on a buffer.
-        * Returns the number of bytes read, or negative error value.
-        */
-       ssize_t (*on_buffer_ready)(struct lttng_consumer_stream *stream,
-                       struct lttng_consumer_local_data *ctx,
-                       bool locked_by_caller);
-       /*
-        * function to call when we receive a new channel, it receives a
-        * newly allocated channel, depending on the return code of this
-        * function, the new channel will be handled by the application
-        * or the library.
-        *
-        * Returns:
-        *    > 0 (success, FD is kept by application)
-        *   == 0 (success, FD is left to library)
-        *    < 0 (error)
-        */
-       int (*on_recv_channel)(struct lttng_consumer_channel *channel);
-       /*
-        * function to call when we receive a new stream, it receives a
-        * newly allocated stream, depending on the return code of this
-        * function, the new stream will be handled by the application
-        * or the library.
-        *
-        * Returns:
-        *    > 0 (success, FD is kept by application)
-        *   == 0 (success, FD is left to library)
-        *    < 0 (error)
-        */
-       int (*on_recv_stream)(struct lttng_consumer_stream *stream);
-       /*
-        * function to call when a stream is getting updated by the session
-        * daemon, this function receives the sessiond key and the new
-        * state, depending on the return code of this function the
-        * update of state for the stream is handled by the application
-        * or the library.
-        *
-        * Returns:
-        *    > 0 (success, FD is kept by application)
-        *   == 0 (success, FD is left to library)
-        *    < 0 (error)
-        */
-       int (*on_update_stream)(uint64_t sessiond_key, uint32_t state);
-       enum lttng_consumer_type type;
-       /* socket to communicate errors with sessiond */
-       int consumer_error_socket;
-       /* socket to ask metadata to sessiond. */
-       int consumer_metadata_socket;
-       /*
-        * Protect consumer_metadata_socket.
-        *
-        * This is nested OUTSIDE the metadata cache lock.
-        */
-       pthread_mutex_t metadata_socket_lock;
-       /* socket to exchange commands with sessiond */
-       char *consumer_command_sock_path;
-       /* communication with splice */
-       int consumer_channel_pipe[2];
-       /* Data stream poll thread pipe. To transfer data stream to the thread */
-       struct lttng_pipe *consumer_data_pipe;
-
-       /*
-        * Data thread use that pipe to catch wakeup from read subbuffer that
-        * detects that there is still data to be read for the stream encountered.
-        * Before doing so, the stream is flagged to indicate that there is still
-        * data to be read.
-        *
-        * Both pipes (read/write) are owned and used inside the data thread.
-        */
-       struct lttng_pipe *consumer_wakeup_pipe;
-       /* Indicate if the wakeup thread has been notified. */
-       unsigned int has_wakeup:1;
-
-       /* to let the signal handler wake up the fd receiver thread */
-       int consumer_should_quit[2];
-       /* Metadata poll thread pipe. Transfer metadata stream to it */
-       struct lttng_pipe *consumer_metadata_pipe;
-       /*
-        * Pipe used by the channel monitoring timers to provide state samples
-        * to the session daemon (write-only).
-        */
-       int channel_monitor_pipe;
-       LTTNG_OPTIONAL(lttng_uuid) sessiond_uuid;
-};
-
-/*
- * Library-level data. One instance per process.
- */
-struct lttng_consumer_global_data {
-       /*
-        * At this time, this lock is used to ensure coherence between the count
-        * and number of element in the hash table. It's also a protection for
-        * concurrent read/write between threads.
-        *
-        * This is nested OUTSIDE the stream lock.
-        * This is nested OUTSIDE the consumer_relayd_sock_pair lock.
-        */
-       pthread_mutex_t lock {};
-
-       /*
-        * Number of streams in the data stream hash table declared outside.
-        * Protected by consumer_data.lock.
-        */
-       int stream_count = 0;
-
-       /* Channel hash table protected by consumer_data.lock. */
-       struct lttng_ht *channel_ht = nullptr;
-       /* Channel hash table indexed by session id. */
-       struct lttng_ht *channels_by_session_id_ht = nullptr;
-       /*
-        * Flag specifying if the local array of FDs needs update in the
-        * poll function. Protected by consumer_data.lock.
-        */
-       unsigned int need_update = 1;
-       enum lttng_consumer_type type = LTTNG_CONSUMER_UNKNOWN;
-
-       /*
-        * Relayd socket(s) hashtable indexed by network sequence number. Each
-        * stream has an index which associate the right relayd socket to use.
-        */
-       struct lttng_ht *relayd_ht = nullptr;
-
-       /*
-        * This hash table contains all streams (metadata and data) indexed by
-        * session id. In other words, the ht is indexed by session id and each
-        * bucket contains the list of associated streams.
-        *
-        * This HT uses the "node_session_id" of the consumer stream.
-        */
-       struct lttng_ht *stream_list_ht = nullptr;
-
-       /*
-        * This HT uses the "node_channel_id" of the consumer stream.
-        */
-       struct lttng_ht *stream_per_chan_id_ht = nullptr;
-
-       /*
-        * Trace chunk registry indexed by (session_id, chunk_id).
-        */
-       struct lttng_trace_chunk_registry *chunk_registry = nullptr;
-};
-
-/*
- * Set to nonzero when the consumer is exiting. Updated by signal
- * handler and thread exit, read by threads.
- */
-extern int consumer_quit;
-
-/*
- * Set to nonzero when the consumer is exiting. Updated by signal
- * handler and thread exit, read by threads.
- */
-extern int consumer_quit;
-
-/*
- * Flag used to temporarily pause data consumption from testpoints.
- *
- * This variable is dlsym-ed from a test, so needs to be exported.
- */
-LTTNG_EXPORT extern int data_consumption_paused;
-
-/* Return a human-readable consumer type string that is suitable for logging. */
-static inline
-const char *lttng_consumer_type_str(enum lttng_consumer_type type)
-{
-       switch (type) {
-       case LTTNG_CONSUMER_UNKNOWN:
-               return "unknown";
-       case LTTNG_CONSUMER_KERNEL:
-               return "kernel";
-       case LTTNG_CONSUMER32_UST:
-               return "32-bit user space";
-       case LTTNG_CONSUMER64_UST:
-               return "64-bit user space";
-       default:
-               abort();
-       }
-}
-
-/*
- * Init consumer data structures.
- */
-int lttng_consumer_init(void);
-
-/*
- * Set the error socket for communication with a session daemon.
- */
-void lttng_consumer_set_error_sock(struct lttng_consumer_local_data *ctx,
-               int sock);
-
-/*
- * Set the command socket path for communication with a session daemon.
- */
-void lttng_consumer_set_command_sock_path(
-               struct lttng_consumer_local_data *ctx, char *sock);
-
-/*
- * Send return code to session daemon.
- *
- * Returns the return code of sendmsg : the number of bytes transmitted or -1
- * on error.
- */
-int lttng_consumer_send_error(struct lttng_consumer_local_data *ctx, int cmd);
-
-/*
- * Called from signal handler to ensure a clean exit.
- */
-void lttng_consumer_should_exit(struct lttng_consumer_local_data *ctx);
-
-/*
- * Cleanup the daemon's socket on exit.
- */
-void lttng_consumer_cleanup(void);
-
-/*
- * Poll on the should_quit pipe and the command socket return -1 on error and
- * should exit, 0 if data is available on the command socket
- */
-int lttng_consumer_poll_socket(struct pollfd *kconsumer_sockpoll);
-
-/*
- * Copy the fields from the channel that need to be accessed (read-only)
- * directly from the stream.
- */
-void consumer_stream_update_channel_attributes(
-               struct lttng_consumer_stream *stream,
-               struct lttng_consumer_channel *channel);
-
-struct lttng_consumer_stream *consumer_allocate_stream(
-               struct lttng_consumer_channel *channel,
-               uint64_t channel_key,
-               uint64_t stream_key,
-               const char *channel_name,
-               uint64_t relayd_id,
-               uint64_t session_id,
-               struct lttng_trace_chunk *trace_chunk,
-               int cpu,
-               int *alloc_ret,
-               enum consumer_channel_type type,
-               unsigned int monitor);
-struct lttng_consumer_channel *consumer_allocate_channel(uint64_t key,
-               uint64_t session_id,
-               const uint64_t *chunk_id,
-               const char *pathname,
-               const char *name,
-               uint64_t relayd_id,
-               enum lttng_event_output output,
-               uint64_t tracefile_size,
-               uint64_t tracefile_count,
-               uint64_t session_id_per_pid,
-               unsigned int monitor,
-               unsigned int live_timer_interval,
-               bool is_in_live_session,
-               const char *root_shm_path,
-               const char *shm_path);
-void consumer_del_stream(struct lttng_consumer_stream *stream,
-               struct lttng_ht *ht);
-void consumer_del_metadata_stream(struct lttng_consumer_stream *stream,
-               struct lttng_ht *ht);
-int consumer_add_channel(struct lttng_consumer_channel *channel,
-               struct lttng_consumer_local_data *ctx);
-void consumer_del_channel(struct lttng_consumer_channel *channel);
-
-/* lttng-relayd consumer command */
-struct consumer_relayd_sock_pair *consumer_find_relayd(uint64_t key);
-int consumer_send_relayd_stream(struct lttng_consumer_stream *stream, char *path);
-int consumer_send_relayd_streams_sent(uint64_t net_seq_idx);
-void close_relayd_stream(struct lttng_consumer_stream *stream);
-struct lttng_consumer_channel *consumer_find_channel(uint64_t key);
-int consumer_handle_stream_before_relayd(struct lttng_consumer_stream *stream,
-               size_t data_size);
-void consumer_steal_stream_key(int key, struct lttng_ht *ht);
-
-struct lttng_consumer_local_data *lttng_consumer_create(
-               enum lttng_consumer_type type,
-               ssize_t (*buffer_ready)(struct lttng_consumer_stream *stream,
-                       struct lttng_consumer_local_data *ctx,
-                       bool locked_by_caller),
-               int (*recv_channel)(struct lttng_consumer_channel *channel),
-               int (*recv_stream)(struct lttng_consumer_stream *stream),
-               int (*update_stream)(uint64_t sessiond_key, uint32_t state));
-void lttng_consumer_destroy(struct lttng_consumer_local_data *ctx);
-ssize_t lttng_consumer_on_read_subbuffer_mmap(
-               struct lttng_consumer_stream *stream,
-               const struct lttng_buffer_view *buffer,
-               unsigned long padding);
-ssize_t lttng_consumer_on_read_subbuffer_splice(
-               struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_stream *stream, unsigned long len,
-               unsigned long padding);
-int lttng_consumer_sample_snapshot_positions(struct lttng_consumer_stream *stream);
-int lttng_consumer_take_snapshot(struct lttng_consumer_stream *stream);
-int lttng_consumer_get_produced_snapshot(struct lttng_consumer_stream *stream,
-               unsigned long *pos);
-int lttng_consumer_get_consumed_snapshot(struct lttng_consumer_stream *stream,
-               unsigned long *pos);
-int lttng_ustconsumer_get_wakeup_fd(struct lttng_consumer_stream *stream);
-int lttng_ustconsumer_close_wakeup_fd(struct lttng_consumer_stream *stream);
-void *consumer_thread_metadata_poll(void *data);
-void *consumer_thread_data_poll(void *data);
-void *consumer_thread_sessiond_poll(void *data);
-void *consumer_thread_channel_poll(void *data);
-int lttng_consumer_recv_cmd(struct lttng_consumer_local_data *ctx,
-               int sock, struct pollfd *consumer_sockpoll);
-
-ssize_t lttng_consumer_read_subbuffer(struct lttng_consumer_stream *stream,
-               struct lttng_consumer_local_data *ctx,
-               bool locked_by_caller);
-int lttng_consumer_on_recv_stream(struct lttng_consumer_stream *stream);
-void consumer_add_relayd_socket(uint64_t net_seq_idx, int sock_type,
-               struct lttng_consumer_local_data *ctx, int sock,
-               struct pollfd *consumer_sockpoll, struct lttcomm_relayd_sock *relayd_sock,
-               uint64_t sessiond_id, uint64_t relayd_session_id);
-void consumer_flag_relayd_for_destroy(
-               struct consumer_relayd_sock_pair *relayd);
-int consumer_data_pending(uint64_t id);
-int consumer_send_status_msg(int sock, int ret_code);
-int consumer_send_status_channel(int sock,
-               struct lttng_consumer_channel *channel);
-void notify_thread_del_channel(struct lttng_consumer_local_data *ctx,
-               uint64_t key);
-void consumer_destroy_relayd(struct consumer_relayd_sock_pair *relayd);
-unsigned long consumer_get_consume_start_pos(unsigned long consumed_pos,
-               unsigned long produced_pos, uint64_t nb_packets_per_stream,
-               uint64_t max_sb_size);
-void consumer_add_data_stream(struct lttng_consumer_stream *stream);
-void consumer_del_stream_for_data(struct lttng_consumer_stream *stream);
-void consumer_add_metadata_stream(struct lttng_consumer_stream *stream);
-void consumer_del_stream_for_metadata(struct lttng_consumer_stream *stream);
-int consumer_create_index_file(struct lttng_consumer_stream *stream);
-int lttng_consumer_rotate_channel(struct lttng_consumer_channel *channel,
-               uint64_t key, uint64_t relayd_id, uint32_t metadata,
-               struct lttng_consumer_local_data *ctx);
-int lttng_consumer_stream_is_rotate_ready(struct lttng_consumer_stream *stream);
-int lttng_consumer_rotate_stream(struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_stream *stream);
-int lttng_consumer_rotate_ready_streams(struct lttng_consumer_channel *channel,
-               uint64_t key, struct lttng_consumer_local_data *ctx);
-void lttng_consumer_reset_stream_rotate_state(struct lttng_consumer_stream *stream);
-enum lttcomm_return_code lttng_consumer_create_trace_chunk(
-               const uint64_t *relayd_id, uint64_t session_id,
-               uint64_t chunk_id,
-               time_t chunk_creation_timestamp,
-               const char *chunk_override_name,
-               const struct lttng_credentials *credentials,
-               struct lttng_directory_handle *chunk_directory_handle);
-enum lttcomm_return_code lttng_consumer_close_trace_chunk(
-               const uint64_t *relayd_id, uint64_t session_id,
-               uint64_t chunk_id, time_t chunk_close_timestamp,
-               const enum lttng_trace_chunk_command_type *close_command,
-               char *path);
-enum lttcomm_return_code lttng_consumer_trace_chunk_exists(
-               const uint64_t *relayd_id, uint64_t session_id,
-               uint64_t chunk_id);
-void lttng_consumer_cleanup_relayd(struct consumer_relayd_sock_pair *relayd);
-enum lttcomm_return_code lttng_consumer_init_command(
-               struct lttng_consumer_local_data *ctx,
-               const lttng_uuid sessiond_uuid);
-int lttng_consumer_clear_channel(struct lttng_consumer_channel *channel);
-enum lttcomm_return_code lttng_consumer_open_channel_packets(
-               struct lttng_consumer_channel *channel);
-int consumer_metadata_wakeup_pipe(const struct lttng_consumer_channel *channel);
-void lttng_consumer_sigbus_handle(void *addr);
-
-#endif /* LIB_CONSUMER_H */
diff --git a/src/common/consumer/consumer.hpp b/src/common/consumer/consumer.hpp
new file mode 100644 (file)
index 0000000..869dd65
--- /dev/null
@@ -0,0 +1,1076 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LIB_CONSUMER_H
+#define LIB_CONSUMER_H
+
+#include <limits.h>
+#include <poll.h>
+#include <unistd.h>
+#include <urcu/list.h>
+
+#include <lttng/lttng.h>
+
+#include <common/hashtable/hashtable.hpp>
+#include <common/compat/fcntl.hpp>
+#include <common/uuid.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/pipe.hpp>
+#include <common/index/ctf-index.hpp>
+#include <common/trace-chunk-registry.hpp>
+#include <common/credentials.hpp>
+#include <common/buffer-view.hpp>
+#include <common/dynamic-array.hpp>
+
+struct lttng_consumer_local_data;
+
+/* Commands for consumer */
+enum lttng_consumer_command {
+       LTTNG_CONSUMER_ADD_CHANNEL,
+       LTTNG_CONSUMER_ADD_STREAM,
+       /* pause, delete, active depending on fd state */
+       LTTNG_CONSUMER_UPDATE_STREAM,
+       /* inform the consumer to quit when all fd has hang up */
+       LTTNG_CONSUMER_STOP,    /* deprecated */
+       LTTNG_CONSUMER_ADD_RELAYD_SOCKET,
+       /* Inform the consumer to kill a specific relayd connection */
+       LTTNG_CONSUMER_DESTROY_RELAYD,
+       /* Return to the sessiond if there is data pending for a session */
+       LTTNG_CONSUMER_DATA_PENDING,
+       /* Consumer creates a channel and returns it to sessiond. */
+       LTTNG_CONSUMER_ASK_CHANNEL_CREATION,
+       LTTNG_CONSUMER_GET_CHANNEL,
+       LTTNG_CONSUMER_DESTROY_CHANNEL,
+       LTTNG_CONSUMER_PUSH_METADATA,
+       LTTNG_CONSUMER_CLOSE_METADATA,
+       LTTNG_CONSUMER_SETUP_METADATA,
+       LTTNG_CONSUMER_FLUSH_CHANNEL,
+       LTTNG_CONSUMER_SNAPSHOT_CHANNEL,
+       LTTNG_CONSUMER_SNAPSHOT_METADATA,
+       LTTNG_CONSUMER_STREAMS_SENT,
+       LTTNG_CONSUMER_DISCARDED_EVENTS,
+       LTTNG_CONSUMER_LOST_PACKETS,
+       LTTNG_CONSUMER_CLEAR_QUIESCENT_CHANNEL,
+       LTTNG_CONSUMER_SET_CHANNEL_MONITOR_PIPE,
+       LTTNG_CONSUMER_ROTATE_CHANNEL,
+       LTTNG_CONSUMER_INIT,
+       LTTNG_CONSUMER_CREATE_TRACE_CHUNK,
+       LTTNG_CONSUMER_CLOSE_TRACE_CHUNK,
+       LTTNG_CONSUMER_TRACE_CHUNK_EXISTS,
+       LTTNG_CONSUMER_CLEAR_CHANNEL,
+       LTTNG_CONSUMER_OPEN_CHANNEL_PACKETS,
+};
+
+enum lttng_consumer_type {
+       LTTNG_CONSUMER_UNKNOWN = 0,
+       LTTNG_CONSUMER_KERNEL,
+       LTTNG_CONSUMER64_UST,
+       LTTNG_CONSUMER32_UST,
+};
+
+enum consumer_endpoint_status {
+       CONSUMER_ENDPOINT_ACTIVE,
+       CONSUMER_ENDPOINT_INACTIVE,
+};
+
+enum consumer_channel_output {
+       CONSUMER_CHANNEL_MMAP   = 0,
+       CONSUMER_CHANNEL_SPLICE = 1,
+};
+
+enum consumer_channel_type {
+       CONSUMER_CHANNEL_TYPE_METADATA  = 0,
+       CONSUMER_CHANNEL_TYPE_DATA      = 1,
+};
+
+enum sync_metadata_status {
+       SYNC_METADATA_STATUS_NEW_DATA,
+       SYNC_METADATA_STATUS_NO_DATA,
+       SYNC_METADATA_STATUS_ERROR,
+};
+
+extern struct lttng_consumer_global_data the_consumer_data;
+
+struct stream_list {
+       struct cds_list_head head;
+       unsigned int count;
+};
+
+/* Stub. */
+struct consumer_metadata_cache;
+
+struct lttng_consumer_channel {
+       /* Is the channel published in the channel hash tables? */
+       bool is_published;
+       /*
+        * Was the channel deleted (logically) and waiting to be reclaimed?
+        * If this flag is set, no modification that is not cleaned-up by the
+        * RCU reclamation callback should be made
+        */
+       bool is_deleted;
+       /* HT node used for consumer_data.channel_ht */
+       struct lttng_ht_node_u64 node;
+       /* HT node used for consumer_data.channels_by_session_id_ht */
+       struct lttng_ht_node_u64 channels_by_session_id_ht_node;
+       /* Indexed key. Incremented value in the consumer. */
+       uint64_t key;
+       /* Number of streams referencing this channel */
+       int refcount;
+       /* Tracing session id on the session daemon side. */
+       uint64_t session_id;
+       /* Current trace chunk of the session in which this channel exists. */
+       struct lttng_trace_chunk *trace_chunk;
+       /*
+        * Session id when requesting metadata to the session daemon for
+        * a session with per-PID buffers.
+        */
+       uint64_t session_id_per_pid;
+       /*
+        * In the case of local streams, this field contains the channel's
+        * output path; a path relative to the session's output path.
+        *   e.g. ust/uid/1000/64-bit
+        *
+        * In the case of remote streams, the contents of this field depends
+        * on the version of the relay daemon peer. For 2.11+ peers, the
+        * contents are the same as in the local case. However, for legacy
+        * peers, this contains a path of the form:
+        *   /hostname/session_path/ust/uid/1000/64-bit
+        */
+       char pathname[PATH_MAX];
+       /* Channel name. */
+       char name[LTTNG_SYMBOL_NAME_LEN];
+       /* Relayd id of the channel. -1ULL if it does not apply. */
+       uint64_t relayd_id;
+       /*
+        * Number of streams NOT initialized yet. This is used in order to not
+        * delete this channel if streams are getting initialized.
+        */
+       unsigned int nb_init_stream_left;
+       /* Output type (mmap or splice). */
+       enum consumer_channel_output output;
+       /* Channel type for stream */
+       enum consumer_channel_type type;
+
+       /* For UST */
+       uid_t ust_app_uid;      /* Application UID. */
+       struct lttng_ust_ctl_consumer_channel *uchan;
+       unsigned char uuid[LTTNG_UUID_STR_LEN];
+       /*
+        * Temporary stream list used to store the streams once created and waiting
+        * to be sent to the session daemon by receiving the
+        * LTTNG_CONSUMER_GET_CHANNEL.
+        */
+       struct stream_list streams;
+
+       /*
+        * Set if the channel is metadata. We keep a reference to the stream
+        * because we have to flush data once pushed by the session daemon. For a
+        * regular channel, this is always set to NULL.
+        */
+       struct lttng_consumer_stream *metadata_stream;
+
+       /* for UST */
+       int wait_fd;
+       /* Node within channel thread ht */
+       struct lttng_ht_node_u64 wait_fd_node;
+
+       /* Metadata cache is metadata channel */
+       struct consumer_metadata_cache *metadata_cache;
+
+       /* For UST metadata periodical flush */
+       int switch_timer_enabled;
+       timer_t switch_timer;
+       int switch_timer_error;
+
+       /* For the live mode */
+       int live_timer_enabled;
+       timer_t live_timer;
+       int live_timer_error;
+       /* Channel is part of a live session ? */
+       bool is_live;
+
+       /* For channel monitoring timer. */
+       int monitor_timer_enabled;
+       timer_t monitor_timer;
+
+       /* On-disk circular buffer */
+       uint64_t tracefile_size;
+       uint64_t tracefile_count;
+       /*
+        * Monitor or not the streams of this channel meaning this indicates if the
+        * streams should be sent to the data/metadata thread or added to the no
+        * monitor list of the channel.
+        */
+       unsigned int monitor;
+
+       /*
+        * Channel lock.
+        *
+        * This lock protects against concurrent update of channel.
+        *
+        * This is nested INSIDE the consumer data lock.
+        * This is nested OUTSIDE the channel timer lock.
+        * This is nested OUTSIDE the metadata cache lock.
+        * This is nested OUTSIDE stream lock.
+        * This is nested OUTSIDE consumer_relayd_sock_pair lock.
+        */
+       pthread_mutex_t lock;
+
+       /*
+        * Channel teardown lock.
+        *
+        * This lock protect against teardown of channel. It is _never_
+        * taken by the timer handler.
+        *
+        * This is nested INSIDE the consumer data lock.
+        * This is nested INSIDE the channel lock.
+        * This is nested OUTSIDE the metadata cache lock.
+        * This is nested OUTSIDE stream lock.
+        * This is nested OUTSIDE consumer_relayd_sock_pair lock.
+        */
+       pthread_mutex_t timer_lock;
+
+       /* Timer value in usec for live streaming. */
+       unsigned int live_timer_interval;
+
+       int *stream_fds;
+       int nr_stream_fds;
+       char root_shm_path[PATH_MAX];
+       char shm_path[PATH_MAX];
+       /* Only set for UST channels. */
+       LTTNG_OPTIONAL(struct lttng_credentials) buffer_credentials;
+       /* Total number of discarded events for that channel. */
+       uint64_t discarded_events;
+       /* Total number of missed packets due to overwriting (overwrite). */
+       uint64_t lost_packets;
+
+       bool streams_sent_to_relayd;
+};
+
+struct stream_subbuffer {
+       union {
+               /*
+                * CONSUMER_CHANNEL_SPLICE
+                * No ownership assumed.
+                */
+               int fd;
+               /* CONSUMER_CHANNEL_MMAP */
+               struct lttng_buffer_view buffer;
+       } buffer;
+       union {
+               /*
+                * Common members are fine to access through either
+                * union entries (as per C11, Common Initial Sequence).
+                */
+               struct {
+                       unsigned long subbuf_size;
+                       unsigned long padded_subbuf_size;
+                       uint64_t version;
+                       /*
+                        * Left unset when unsupported.
+                        *
+                        * Indicates that this is the last sub-buffer of
+                        * a series of sub-buffer that makes-up a coherent
+                        * (parseable) unit of metadata.
+                        */
+                       LTTNG_OPTIONAL(bool) coherent;
+               } metadata;
+               struct {
+                       unsigned long subbuf_size;
+                       unsigned long padded_subbuf_size;
+                       uint64_t packet_size;
+                       uint64_t content_size;
+                       uint64_t timestamp_begin;
+                       uint64_t timestamp_end;
+                       uint64_t events_discarded;
+                       /* Left unset when unsupported. */
+                       LTTNG_OPTIONAL(uint64_t) sequence_number;
+                       uint64_t stream_id;
+                       /* Left unset when unsupported. */
+                       LTTNG_OPTIONAL(uint64_t) stream_instance_id;
+               } data;
+       } info;
+};
+
+enum get_next_subbuffer_status {
+       GET_NEXT_SUBBUFFER_STATUS_OK,
+       GET_NEXT_SUBBUFFER_STATUS_NO_DATA,
+       GET_NEXT_SUBBUFFER_STATUS_ERROR,
+};
+
+/*
+ * Perform any operation required to acknowledge
+ * the wake-up of a consumer stream (e.g. consume a byte on a wake-up pipe).
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef int (*on_wake_up_cb)(struct lttng_consumer_stream *);
+
+/*
+ * Perform any operation required before a consumer stream is put
+ * to sleep before awaiting a data availability notification.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef int (*on_sleep_cb)(struct lttng_consumer_stream *,
+               struct lttng_consumer_local_data *);
+
+/*
+ * Acquire the subbuffer at the current 'consumed' position.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef enum get_next_subbuffer_status (*get_next_subbuffer_cb)(
+               struct lttng_consumer_stream *, struct stream_subbuffer *);
+
+/*
+ * Populate the stream_subbuffer's info member. The info to populate
+ * depends on the type (metadata/data) of the stream.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef int (*extract_subbuffer_info_cb)(
+               struct lttng_consumer_stream *, struct stream_subbuffer *);
+
+/*
+ * Invoked after a subbuffer's info has been filled.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef int (*pre_consume_subbuffer_cb)(struct lttng_consumer_stream *,
+               const struct stream_subbuffer *);
+
+/*
+ * Consume subbuffer contents.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef ssize_t (*consume_subbuffer_cb)(struct lttng_consumer_local_data *,
+               struct lttng_consumer_stream *,
+               const struct stream_subbuffer *);
+
+/*
+ * Release the current subbuffer and advance the 'consumed' position by
+ * one subbuffer.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef int (*put_next_subbuffer_cb)(struct lttng_consumer_stream *,
+               struct stream_subbuffer *);
+
+/*
+ * Invoked after consuming a subbuffer.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef int (*post_consume_cb)(struct lttng_consumer_stream *,
+               const struct stream_subbuffer *,
+               struct lttng_consumer_local_data *);
+
+/*
+ * Send a live beacon if no data is available.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef int (*send_live_beacon_cb)(struct lttng_consumer_stream *);
+
+/*
+ * Lock the stream and channel locks and any other stream-type specific
+ * lock that need to be acquired during the processing of an
+ * availability notification.
+ */
+typedef void (*lock_cb)(struct lttng_consumer_stream *);
+
+/*
+ * Unlock the stream and channel locks and any other stream-type specific
+ * lock before sleeping until the next availability notification.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef void (*unlock_cb)(struct lttng_consumer_stream *);
+
+/*
+ * Assert that the stream and channel lock and any other stream type specific
+ * lock that need to be acquired during the processing of a read_subbuffer
+ * operation is acquired.
+ */
+typedef void (*assert_locked_cb)(struct lttng_consumer_stream *);
+
+/*
+ * Invoked when a subbuffer's metadata version does not match the last
+ * known metadata version.
+ *
+ * Stream and channel locks are acquired during this call.
+ */
+typedef void (*reset_metadata_cb)(struct lttng_consumer_stream *);
+
+/*
+ * Internal representation of the streams, sessiond_key is used to identify
+ * uniquely a stream.
+ */
+struct lttng_consumer_stream {
+       /* HT node used by the data_ht and metadata_ht */
+       struct lttng_ht_node_u64 node;
+       /* stream indexed per channel key node */
+       struct lttng_ht_node_u64 node_channel_id;
+       /* HT node used in consumer_data.stream_list_ht */
+       struct lttng_ht_node_u64 node_session_id;
+       /* Pointer to associated channel. */
+       struct lttng_consumer_channel *chan;
+       /*
+        * Current trace chunk. Holds a reference to the trace chunk.
+        * `chunk` can be NULL when a stream is not associated to a chunk, e.g.
+        * when it was created in the context of a no-output session.
+        */
+       struct lttng_trace_chunk *trace_chunk;
+
+       /* Key by which the stream is indexed for 'node'. */
+       uint64_t key;
+       /*
+        * File descriptor of the data output file. This can be either a file or a
+        * socket fd for relayd streaming.
+        */
+       int out_fd; /* output file to write the data */
+       /* Write position in the output file descriptor */
+       off_t out_fd_offset;
+       /* Amount of bytes written to the output */
+       uint64_t output_written;
+       int shm_fd_is_copy;
+       int data_read;
+       int hangup_flush_done;
+
+       /*
+        * Whether the stream is in a "complete" state (e.g. it does not have a
+        * partially written sub-buffer.
+        *
+        * Initialized to "false" on stream creation (first packet is empty).
+        *
+        * The various transitions of the quiescent state are:
+        *     - On "start" tracing: set to false, since the stream is not
+        *       "complete".
+        *     - On "stop" tracing: if !quiescent -> flush FINAL (update
+        *       timestamp_end), and set to true; the stream has entered a
+        *       complete/quiescent state.
+        *     - On "destroy" or stream/application hang-up: if !quiescent ->
+        *       flush FINAL, and set to true.
+        *
+        * NOTE: Update and read are protected by the stream lock.
+        */
+       bool quiescent;
+
+       /*
+        * True if the sequence number is not available (lttng-modules < 2.8).
+        */
+       bool sequence_number_unavailable;
+
+       /*
+        * metadata_timer_lock protects flags waiting_on_metadata and
+        * missed_metadata_flush.
+        */
+       pthread_mutex_t metadata_timer_lock;
+       /*
+        * Flag set when awaiting metadata to be pushed. Used in the
+        * timer thread to skip waiting on the stream (and stream lock) to
+        * ensure we can proceed to flushing metadata in live mode.
+        */
+       bool waiting_on_metadata;
+       /* Raised when a timer misses a metadata flush. */
+       bool missed_metadata_flush;
+
+       enum lttng_event_output output;
+       /* Maximum subbuffer size (in bytes). */
+       unsigned long max_sb_size;
+
+       /*
+        * Still used by the kernel for MMAP output. For UST, the ustctl getter is
+        * used for the mmap base and offset.
+        */
+       void *mmap_base;
+       unsigned long mmap_len;
+
+       /* For UST */
+
+       int wait_fd;
+       /* Network sequence number. Indicating on which relayd socket it goes. */
+       uint64_t net_seq_idx;
+       /*
+        * Indicate if this stream was successfully sent to a relayd. This is set
+        * after the refcount of the relayd is incremented and is checked when the
+        * stream is closed before decrementing the refcount in order to avoid an
+        * unbalanced state.
+        */
+       unsigned int sent_to_relayd;
+
+       /* Identify if the stream is the metadata */
+       unsigned int metadata_flag;
+       /*
+        * Last known metadata version, reset the metadata file in case
+        * of change.
+        */
+       uint64_t metadata_version;
+       /* Used when the stream is set for network streaming */
+       uint64_t relayd_stream_id;
+       /*
+        * When sending a stream packet to a relayd, this number is used to track
+        * the packet sent by the consumer and seen by the relayd. When sending the
+        * data header to the relayd, this number is sent and if the transmission
+        * was successful, it is incremented.
+        *
+        * Even if the full data is not fully transmitted it won't matter since
+        * only two possible error can happen after that where either the relayd
+        * died or a read error is detected on the stream making this value useless
+        * after that.
+        *
+        * This value SHOULD be read/updated atomically or with the lock acquired.
+        */
+       uint64_t next_net_seq_num;
+       /*
+        * Lock to use the stream FDs since they are used between threads.
+        *
+        * This is nested INSIDE the consumer_data lock.
+        * This is nested INSIDE the channel lock.
+        * This is nested INSIDE the channel timer lock.
+        * This is nested OUTSIDE the metadata cache lock.
+        * This is nested OUTSIDE consumer_relayd_sock_pair lock.
+        */
+       pthread_mutex_t lock;
+       /* Tracing session id */
+       uint64_t session_id;
+       /*
+        * Indicates if the stream end point is still active or not (network
+        * streaming or local file system). The thread "owning" the stream is
+        * handling this status and can be notified of a state change through the
+        * consumer data appropriate pipe.
+        */
+       enum consumer_endpoint_status endpoint_status;
+       /* Stream name. Format is: <channel_name>_<cpu_number> */
+       char name[LTTNG_SYMBOL_NAME_LEN];
+       /* Internal state of libustctl. */
+       struct lttng_ust_ctl_consumer_stream *ustream;
+       struct cds_list_head send_node;
+       /* On-disk circular buffer */
+       uint64_t tracefile_size_current;
+       uint64_t tracefile_count_current;
+       /*
+        * Monitor or not the streams of this channel meaning this indicates if the
+        * streams should be sent to the data/metadata thread or added to the no
+        * monitor list of the channel.
+        */
+       unsigned int monitor;
+       /*
+        * Indicate if the stream is globally visible meaning that it has been
+        * added to the multiple hash tables. If *not* set, NO lock should be
+        * acquired in the destroy path.
+        */
+       unsigned int globally_visible;
+       /*
+        * Pipe to wake up the metadata poll thread when the UST metadata
+        * cache is updated.
+        */
+       int ust_metadata_poll_pipe[2];
+       /*
+        * How much metadata was read from the metadata cache and sent
+        * to the channel.
+        */
+       uint64_t ust_metadata_pushed;
+       /*
+        * Copy of the last discarded event value to detect the overflow of
+        * the counter.
+        */
+       uint64_t last_discarded_events;
+       /* Copy of the sequence number of the last packet extracted. */
+       uint64_t last_sequence_number;
+       /*
+        * Index file object of the index file for this stream.
+        */
+       struct lttng_index_file *index_file;
+
+       /*
+        * Local pipe to extract data when using splice.
+        */
+       int splice_pipe[2];
+
+       /*
+        * Rendez-vous point between data and metadata stream in live mode.
+        */
+       pthread_cond_t metadata_rdv;
+       pthread_mutex_t metadata_rdv_lock;
+
+       /*
+        * rotate_position represents the packet sequence number of the last
+        * packet which belongs to the current trace chunk prior to the rotation.
+        * When that position is reached, this tracefile can be closed and a
+        * new one is created in channel_read_only_attributes.path.
+        */
+       uint64_t rotate_position;
+
+       /* Whether or not a packet was opened during the current trace chunk. */
+       bool opened_packet_in_current_trace_chunk;
+
+       /*
+        * Read-only copies of channel values. We cannot safely access the
+        * channel from a stream, so we need to have a local copy of these
+        * fields in the stream object. These fields should be removed from
+        * the stream objects when we introduce refcounting.
+        */
+       struct {
+               uint64_t tracefile_size;
+       } channel_read_only_attributes;
+
+       /*
+        * Flag to inform the data or metadata thread that a stream is
+        * ready to be rotated.
+        */
+       bool rotate_ready;
+
+       /* Indicate if the stream still has some data to be read. */
+       unsigned int has_data:1;
+       /*
+        * Inform the consumer or relay to reset the metadata
+        * file before writing in it (regeneration).
+        */
+       unsigned int reset_metadata_flag:1;
+       struct {
+               /*
+                * Invoked in the order of declaration.
+                * See callback type definitions.
+                */
+               lock_cb lock;
+               on_wake_up_cb on_wake_up;
+               get_next_subbuffer_cb get_next_subbuffer;
+               extract_subbuffer_info_cb extract_subbuffer_info;
+               pre_consume_subbuffer_cb pre_consume_subbuffer;
+               reset_metadata_cb reset_metadata;
+               consume_subbuffer_cb consume_subbuffer;
+               put_next_subbuffer_cb put_next_subbuffer;
+               struct lttng_dynamic_array post_consume_cbs;
+               send_live_beacon_cb send_live_beacon;
+               on_sleep_cb on_sleep;
+               unlock_cb unlock;
+               assert_locked_cb assert_locked;
+       } read_subbuffer_ops;
+       struct metadata_bucket *metadata_bucket;
+};
+
+/*
+ * Internal representation of a relayd socket pair.
+ */
+struct consumer_relayd_sock_pair {
+       /* Network sequence number. */
+       uint64_t net_seq_idx;
+       /* Number of stream associated with this relayd */
+       int refcount;
+
+       /*
+        * This flag indicates whether or not we should destroy this object. The
+        * destruction should ONLY occurs when this flag is set and the refcount is
+        * set to zero.
+        */
+       unsigned int destroy_flag;
+
+       /*
+        * Mutex protecting the control socket to avoid out of order packets
+        * between threads sending data to the relayd. Since metadata data is sent
+        * over that socket, at least two sendmsg() are needed (header + data)
+        * creating a race for packets to overlap between threads using it.
+        *
+        * This is nested INSIDE the consumer_data lock.
+        * This is nested INSIDE the stream lock.
+        */
+       pthread_mutex_t ctrl_sock_mutex;
+
+       /* Control socket. Command and metadata are passed over it */
+       struct lttcomm_relayd_sock control_sock;
+
+       /*
+        * We don't need a mutex at this point since we only splice or write single
+        * large chunk of data with a header appended at the begining. Moreover,
+        * this socket is for now only used in a single thread.
+        */
+       struct lttcomm_relayd_sock data_sock;
+       struct lttng_ht_node_u64 node;
+
+       /* Session id on both sides for the sockets. */
+       uint64_t relayd_session_id;
+       uint64_t sessiond_session_id;
+       struct lttng_consumer_local_data *ctx;
+};
+
+/*
+ * UST consumer local data to the program. One or more instance per
+ * process.
+ */
+struct lttng_consumer_local_data {
+       /*
+        * Function to call when data is available on a buffer.
+        * Returns the number of bytes read, or negative error value.
+        */
+       ssize_t (*on_buffer_ready)(struct lttng_consumer_stream *stream,
+                       struct lttng_consumer_local_data *ctx,
+                       bool locked_by_caller);
+       /*
+        * function to call when we receive a new channel, it receives a
+        * newly allocated channel, depending on the return code of this
+        * function, the new channel will be handled by the application
+        * or the library.
+        *
+        * Returns:
+        *    > 0 (success, FD is kept by application)
+        *   == 0 (success, FD is left to library)
+        *    < 0 (error)
+        */
+       int (*on_recv_channel)(struct lttng_consumer_channel *channel);
+       /*
+        * function to call when we receive a new stream, it receives a
+        * newly allocated stream, depending on the return code of this
+        * function, the new stream will be handled by the application
+        * or the library.
+        *
+        * Returns:
+        *    > 0 (success, FD is kept by application)
+        *   == 0 (success, FD is left to library)
+        *    < 0 (error)
+        */
+       int (*on_recv_stream)(struct lttng_consumer_stream *stream);
+       /*
+        * function to call when a stream is getting updated by the session
+        * daemon, this function receives the sessiond key and the new
+        * state, depending on the return code of this function the
+        * update of state for the stream is handled by the application
+        * or the library.
+        *
+        * Returns:
+        *    > 0 (success, FD is kept by application)
+        *   == 0 (success, FD is left to library)
+        *    < 0 (error)
+        */
+       int (*on_update_stream)(uint64_t sessiond_key, uint32_t state);
+       enum lttng_consumer_type type;
+       /* socket to communicate errors with sessiond */
+       int consumer_error_socket;
+       /* socket to ask metadata to sessiond. */
+       int consumer_metadata_socket;
+       /*
+        * Protect consumer_metadata_socket.
+        *
+        * This is nested OUTSIDE the metadata cache lock.
+        */
+       pthread_mutex_t metadata_socket_lock;
+       /* socket to exchange commands with sessiond */
+       char *consumer_command_sock_path;
+       /* communication with splice */
+       int consumer_channel_pipe[2];
+       /* Data stream poll thread pipe. To transfer data stream to the thread */
+       struct lttng_pipe *consumer_data_pipe;
+
+       /*
+        * Data thread use that pipe to catch wakeup from read subbuffer that
+        * detects that there is still data to be read for the stream encountered.
+        * Before doing so, the stream is flagged to indicate that there is still
+        * data to be read.
+        *
+        * Both pipes (read/write) are owned and used inside the data thread.
+        */
+       struct lttng_pipe *consumer_wakeup_pipe;
+       /* Indicate if the wakeup thread has been notified. */
+       unsigned int has_wakeup:1;
+
+       /* to let the signal handler wake up the fd receiver thread */
+       int consumer_should_quit[2];
+       /* Metadata poll thread pipe. Transfer metadata stream to it */
+       struct lttng_pipe *consumer_metadata_pipe;
+       /*
+        * Pipe used by the channel monitoring timers to provide state samples
+        * to the session daemon (write-only).
+        */
+       int channel_monitor_pipe;
+       LTTNG_OPTIONAL(lttng_uuid) sessiond_uuid;
+};
+
+/*
+ * Library-level data. One instance per process.
+ */
+struct lttng_consumer_global_data {
+       /*
+        * At this time, this lock is used to ensure coherence between the count
+        * and number of element in the hash table. It's also a protection for
+        * concurrent read/write between threads.
+        *
+        * This is nested OUTSIDE the stream lock.
+        * This is nested OUTSIDE the consumer_relayd_sock_pair lock.
+        */
+       pthread_mutex_t lock {};
+
+       /*
+        * Number of streams in the data stream hash table declared outside.
+        * Protected by consumer_data.lock.
+        */
+       int stream_count = 0;
+
+       /* Channel hash table protected by consumer_data.lock. */
+       struct lttng_ht *channel_ht = nullptr;
+       /* Channel hash table indexed by session id. */
+       struct lttng_ht *channels_by_session_id_ht = nullptr;
+       /*
+        * Flag specifying if the local array of FDs needs update in the
+        * poll function. Protected by consumer_data.lock.
+        */
+       unsigned int need_update = 1;
+       enum lttng_consumer_type type = LTTNG_CONSUMER_UNKNOWN;
+
+       /*
+        * Relayd socket(s) hashtable indexed by network sequence number. Each
+        * stream has an index which associate the right relayd socket to use.
+        */
+       struct lttng_ht *relayd_ht = nullptr;
+
+       /*
+        * This hash table contains all streams (metadata and data) indexed by
+        * session id. In other words, the ht is indexed by session id and each
+        * bucket contains the list of associated streams.
+        *
+        * This HT uses the "node_session_id" of the consumer stream.
+        */
+       struct lttng_ht *stream_list_ht = nullptr;
+
+       /*
+        * This HT uses the "node_channel_id" of the consumer stream.
+        */
+       struct lttng_ht *stream_per_chan_id_ht = nullptr;
+
+       /*
+        * Trace chunk registry indexed by (session_id, chunk_id).
+        */
+       struct lttng_trace_chunk_registry *chunk_registry = nullptr;
+};
+
+/*
+ * Set to nonzero when the consumer is exiting. Updated by signal
+ * handler and thread exit, read by threads.
+ */
+extern int consumer_quit;
+
+/*
+ * Set to nonzero when the consumer is exiting. Updated by signal
+ * handler and thread exit, read by threads.
+ */
+extern int consumer_quit;
+
+/*
+ * Flag used to temporarily pause data consumption from testpoints.
+ *
+ * This variable is dlsym-ed from a test, so needs to be exported.
+ */
+LTTNG_EXPORT extern int data_consumption_paused;
+
+/* Return a human-readable consumer type string that is suitable for logging. */
+static inline
+const char *lttng_consumer_type_str(enum lttng_consumer_type type)
+{
+       switch (type) {
+       case LTTNG_CONSUMER_UNKNOWN:
+               return "unknown";
+       case LTTNG_CONSUMER_KERNEL:
+               return "kernel";
+       case LTTNG_CONSUMER32_UST:
+               return "32-bit user space";
+       case LTTNG_CONSUMER64_UST:
+               return "64-bit user space";
+       default:
+               abort();
+       }
+}
+
+/*
+ * Init consumer data structures.
+ */
+int lttng_consumer_init(void);
+
+/*
+ * Set the error socket for communication with a session daemon.
+ */
+void lttng_consumer_set_error_sock(struct lttng_consumer_local_data *ctx,
+               int sock);
+
+/*
+ * Set the command socket path for communication with a session daemon.
+ */
+void lttng_consumer_set_command_sock_path(
+               struct lttng_consumer_local_data *ctx, char *sock);
+
+/*
+ * Send return code to session daemon.
+ *
+ * Returns the return code of sendmsg : the number of bytes transmitted or -1
+ * on error.
+ */
+int lttng_consumer_send_error(struct lttng_consumer_local_data *ctx, int cmd);
+
+/*
+ * Called from signal handler to ensure a clean exit.
+ */
+void lttng_consumer_should_exit(struct lttng_consumer_local_data *ctx);
+
+/*
+ * Cleanup the daemon's socket on exit.
+ */
+void lttng_consumer_cleanup(void);
+
+/*
+ * Poll on the should_quit pipe and the command socket return -1 on error and
+ * should exit, 0 if data is available on the command socket
+ */
+int lttng_consumer_poll_socket(struct pollfd *kconsumer_sockpoll);
+
+/*
+ * Copy the fields from the channel that need to be accessed (read-only)
+ * directly from the stream.
+ */
+void consumer_stream_update_channel_attributes(
+               struct lttng_consumer_stream *stream,
+               struct lttng_consumer_channel *channel);
+
+struct lttng_consumer_stream *consumer_allocate_stream(
+               struct lttng_consumer_channel *channel,
+               uint64_t channel_key,
+               uint64_t stream_key,
+               const char *channel_name,
+               uint64_t relayd_id,
+               uint64_t session_id,
+               struct lttng_trace_chunk *trace_chunk,
+               int cpu,
+               int *alloc_ret,
+               enum consumer_channel_type type,
+               unsigned int monitor);
+struct lttng_consumer_channel *consumer_allocate_channel(uint64_t key,
+               uint64_t session_id,
+               const uint64_t *chunk_id,
+               const char *pathname,
+               const char *name,
+               uint64_t relayd_id,
+               enum lttng_event_output output,
+               uint64_t tracefile_size,
+               uint64_t tracefile_count,
+               uint64_t session_id_per_pid,
+               unsigned int monitor,
+               unsigned int live_timer_interval,
+               bool is_in_live_session,
+               const char *root_shm_path,
+               const char *shm_path);
+void consumer_del_stream(struct lttng_consumer_stream *stream,
+               struct lttng_ht *ht);
+void consumer_del_metadata_stream(struct lttng_consumer_stream *stream,
+               struct lttng_ht *ht);
+int consumer_add_channel(struct lttng_consumer_channel *channel,
+               struct lttng_consumer_local_data *ctx);
+void consumer_del_channel(struct lttng_consumer_channel *channel);
+
+/* lttng-relayd consumer command */
+struct consumer_relayd_sock_pair *consumer_find_relayd(uint64_t key);
+int consumer_send_relayd_stream(struct lttng_consumer_stream *stream, char *path);
+int consumer_send_relayd_streams_sent(uint64_t net_seq_idx);
+void close_relayd_stream(struct lttng_consumer_stream *stream);
+struct lttng_consumer_channel *consumer_find_channel(uint64_t key);
+int consumer_handle_stream_before_relayd(struct lttng_consumer_stream *stream,
+               size_t data_size);
+void consumer_steal_stream_key(int key, struct lttng_ht *ht);
+
+struct lttng_consumer_local_data *lttng_consumer_create(
+               enum lttng_consumer_type type,
+               ssize_t (*buffer_ready)(struct lttng_consumer_stream *stream,
+                       struct lttng_consumer_local_data *ctx,
+                       bool locked_by_caller),
+               int (*recv_channel)(struct lttng_consumer_channel *channel),
+               int (*recv_stream)(struct lttng_consumer_stream *stream),
+               int (*update_stream)(uint64_t sessiond_key, uint32_t state));
+void lttng_consumer_destroy(struct lttng_consumer_local_data *ctx);
+ssize_t lttng_consumer_on_read_subbuffer_mmap(
+               struct lttng_consumer_stream *stream,
+               const struct lttng_buffer_view *buffer,
+               unsigned long padding);
+ssize_t lttng_consumer_on_read_subbuffer_splice(
+               struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_stream *stream, unsigned long len,
+               unsigned long padding);
+int lttng_consumer_sample_snapshot_positions(struct lttng_consumer_stream *stream);
+int lttng_consumer_take_snapshot(struct lttng_consumer_stream *stream);
+int lttng_consumer_get_produced_snapshot(struct lttng_consumer_stream *stream,
+               unsigned long *pos);
+int lttng_consumer_get_consumed_snapshot(struct lttng_consumer_stream *stream,
+               unsigned long *pos);
+int lttng_ustconsumer_get_wakeup_fd(struct lttng_consumer_stream *stream);
+int lttng_ustconsumer_close_wakeup_fd(struct lttng_consumer_stream *stream);
+void *consumer_thread_metadata_poll(void *data);
+void *consumer_thread_data_poll(void *data);
+void *consumer_thread_sessiond_poll(void *data);
+void *consumer_thread_channel_poll(void *data);
+int lttng_consumer_recv_cmd(struct lttng_consumer_local_data *ctx,
+               int sock, struct pollfd *consumer_sockpoll);
+
+ssize_t lttng_consumer_read_subbuffer(struct lttng_consumer_stream *stream,
+               struct lttng_consumer_local_data *ctx,
+               bool locked_by_caller);
+int lttng_consumer_on_recv_stream(struct lttng_consumer_stream *stream);
+void consumer_add_relayd_socket(uint64_t net_seq_idx, int sock_type,
+               struct lttng_consumer_local_data *ctx, int sock,
+               struct pollfd *consumer_sockpoll, struct lttcomm_relayd_sock *relayd_sock,
+               uint64_t sessiond_id, uint64_t relayd_session_id);
+void consumer_flag_relayd_for_destroy(
+               struct consumer_relayd_sock_pair *relayd);
+int consumer_data_pending(uint64_t id);
+int consumer_send_status_msg(int sock, int ret_code);
+int consumer_send_status_channel(int sock,
+               struct lttng_consumer_channel *channel);
+void notify_thread_del_channel(struct lttng_consumer_local_data *ctx,
+               uint64_t key);
+void consumer_destroy_relayd(struct consumer_relayd_sock_pair *relayd);
+unsigned long consumer_get_consume_start_pos(unsigned long consumed_pos,
+               unsigned long produced_pos, uint64_t nb_packets_per_stream,
+               uint64_t max_sb_size);
+void consumer_add_data_stream(struct lttng_consumer_stream *stream);
+void consumer_del_stream_for_data(struct lttng_consumer_stream *stream);
+void consumer_add_metadata_stream(struct lttng_consumer_stream *stream);
+void consumer_del_stream_for_metadata(struct lttng_consumer_stream *stream);
+int consumer_create_index_file(struct lttng_consumer_stream *stream);
+int lttng_consumer_rotate_channel(struct lttng_consumer_channel *channel,
+               uint64_t key, uint64_t relayd_id, uint32_t metadata,
+               struct lttng_consumer_local_data *ctx);
+int lttng_consumer_stream_is_rotate_ready(struct lttng_consumer_stream *stream);
+int lttng_consumer_rotate_stream(struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_stream *stream);
+int lttng_consumer_rotate_ready_streams(struct lttng_consumer_channel *channel,
+               uint64_t key, struct lttng_consumer_local_data *ctx);
+void lttng_consumer_reset_stream_rotate_state(struct lttng_consumer_stream *stream);
+enum lttcomm_return_code lttng_consumer_create_trace_chunk(
+               const uint64_t *relayd_id, uint64_t session_id,
+               uint64_t chunk_id,
+               time_t chunk_creation_timestamp,
+               const char *chunk_override_name,
+               const struct lttng_credentials *credentials,
+               struct lttng_directory_handle *chunk_directory_handle);
+enum lttcomm_return_code lttng_consumer_close_trace_chunk(
+               const uint64_t *relayd_id, uint64_t session_id,
+               uint64_t chunk_id, time_t chunk_close_timestamp,
+               const enum lttng_trace_chunk_command_type *close_command,
+               char *path);
+enum lttcomm_return_code lttng_consumer_trace_chunk_exists(
+               const uint64_t *relayd_id, uint64_t session_id,
+               uint64_t chunk_id);
+void lttng_consumer_cleanup_relayd(struct consumer_relayd_sock_pair *relayd);
+enum lttcomm_return_code lttng_consumer_init_command(
+               struct lttng_consumer_local_data *ctx,
+               const lttng_uuid sessiond_uuid);
+int lttng_consumer_clear_channel(struct lttng_consumer_channel *channel);
+enum lttcomm_return_code lttng_consumer_open_channel_packets(
+               struct lttng_consumer_channel *channel);
+int consumer_metadata_wakeup_pipe(const struct lttng_consumer_channel *channel);
+void lttng_consumer_sigbus_handle(void *addr);
+
+#endif /* LIB_CONSUMER_H */
index 160185def7b77fe5e05ff5434c486eae9c405092..6dd26675e615ba3770259f56ab9e9f4fa539fcea 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include "metadata-bucket.h"
+#include "metadata-bucket.hpp"
 
-#include <common/buffer-view.h>
-#include <common/consumer/consumer.h>
-#include <common/dynamic-buffer.h>
-#include <common/macros.h>
-#include <common/error.h>
+#include <common/buffer-view.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/macros.hpp>
+#include <common/error.hpp>
 
 struct metadata_bucket {
        struct lttng_dynamic_buffer content;
@@ -62,6 +62,25 @@ void metadata_bucket_reset(struct metadata_bucket *bucket)
        bucket->buffer_count = 0;
 }
 
+struct metadata_packet_header {
+       uint32_t magic;                 /* 0x75D11D57 */
+       uint8_t  uuid[16];              /* Unique Universal Identifier */
+       uint32_t checksum;              /* 0 if unused */
+       uint32_t content_size;          /* in bits */
+       uint32_t packet_size;           /* in bits */
+       uint8_t  compression_scheme;    /* 0 if unused */
+       uint8_t  encryption_scheme;     /* 0 if unused */
+       uint8_t  checksum_scheme;       /* 0 if unused */
+       uint8_t  major;                 /* CTF spec major version number */
+       uint8_t  minor;                 /* CTF spec minor version number */
+       uint8_t  header_end[0];
+};
+
+static size_t metadata_length(void)
+{
+       return offsetof(struct metadata_packet_header, header_end);
+}
+
 enum metadata_bucket_status metadata_bucket_fill(struct metadata_bucket *bucket,
                const struct stream_subbuffer *buffer)
 {
@@ -71,10 +90,6 @@ enum metadata_bucket_status metadata_bucket_fill(struct metadata_bucket *bucket,
        enum metadata_bucket_status status;
        const bool should_flush =
                        LTTNG_OPTIONAL_GET(buffer->info.metadata.coherent);
-       const size_t padding_this_buffer =
-                       buffer->info.metadata.padded_subbuf_size -
-                       buffer->info.metadata.subbuf_size;
-       size_t flush_size;
 
        DBG("Metadata bucket filled with %zu bytes buffer view, sub-buffer size: %lu, padded sub-buffer size: %lu, coherent: %s",
                        buffer->buffer.buffer.size,
@@ -86,22 +101,20 @@ enum metadata_bucket_status metadata_bucket_fill(struct metadata_bucket *bucket,
         * flushed, don't copy it unecessarily; just flush it directly.
         */
        if (!should_flush || bucket->buffer_count != 0) {
+               struct lttng_buffer_view append_view;
+
                /*
-                * Append the _padded_ subbuffer since they are combined
+                * Append the subbuffer since they are combined
                 * into a single "virtual" subbuffer that will be
                 * flushed at once.
                 *
-                * This means that some padding will be sent over the
-                * network, but should not represent a large amount
-                * of data as incoherent subbuffers are typically
-                * pretty full.
-                *
-                * The padding of the last subbuffer (coherent) added to
-                * the bucket is not sent, which is what really matters
-                * from an efficiency point of view.
+                * Peel off metadata header and padding, only preserve
+                * the json-seq metadata.
                 */
+               append_view = lttng_buffer_view_from_view(&buffer->buffer.buffer, metadata_length(),
+                               buffer->info.metadata.subbuf_size - metadata_length());
                ret = lttng_dynamic_buffer_append_view(
-                       &bucket->content, &buffer->buffer.buffer);
+                       &bucket->content, &append_view);
                if (ret) {
                        status = METADATA_BUCKET_STATUS_ERROR;
                        goto end;
@@ -116,14 +129,8 @@ enum metadata_bucket_status metadata_bucket_fill(struct metadata_bucket *bucket,
 
        flushed_view = bucket->content.size != 0 ?
                lttng_buffer_view_from_dynamic_buffer(&bucket->content, 0, -1) :
-               lttng_buffer_view_from_view(&buffer->buffer.buffer, 0, -1);
-
-       /*
-        * The flush is done with the size of all padded sub-buffers, except
-        * for the last one which we can safely "trim". The padding of the last
-        * packet will be reconstructed by the relay daemon.
-        */
-       flush_size = flushed_view.size - padding_this_buffer;
+               lttng_buffer_view_from_view(&buffer->buffer.buffer, metadata_length(),
+                               buffer->info.metadata.subbuf_size - metadata_length());
 
        flushed_subbuffer = (typeof(flushed_subbuffer)) {
                .buffer = {
@@ -131,7 +138,7 @@ enum metadata_bucket_status metadata_bucket_fill(struct metadata_bucket *bucket,
                },
                .info = {
                        .metadata = {
-                               .subbuf_size = flush_size,
+                               .subbuf_size = flushed_view.size,
                                .padded_subbuf_size = flushed_view.size,
                                .version = buffer->info.metadata.version,
                                .coherent = buffer->info.metadata.coherent,
diff --git a/src/common/consumer/metadata-bucket.h b/src/common/consumer/metadata-bucket.h
deleted file mode 100644 (file)
index 993d3f4..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef METADATA_BUCKET_H
-#define METADATA_BUCKET_H
-
-#include <common/consumer/consumer.h>
-
-struct metadata_bucket;
-
-typedef ssize_t (*metadata_bucket_flush_cb)(
-               const struct stream_subbuffer *buffer, void *data);
-
-enum metadata_bucket_status {
-       METADATA_BUCKET_STATUS_OK,
-       METADATA_BUCKET_STATUS_ERROR,
-};
-
-struct metadata_bucket *metadata_bucket_create(
-               metadata_bucket_flush_cb flush, void *data);
-
-void metadata_bucket_destroy(struct metadata_bucket *bucket);
-
-enum metadata_bucket_status metadata_bucket_fill(struct metadata_bucket *bucket,
-               const struct stream_subbuffer *buffer);
-
-void metadata_bucket_reset(struct metadata_bucket *bucket);
-
-#endif /* METADATA_BUCKET_H */
diff --git a/src/common/consumer/metadata-bucket.hpp b/src/common/consumer/metadata-bucket.hpp
new file mode 100644 (file)
index 0000000..2c6961c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef METADATA_BUCKET_H
+#define METADATA_BUCKET_H
+
+#include <common/consumer/consumer.hpp>
+
+struct metadata_bucket;
+
+typedef ssize_t (*metadata_bucket_flush_cb)(
+               const struct stream_subbuffer *buffer, void *data);
+
+enum metadata_bucket_status {
+       METADATA_BUCKET_STATUS_OK,
+       METADATA_BUCKET_STATUS_ERROR,
+};
+
+struct metadata_bucket *metadata_bucket_create(
+               metadata_bucket_flush_cb flush, void *data);
+
+void metadata_bucket_destroy(struct metadata_bucket *bucket);
+
+enum metadata_bucket_status metadata_bucket_fill(struct metadata_bucket *bucket,
+               const struct stream_subbuffer *buffer);
+
+void metadata_bucket_reset(struct metadata_bucket *bucket);
+
+#endif /* METADATA_BUCKET_H */
index ab61a8133386b026bf27972a168030c74d9c401f..98c29f86c2cbac21f344e3a1df33231e6e6eb7c5 100644 (file)
@@ -5,11 +5,11 @@
  *
  */
 
-#include "context.h"
+#include "context.hpp"
 #include <stddef.h>
 #include <string.h>
-#include <common/error.h>
-#include <common/macros.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
 
 int parse_application_context(const char *str, char **out_provider_name,
                char **out_ctx_name)
diff --git a/src/common/context.h b/src/common/context.h
deleted file mode 100644 (file)
index f4abd84..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_COMMON_CONTEXT_H
-#define LTTNG_COMMON_CONTEXT_H
-
-#include <common/macros.h>
-
-/*
- * Parse string as an application context of the form
- * "$app.provider_name:context_name" and return the provider name and context
- * name separately.
- *
- * provider_name and ctx_name are returned only if an application context name
- * was successfully parsed and must be freed by the caller.
- *
- * Returns 0 if the string is a valid application context, else a negative
- * value on error.
- */
-int parse_application_context(const char *str, char **provider_name,
-               char **ctx_name);
-
-#endif /* LTTNG_COMMON_CONTEXT_H */
diff --git a/src/common/context.hpp b/src/common/context.hpp
new file mode 100644 (file)
index 0000000..324ef53
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_COMMON_CONTEXT_H
+#define LTTNG_COMMON_CONTEXT_H
+
+#include <common/macros.hpp>
+
+/*
+ * Parse string as an application context of the form
+ * "$app.provider_name:context_name" and return the provider name and context
+ * name separately.
+ *
+ * provider_name and ctx_name are returned only if an application context name
+ * was successfully parsed and must be freed by the caller.
+ *
+ * Returns 0 if the string is a valid application context, else a negative
+ * value on error.
+ */
+int parse_application_context(const char *str, char **provider_name,
+               char **ctx_name);
+
+#endif /* LTTNG_COMMON_CONTEXT_H */
index fd8b4477bb9ad1b0861ab8a76a10bce35fed60ac..f936736db4919760dcc5c42094c35497d25ddb7b 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include <stdbool.h>
-#include "credentials.h"
+#include "credentials.hpp"
 
 uid_t lttng_credentials_get_uid(const struct lttng_credentials *creds)
 {
diff --git a/src/common/credentials.h b/src/common/credentials.h
deleted file mode 100644 (file)
index b1576a7..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_CREDENTIALS_H
-#define LTTNG_CREDENTIALS_H
-
-#include <sys/types.h>
-#include <stdbool.h>
-#include "macros.h"
-
-#include "optional.h"
-
-struct lttng_credentials {
-       LTTNG_OPTIONAL(uid_t) uid;
-       LTTNG_OPTIONAL(gid_t) gid;
-};
-
-uid_t lttng_credentials_get_uid(const struct lttng_credentials *creds);
-
-gid_t lttng_credentials_get_gid(const struct lttng_credentials *creds);
-
-bool lttng_credentials_is_equal_uid(const struct lttng_credentials *a,
-               const struct lttng_credentials *b);
-
-bool lttng_credentials_is_equal_gid(const struct lttng_credentials *a,
-               const struct lttng_credentials *b);
-
-bool lttng_credentials_is_equal(const struct lttng_credentials *a,
-               const struct lttng_credentials *b);
-
-#endif /* LTTNG_CREDENTIALS_H */
diff --git a/src/common/credentials.hpp b/src/common/credentials.hpp
new file mode 100644 (file)
index 0000000..1a05590
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_CREDENTIALS_H
+#define LTTNG_CREDENTIALS_H
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include "macros.hpp"
+
+#include "optional.hpp"
+
+struct lttng_credentials {
+       LTTNG_OPTIONAL(uid_t) uid;
+       LTTNG_OPTIONAL(gid_t) gid;
+};
+
+uid_t lttng_credentials_get_uid(const struct lttng_credentials *creds);
+
+gid_t lttng_credentials_get_gid(const struct lttng_credentials *creds);
+
+bool lttng_credentials_is_equal_uid(const struct lttng_credentials *a,
+               const struct lttng_credentials *b);
+
+bool lttng_credentials_is_equal_gid(const struct lttng_credentials *a,
+               const struct lttng_credentials *b);
+
+bool lttng_credentials_is_equal(const struct lttng_credentials *a,
+               const struct lttng_credentials *b);
+
+#endif /* LTTNG_CREDENTIALS_H */
index 16af5a3f78ccec5da76033a48a7d0a04bd0c38f2..0ed35556e81a52a87c8a94e8295e10a1fd1f3eca 100644 (file)
@@ -8,15 +8,15 @@
 
 #define _LGPL_SOURCE
 #include <unistd.h>
-#include <common/compat/paths.h>
+#include <common/compat/paths.hpp>
 #include <fcntl.h>
 #include <sys/wait.h>
 #include <stdlib.h>
 
 #include <urcu/system.h>
 
-#include <common/daemonize.h>
-#include <common/error.h>
+#include <common/daemonize.hpp>
+#include <common/error.hpp>
 
 int lttng_daemonize(pid_t *child_ppid, int *completion_flag,
                int close_fds)
diff --git a/src/common/daemonize.h b/src/common/daemonize.h
deleted file mode 100644 (file)
index 2c88f06..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef LTTNG_DAEMONIZE_H
-#define LTTNG_DAEMONIZE_H
-
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <unistd.h>
-#include <common/macros.h>
-
-/*
- * Daemonize this process by forking and making the parent wait for the child
- * to signal it indicating readiness. Once received, the parent successfully
- * quits.
- *
- * The child process undergoes the same action that daemon(3) does meaning
- * setsid, chdir, and dup /dev/null into 0, 1 and 2.
- *
- * Return 0 on success else -1 on error.
- */
-int lttng_daemonize(pid_t *child_ppid, int *completion_flag,
-               int close_fds);
-
-#endif /* LTTNG_DAEMONIZE_H */
diff --git a/src/common/daemonize.hpp b/src/common/daemonize.hpp
new file mode 100644 (file)
index 0000000..d1ec1cb
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef LTTNG_DAEMONIZE_H
+#define LTTNG_DAEMONIZE_H
+
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <unistd.h>
+#include <common/macros.hpp>
+
+/*
+ * Daemonize this process by forking and making the parent wait for the child
+ * to signal it indicating readiness. Once received, the parent successfully
+ * quits.
+ *
+ * The child process undergoes the same action that daemon(3) does meaning
+ * setsid, chdir, and dup /dev/null into 0, 1 and 2.
+ *
+ * Return 0 on success else -1 on error.
+ */
+int lttng_daemonize(pid_t *child_ppid, int *completion_flag,
+               int close_fds);
+
+#endif /* LTTNG_DAEMONIZE_H */
index 5ecb435bb630af685be875ebf257fb6d6e46bd0b..5b26cc99633c546a68c64abb10d4e1b9317164d5 100644 (file)
@@ -13,9 +13,9 @@
 #include <pthread.h>
 #include <algorithm>
 
-#include "defaults.h"
-#include "macros.h"
-#include "error.h"
+#include "defaults.hpp"
+#include "macros.hpp"
+#include "error.hpp"
 
 static int pthread_attr_init_done;
 static pthread_attr_t tattr;
diff --git a/src/common/defaults.h b/src/common/defaults.h
deleted file mode 100644 (file)
index 39b7747..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _DEFAULTS_H
-#define _DEFAULTS_H
-
-#include <pthread.h>
-#include <common/macros.h>
-
-/* Default unix group name for tracing. */
-#define DEFAULT_TRACING_GROUP                   "tracing"
-
-/*
- * This value is defined in the CTF specification (see
- * git://git.efficios.com/ctf.git in the file
- * common-trace-format-specification.txt.
- */
-#define DEFAULT_METADATA_NAME                   "metadata"
-
-/* Environment variable to set session daemon binary path. */
-#define DEFAULT_SESSIOND_PATH_ENV               "LTTNG_SESSIOND_PATH"
-
-/* Environment variable to set man pager binary path. */
-#define DEFAULT_MAN_BIN_PATH_ENV                "LTTNG_MAN_BIN_PATH"
-
-/* Default man pager binary path. */
-#define DEFAULT_MAN_BIN_PATH                    "/usr/bin/man"
-
-/* Default trace output directory name */
-#define DEFAULT_TRACE_DIR_NAME                  "lttng-traces"
-
-/* Default size of a hash table */
-#define DEFAULT_HT_SIZE                         4
-
-/* Default session daemon paths */
-#define DEFAULT_HOME_DIR                                               "/tmp"
-#define DEFAULT_UST_SOCK_DIR                    DEFAULT_HOME_DIR "/ust-app-socks"
-#define DEFAULT_GLOBAL_APPS_PIPE                DEFAULT_UST_SOCK_DIR "/global"
-#define DEFAULT_TRACE_OUTPUT                    DEFAULT_HOME_DIR "/lttng"
-
-/* Default directory where the trace are written in per domain */
-#define DEFAULT_KERNEL_TRACE_DIR                "kernel"
-#define DEFAULT_UST_TRACE_DIR                   "ust"
-
-/* Subpath for per PID or UID sessions. */
-#define DEFAULT_UST_TRACE_PID_PATH               "pid"
-#define DEFAULT_UST_TRACE_UID_PATH               "uid/%d/%u-bit"
-
-/*
- * Default session name for the lttng command line. This default value will
- * get the date and time appended (%Y%m%d-%H%M%S) to it.
- */
-#define DEFAULT_SESSION_NAME                    "auto"
-
-/* Default consumer paths */
-#define DEFAULT_CONSUMERD_FILE                  "lttng-consumerd"
-
-/* Default consumer paths */
-#define DEFAULT_CONSUMERD_RUNDIR                "%s"
-
-/* Kernel consumer path */
-#define DEFAULT_KCONSUMERD_PATH                 DEFAULT_CONSUMERD_RUNDIR "/kconsumerd"
-#define DEFAULT_KCONSUMERD_CMD_SOCK_PATH        DEFAULT_KCONSUMERD_PATH "/command"
-#define DEFAULT_KCONSUMERD_ERR_SOCK_PATH        DEFAULT_KCONSUMERD_PATH "/error"
-
-/* UST 64-bit consumer path */
-#define DEFAULT_USTCONSUMERD64_PATH             DEFAULT_CONSUMERD_RUNDIR "/ustconsumerd64"
-#define DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH    DEFAULT_USTCONSUMERD64_PATH "/command"
-#define DEFAULT_USTCONSUMERD64_ERR_SOCK_PATH    DEFAULT_USTCONSUMERD64_PATH "/error"
-
-/* UST 32-bit consumer path */
-#define DEFAULT_USTCONSUMERD32_PATH             DEFAULT_CONSUMERD_RUNDIR "/ustconsumerd32"
-#define DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH    DEFAULT_USTCONSUMERD32_PATH "/command"
-#define DEFAULT_USTCONSUMERD32_ERR_SOCK_PATH    DEFAULT_USTCONSUMERD32_PATH "/error"
-
-/* Relayd path */
-#define DEFAULT_RELAYD_RUNDIR                  "%s"
-#define DEFAULT_RELAYD_PATH                    DEFAULT_RELAYD_RUNDIR "/relayd"
-
-#define DEFAULT_RELAYD_MIN_FD_POOL_SIZE                100
-/*
- * The file descriptor pool size needs a reserve buffer to accommodates the
- * indirect use of short-lived file descriptors. For instance, glibc will
- * create a socket (and thus, use an fd) during calls to gethostname() or
- * when querying the user's group. Other calls also probably make use of
- * short-lived FDs.
- *
- * The theoritical maximal reserve corresponds to the number of threads as,
- * in the worst case, they could all be making such calls.
- *
- * This value must be less than DEFAULT_RELAYD_MIN_FD_POOL_SIZE.
- */
-#define DEFAULT_RELAYD_FD_POOL_SIZE_RESERVE    10
-
-/* Default lttng run directory */
-#define DEFAULT_LTTNG_HOME_ENV_VAR              "LTTNG_HOME"
-#define DEFAULT_LTTNG_FALLBACK_HOME_ENV_VAR    "HOME"
-#define DEFAULT_LTTNG_RUNDIR                    CONFIG_LTTNG_SYSTEM_RUNDIR
-#define DEFAULT_LTTNG_HOME_RUNDIR               "%s/.lttng"
-#define DEFAULT_LTTNG_SESSIOND_PIDFILE          "lttng-sessiond.pid"
-#define DEFAULT_LTTNG_SESSIOND_AGENTPORT_FILE   "agent.port"
-#define DEFAULT_LTTNG_SESSIOND_LOCKFILE         "lttng-sessiond.lck"
-
-/* Default probes list */
-#define DEFAULT_LTTNG_KMOD_PROBES              "LTTNG_KMOD_PROBES"
-
-/* Default extra probes list */
-#define DEFAULT_LTTNG_EXTRA_KMOD_PROBES                "LTTNG_EXTRA_KMOD_PROBES"
-
-/* Default unix socket path */
-#define DEFAULT_GLOBAL_CLIENT_UNIX_SOCK                DEFAULT_LTTNG_RUNDIR "/client-lttng-sessiond"
-#define DEFAULT_HOME_CLIENT_UNIX_SOCK                  DEFAULT_LTTNG_HOME_RUNDIR "/client-lttng-sessiond"
-#define DEFAULT_GLOBAL_HEALTH_UNIX_SOCK                DEFAULT_LTTNG_RUNDIR "/sessiond-health"
-#define DEFAULT_HOME_HEALTH_UNIX_SOCK                  DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-health"
-#define DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK   DEFAULT_LTTNG_RUNDIR "/sessiond-notification"
-#define DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK    DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-notification"
-
-/* Default consumer health unix socket path */
-#define DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK  DEFAULT_LTTNG_RUNDIR "/ustconsumerd32/health"
-#define DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK    DEFAULT_LTTNG_HOME_RUNDIR "/ustconsumerd32/health"
-#define DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK  DEFAULT_LTTNG_RUNDIR "/ustconsumerd64/health"
-#define DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK    DEFAULT_LTTNG_HOME_RUNDIR "/ustconsumerd64/health"
-#define DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK      DEFAULT_LTTNG_RUNDIR "/kconsumerd/health"
-#define DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK                DEFAULT_LTTNG_HOME_RUNDIR "/kconsumerd/health"
-
-/* Default relay health unix socket path */
-#define DEFAULT_GLOBAL_RELAY_HEALTH_UNIX_SOCK          DEFAULT_LTTNG_RUNDIR "/relayd/health-%d"
-#define DEFAULT_HOME_RELAY_HEALTH_UNIX_SOCK            DEFAULT_LTTNG_HOME_RUNDIR "/relayd/health-%d"
-
-/* Default daemon configuration file path */
-#define DEFAULT_SYSTEM_CONFIGPATH               CONFIG_LTTNG_SYSTEM_CONFIGDIR \
-       "/lttng"
-
-#define DEFAULT_DAEMON_CONFIG_FILE              "lttng.conf"
-#define DEFAULT_DAEMON_HOME_CONFIGPATH          DEFAULT_LTTNG_HOME_RUNDIR "/" \
-       DEFAULT_DAEMON_CONFIG_FILE
-#define DEFAULT_DAEMON_SYSTEM_CONFIGPATH        DEFAULT_SYSTEM_CONFIGPATH "/" \
-       DEFAULT_DAEMON_CONFIG_FILE
-
-/* Default session configuration file path */
-#define DEFAULT_SESSION_PATH                    "sessions"
-/* Auto load session in that directory. */
-#define DEFAULT_SESSION_CONFIG_AUTOLOAD         "auto"
-#define DEFAULT_SESSION_HOME_CONFIGPATH         DEFAULT_LTTNG_HOME_RUNDIR "/" \
-       DEFAULT_SESSION_PATH
-#define DEFAULT_SESSION_SYSTEM_CONFIGPATH       DEFAULT_SYSTEM_CONFIGPATH "/" \
-       DEFAULT_SESSION_PATH
-#define DEFAULT_SESSION_CONFIG_FILE_EXTENSION   ".lttng"
-#define DEFAULT_SESSION_CONFIG_XSD_FILENAME     "session.xsd"
-#define DEFAULT_SESSION_CONFIG_XSD_PATH         CONFIG_LTTNG_SYSTEM_DATADIR "/xml/lttng/"
-#define DEFAULT_SESSION_CONFIG_XSD_PATH_ENV     "LTTNG_SESSION_CONFIG_XSD_PATH"
-
-#define DEFAULT_GLOBAL_APPS_UNIX_SOCK \
-       DEFAULT_LTTNG_RUNDIR "/" LTTNG_UST_SOCK_FILENAME
-#define DEFAULT_HOME_APPS_UNIX_SOCK \
-       DEFAULT_LTTNG_HOME_RUNDIR "/" LTTNG_UST_SOCK_FILENAME
-#define DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH \
-       "/" LTTNG_UST_WAIT_FILENAME
-#define DEFAULT_HOME_APPS_WAIT_SHM_PATH \
-       DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH "-%d"
-
-/*
- * Value taken from the hard limit allowed by the kernel when using setrlimit
- * with RLIMIT_NOFILE on an Intel i7 CPU and Linux 3.0.3.
- */
-#define DEFAULT_POLL_SIZE 65535
-
-/*
- * Format is %s_%d respectively channel name and CPU number. Eigth bytes
- * are added here to add space for the CPU number. I guess 2^8 CPUs is more
- * than enough. We might end up with quantum computing in a cell phone when
- * reaching this limit.
- */
-#define DEFAULT_STREAM_NAME_LEN        LTTNG_SYMBOL_NAME_LEN + 8
-
-/* Default channel attributes */
-#define DEFAULT_CHANNEL_NAME            "channel0"
-/* Default JUL domain channel name. */
-#define DEFAULT_JUL_CHANNEL_NAME        "lttng_jul_channel"
-/* Default JUL tracepoint name. This is a wildcard for the JUL domain. */
-#define DEFAULT_JUL_EVENT_COMPONENT     "lttng_jul"
-#define DEFAULT_JUL_EVENT_NAME          DEFAULT_JUL_EVENT_COMPONENT ":*"
-
-/* Default log4j domain channel name. */
-#define DEFAULT_LOG4J_CHANNEL_NAME        "lttng_log4j_channel"
-/* Default log4j tracepoint name. This is a wildcard for the log4j domain. */
-#define DEFAULT_LOG4J_EVENT_COMPONENT     "lttng_log4j"
-#define DEFAULT_LOG4J_EVENT_NAME          DEFAULT_LOG4J_EVENT_COMPONENT ":*"
-
-/* Default Python domain channel name. */
-#define DEFAULT_PYTHON_CHANNEL_NAME       "lttng_python_channel"
-/* Default Python tracepoint name. This is a wildcard for the python domain. */
-#define DEFAULT_PYTHON_EVENT_COMPONENT    "lttng_python"
-#define DEFAULT_PYTHON_EVENT_NAME         DEFAULT_PYTHON_EVENT_COMPONENT ":*"
-
-#define DEFAULT_CHANNEL_OVERWRITE       -1
-#define DEFAULT_CHANNEL_TRACEFILE_SIZE  CONFIG_DEFAULT_CHANNEL_TRACEFILE_SIZE
-#define DEFAULT_CHANNEL_TRACEFILE_COUNT CONFIG_DEFAULT_CHANNEL_TRACEFILE_COUNT
-
-#define _DEFAULT_CHANNEL_SUBBUF_SIZE   CONFIG_DEFAULT_CHANNEL_SUBBUF_SIZE
-#define _DEFAULT_CHANNEL_OUTPUT                        LTTNG_EVENT_MMAP
-
-/* Metadata channel defaults. */
-#define DEFAULT_METADATA_SUBBUF_SIZE    CONFIG_DEFAULT_METADATA_SUBBUF_SIZE
-#define DEFAULT_METADATA_SUBBUF_NUM     CONFIG_DEFAULT_METADATA_SUBBUF_NUM
-#define DEFAULT_METADATA_CACHE_SIZE     CONFIG_DEFAULT_METADATA_CACHE_SIZE
-#define DEFAULT_METADATA_SWITCH_TIMER  0
-#define DEFAULT_METADATA_READ_TIMER    0
-#define DEFAULT_METADATA_OVERWRITE     0
-#define DEFAULT_METADATA_OUTPUT                LTTNG_EVENT_MMAP
-
-/* Kernel has different defaults */
-
-/* DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE must always be a power of 2 */
-#define DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE     CONFIG_DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE
-/*
- * DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM must always be a power of 2.
- * Update help manually if override.
- */
-#define DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM      CONFIG_DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM
-/* See lttng-kernel.h enum lttng_kernel_output for channel output */
-#define DEFAULT_KERNEL_CHANNEL_OUTPUT                  LTTNG_EVENT_SPLICE
-#define DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER    CONFIG_DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER
-#define DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER   CONFIG_DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER
-#define DEFAULT_KERNEL_CHANNEL_READ_TIMER      CONFIG_DEFAULT_KERNEL_CHANNEL_READ_TIMER
-#define DEFAULT_KERNEL_CHANNEL_LIVE_TIMER      CONFIG_DEFAULT_KERNEL_CHANNEL_LIVE_TIMER
-#define DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT        CONFIG_DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT
-
-/* User space defaults */
-
-/* Must be a power of 2 */
-#define DEFAULT_UST_PID_CHANNEL_SUBBUF_SIZE    CONFIG_DEFAULT_UST_PID_CHANNEL_SUBBUF_SIZE
-#define DEFAULT_UST_UID_CHANNEL_SUBBUF_SIZE    CONFIG_DEFAULT_UST_UID_CHANNEL_SUBBUF_SIZE
-/* Must be a power of 2. Update help manuall if override. */
-#define DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM     CONFIG_DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM
-#define DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM     CONFIG_DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM
-/* See lttng-ust.h enum lttng_ust_output */
-#define DEFAULT_UST_PID_CHANNEL_OUTPUT                 _DEFAULT_CHANNEL_OUTPUT
-#define DEFAULT_UST_UID_CHANNEL_OUTPUT                 _DEFAULT_CHANNEL_OUTPUT
-/* Timers in usec. */
-#define DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER   CONFIG_DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER
-#define DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER   CONFIG_DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER
-#define DEFAULT_UST_PID_CHANNEL_LIVE_TIMER     CONFIG_DEFAULT_UST_PID_CHANNEL_LIVE_TIMER
-#define DEFAULT_UST_UID_CHANNEL_LIVE_TIMER     CONFIG_DEFAULT_UST_UID_CHANNEL_LIVE_TIMER
-#define DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER  CONFIG_DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER
-#define DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER  CONFIG_DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER
-
-#define DEFAULT_UST_PID_CHANNEL_READ_TIMER      CONFIG_DEFAULT_UST_PID_CHANNEL_READ_TIMER
-#define DEFAULT_UST_UID_CHANNEL_READ_TIMER      CONFIG_DEFAULT_UST_UID_CHANNEL_READ_TIMER
-
-#define DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT       CONFIG_DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT
-#define DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT       CONFIG_DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT
-
-/*
- * Default timeout value for the sem_timedwait() call. Blocking forever is not
- * wanted so a timeout is used to control the data flow and not freeze the
- * session daemon.
- */
-#define DEFAULT_SEM_WAIT_TIMEOUT            30    /* in seconds */
-
-/* Default bind addresses for network services. */
-#define DEFAULT_NETWORK_CONTROL_BIND_ADDRESS    CONFIG_DEFAULT_NETWORK_CONTROL_BIND_ADDRESS
-#define DEFAULT_NETWORK_DATA_BIND_ADDRESS              CONFIG_DEFAULT_NETWORK_DATA_BIND_ADDRESS
-#define DEFAULT_NETWORK_VIEWER_BIND_ADDRESS     CONFIG_DEFAULT_NETWORK_VIEWER_BIND_ADDRESS
-#define DEFAULT_AGENT_BIND_ADDRESS              CONFIG_DEFAULT_AGENT_BIND_ADDRESS
-
-/* Default network ports for trace streaming support. */
-#define DEFAULT_NETWORK_CONTROL_PORT        CONFIG_DEFAULT_NETWORK_CONTROL_PORT
-#define DEFAULT_NETWORK_DATA_PORT           CONFIG_DEFAULT_NETWORK_DATA_PORT
-#define DEFAULT_NETWORK_VIEWER_PORT         CONFIG_DEFAULT_NETWORK_VIEWER_PORT
-
-/* Agent registration TCP port range. */
-#define DEFAULT_AGENT_TCP_PORT_RANGE_BEGIN  CONFIG_DEFAULT_AGENT_TCP_PORT_RANGE_BEGIN
-#define DEFAULT_AGENT_TCP_PORT_RANGE_END    CONFIG_DEFAULT_AGENT_TCP_PORT_RANGE_END
-
-/* Number of buckets in the event notifier error count map. */
-#define DEFAULT_EVENT_NOTIFIER_ERROR_COUNT_MAP_SIZE CONFIG_DEFAULT_EVENT_NOTIFIER_ERROR_COUNT_MAP_SIZE
-
-/*
- * If a thread stalls for this amount of time, it will be considered bogus (bad
- * health).
- */
-#define DEFAULT_HEALTH_CHECK_DELTA_S        20
-#define DEFAULT_HEALTH_CHECK_DELTA_NS       0
-
-/*
- * Wait period before retrying the lttng_data_pending command in the lttng
- * stop command of liblttng-ctl.
- */
-#define DEFAULT_DATA_AVAILABILITY_WAIT_TIME_US 200000  /* usec */
-
-/*
- * Wait period before retrying the lttng_consumer_flushed_cache when
- * the consumer receives metadata.
- */
-#define DEFAULT_METADATA_AVAILABILITY_WAIT_TIME 200000  /* usec */
-
-/*
- * The usual value for the maximum TCP SYN retries time and TCP FIN timeout is
- * 180 and 60 seconds on most Linux system and the default value since kernel
- * 2.2 thus using the highest value. See tcp(7) for more details.
- */
-#define DEFAULT_INET_TCP_TIMEOUT                       180     /* sec */
-
-/* Maximum payload size for a control connection */
-
-#define DEFAULT_NETWORK_RELAYD_CTRL_MAX_PAYLOAD_SIZE CONFIG_DEFAULT_NETWORK_RELAYD_CTRL_MAX_PAYLOAD_SIZE
-
-/*
- * Default receiving and sending timeout for an application socket.
- */
-#define DEFAULT_APP_SOCKET_RW_TIMEOUT       CONFIG_DEFAULT_APP_SOCKET_RW_TIMEOUT
-#define DEFAULT_APP_SOCKET_TIMEOUT_ENV      "LTTNG_APP_SOCKET_TIMEOUT"
-
-#define DEFAULT_UST_STREAM_FD_NUM                      2 /* Number of fd per UST stream. */
-
-#define DEFAULT_SNAPSHOT_NAME                          "snapshot"
-#define DEFAULT_SNAPSHOT_MAX_SIZE                      0 /* Unlimited. */
-
-/* Suffix of an index file. */
-#define DEFAULT_INDEX_FILE_SUFFIX                      ".idx"
-#define DEFAULT_INDEX_DIR                                      "index"
-
-/* Default lttng command live timer value in usec. */
-#define DEFAULT_LTTNG_LIVE_TIMER                       CONFIG_DEFAULT_LTTNG_LIVE_TIMER
-
-/* Default runas worker name */
-#define DEFAULT_RUN_AS_WORKER_NAME                     "lttng-runas"
-
-/* Default LTTng MI XML namespace. */
-#define DEFAULT_LTTNG_MI_NAMESPACE             "https://lttng.org/xml/ns/lttng-mi"
-
-/* Default thread stack size; the default mandated by pthread_create(3) */
-#define DEFAULT_LTTNG_THREAD_STACK_SIZE                2097152
-
-/* Default maximal size of message notification channel message payloads. */
-#define DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE   65536
-
-/* Default maximal size of trace archive location. */
-#define DEFAULT_MAX_TRACE_ARCHIVE_LOCATION_PAYLOAD_SIZE                65536
-
-/* Default maximal size of message notification channel message payloads. */
-#define DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT          100
-
-
-#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE"
-#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME"
-#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT"
-#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL"
-#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD"
-#define DEFAULT_LTTNG_RELAYD_DISALLOW_CLEAR_ENV "LTTNG_RELAYD_DISALLOW_CLEAR"
-
-#define DEFAULT_LTTNG_RELAYD_WORKING_DIRECTORY_ENV "LTTNG_RELAYD_WORKING_DIRECTORY"
-
-/*
- * Name of the intermediate directory used to rename the trace chunk of a
- * session's first rotation.
- */
-#define DEFAULT_CHUNK_TMP_OLD_DIRECTORY                        ".tmp_old_chunk"
-#define DEFAULT_CHUNK_TMP_NEW_DIRECTORY                        ".tmp_new_chunk"
-#define DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY                "archives"
-#define DEFAULT_UNLINKED_FILES_DIRECTORY               ".unlinked"
-
-/*
- * Default timer value in usec for the rotate pending polling check on the
- * relay when a rotation has completed on the consumer.
- */
-#define DEFAULT_ROTATE_PENDING_TIMER   CONFIG_DEFAULT_ROTATE_PENDING_TIMER
-
-/*
- * Returns the default subbuf size.
- *
- * This function depends on a value that is set at constructor time, so it is
- * unsafe to call it from another constructor.
- */
-size_t default_get_channel_subbuf_size(void);
-
-/*
- * Returns the default metadata subbuf size.
- *
- * This function depends on a value that is set at constructor time, so it is
- * unsafe to call it from another constructor.
- */
-size_t default_get_metadata_subbuf_size(void);
-
-/*
- * Returns the default subbuf size for the kernel domain.
- *
- * This function depends on a value that is set at constructor time, so it is
- * unsafe to call it from another constructor.
- */
-size_t default_get_kernel_channel_subbuf_size(void);
-
-/*
- * Returns the default subbuf size for the UST domain per PID.
- *
- * This function depends on a value that is set at constructor time, so it is
- * unsafe to call it from another constructor.
- */
-size_t default_get_ust_pid_channel_subbuf_size(void);
-
-/*
- * Returns the default subbuf size for the UST domain per UID.
- *
- * This function depends on a value that is set at constructor time, so it is
- * unsafe to call it from another constructor.
- */
-size_t default_get_ust_uid_channel_subbuf_size(void);
-
-/*
- * Get the default pthread_attr to use on thread creation.
- *
- * Some libc, such as musl, don't honor the limit set for the stack size and use
- * their own empirically chosen static value. This function checks if the
- * current stack size is smaller than the stack size limit and if so returns a
- * pthread_attr_t pointer where the thread stack size is set to the soft stack
- * size limit.
- */
-pthread_attr_t *default_pthread_attr(void);
-
-#endif /* _DEFAULTS_H */
diff --git a/src/common/defaults.hpp b/src/common/defaults.hpp
new file mode 100644 (file)
index 0000000..04f6c7d
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _DEFAULTS_H
+#define _DEFAULTS_H
+
+#include <pthread.h>
+#include <common/macros.hpp>
+
+/* Default unix group name for tracing. */
+#define DEFAULT_TRACING_GROUP                   "tracing"
+
+/*
+ * This value is defined in the CTF specification (see
+ * git://git.efficios.com/ctf.git in the file
+ * common-trace-format-specification.txt.
+ */
+#define DEFAULT_METADATA_NAME                   "metadata"
+
+/* Environment variable to set session daemon binary path. */
+#define DEFAULT_SESSIOND_PATH_ENV               "LTTNG_SESSIOND_PATH"
+
+/* Environment variable to set man pager binary path. */
+#define DEFAULT_MAN_BIN_PATH_ENV                "LTTNG_MAN_BIN_PATH"
+
+/* Default man pager binary path. */
+#define DEFAULT_MAN_BIN_PATH                    "/usr/bin/man"
+
+/* Default trace output directory name */
+#define DEFAULT_TRACE_DIR_NAME                  "lttng-traces"
+
+/* Default size of a hash table */
+#define DEFAULT_HT_SIZE                         4
+
+/* Default session daemon paths */
+#define DEFAULT_HOME_DIR                                               "/tmp"
+#define DEFAULT_UST_SOCK_DIR                    DEFAULT_HOME_DIR "/ust-app-socks"
+#define DEFAULT_GLOBAL_APPS_PIPE                DEFAULT_UST_SOCK_DIR "/global"
+#define DEFAULT_TRACE_OUTPUT                    DEFAULT_HOME_DIR "/lttng"
+
+/* Default directory where the trace are written in per domain */
+#define DEFAULT_KERNEL_TRACE_DIR                "kernel"
+#define DEFAULT_UST_TRACE_DIR                   "ust"
+
+/* Subpath for per PID or UID sessions. */
+#define DEFAULT_UST_TRACE_PID_PATH               "pid"
+#define DEFAULT_UST_TRACE_UID_PATH               "uid/%d/%u-bit"
+
+/*
+ * Default session name for the lttng command line. This default value will
+ * get the date and time appended (%Y%m%d-%H%M%S) to it.
+ */
+#define DEFAULT_SESSION_NAME                    "auto"
+
+/* Default consumer paths */
+#define DEFAULT_CONSUMERD_FILE                  "lttng-consumerd"
+
+/* Default consumer paths */
+#define DEFAULT_CONSUMERD_RUNDIR                "%s"
+
+/* Kernel consumer path */
+#define DEFAULT_KCONSUMERD_PATH                 DEFAULT_CONSUMERD_RUNDIR "/kconsumerd"
+#define DEFAULT_KCONSUMERD_CMD_SOCK_PATH        DEFAULT_KCONSUMERD_PATH "/command"
+#define DEFAULT_KCONSUMERD_ERR_SOCK_PATH        DEFAULT_KCONSUMERD_PATH "/error"
+
+/* UST 64-bit consumer path */
+#define DEFAULT_USTCONSUMERD64_PATH             DEFAULT_CONSUMERD_RUNDIR "/ustconsumerd64"
+#define DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH    DEFAULT_USTCONSUMERD64_PATH "/command"
+#define DEFAULT_USTCONSUMERD64_ERR_SOCK_PATH    DEFAULT_USTCONSUMERD64_PATH "/error"
+
+/* UST 32-bit consumer path */
+#define DEFAULT_USTCONSUMERD32_PATH             DEFAULT_CONSUMERD_RUNDIR "/ustconsumerd32"
+#define DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH    DEFAULT_USTCONSUMERD32_PATH "/command"
+#define DEFAULT_USTCONSUMERD32_ERR_SOCK_PATH    DEFAULT_USTCONSUMERD32_PATH "/error"
+
+/* Relayd path */
+#define DEFAULT_RELAYD_RUNDIR                  "%s"
+#define DEFAULT_RELAYD_PATH                    DEFAULT_RELAYD_RUNDIR "/relayd"
+
+#define DEFAULT_RELAYD_MIN_FD_POOL_SIZE                100
+/*
+ * The file descriptor pool size needs a reserve buffer to accommodates the
+ * indirect use of short-lived file descriptors. For instance, glibc will
+ * create a socket (and thus, use an fd) during calls to gethostname() or
+ * when querying the user's group. Other calls also probably make use of
+ * short-lived FDs.
+ *
+ * The theoritical maximal reserve corresponds to the number of threads as,
+ * in the worst case, they could all be making such calls.
+ *
+ * This value must be less than DEFAULT_RELAYD_MIN_FD_POOL_SIZE.
+ */
+#define DEFAULT_RELAYD_FD_POOL_SIZE_RESERVE    10
+
+/* Default lttng run directory */
+#define DEFAULT_LTTNG_HOME_ENV_VAR              "LTTNG_HOME"
+#define DEFAULT_LTTNG_FALLBACK_HOME_ENV_VAR    "HOME"
+#define DEFAULT_LTTNG_RUNDIR                    CONFIG_LTTNG_SYSTEM_RUNDIR
+#define DEFAULT_LTTNG_HOME_RUNDIR               "%s/.lttng"
+#define DEFAULT_LTTNG_SESSIOND_PIDFILE          "lttng-sessiond.pid"
+#define DEFAULT_LTTNG_SESSIOND_AGENTPORT_FILE   "agent.port"
+#define DEFAULT_LTTNG_SESSIOND_LOCKFILE         "lttng-sessiond.lck"
+
+/* Default probes list */
+#define DEFAULT_LTTNG_KMOD_PROBES              "LTTNG_KMOD_PROBES"
+
+/* Default extra probes list */
+#define DEFAULT_LTTNG_EXTRA_KMOD_PROBES                "LTTNG_EXTRA_KMOD_PROBES"
+
+/* Default unix socket path */
+#define DEFAULT_GLOBAL_CLIENT_UNIX_SOCK                DEFAULT_LTTNG_RUNDIR "/client-lttng-sessiond"
+#define DEFAULT_HOME_CLIENT_UNIX_SOCK                  DEFAULT_LTTNG_HOME_RUNDIR "/client-lttng-sessiond"
+#define DEFAULT_GLOBAL_HEALTH_UNIX_SOCK                DEFAULT_LTTNG_RUNDIR "/sessiond-health"
+#define DEFAULT_HOME_HEALTH_UNIX_SOCK                  DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-health"
+#define DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK   DEFAULT_LTTNG_RUNDIR "/sessiond-notification"
+#define DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK    DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-notification"
+
+/* Default consumer health unix socket path */
+#define DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK  DEFAULT_LTTNG_RUNDIR "/ustconsumerd32/health"
+#define DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK    DEFAULT_LTTNG_HOME_RUNDIR "/ustconsumerd32/health"
+#define DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK  DEFAULT_LTTNG_RUNDIR "/ustconsumerd64/health"
+#define DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK    DEFAULT_LTTNG_HOME_RUNDIR "/ustconsumerd64/health"
+#define DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK      DEFAULT_LTTNG_RUNDIR "/kconsumerd/health"
+#define DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK                DEFAULT_LTTNG_HOME_RUNDIR "/kconsumerd/health"
+
+/* Default relay health unix socket path */
+#define DEFAULT_GLOBAL_RELAY_HEALTH_UNIX_SOCK          DEFAULT_LTTNG_RUNDIR "/relayd/health-%d"
+#define DEFAULT_HOME_RELAY_HEALTH_UNIX_SOCK            DEFAULT_LTTNG_HOME_RUNDIR "/relayd/health-%d"
+
+/* Default daemon configuration file path */
+#define DEFAULT_SYSTEM_CONFIGPATH               CONFIG_LTTNG_SYSTEM_CONFIGDIR \
+       "/lttng"
+
+#define DEFAULT_DAEMON_CONFIG_FILE              "lttng.conf"
+#define DEFAULT_DAEMON_HOME_CONFIGPATH          DEFAULT_LTTNG_HOME_RUNDIR "/" \
+       DEFAULT_DAEMON_CONFIG_FILE
+#define DEFAULT_DAEMON_SYSTEM_CONFIGPATH        DEFAULT_SYSTEM_CONFIGPATH "/" \
+       DEFAULT_DAEMON_CONFIG_FILE
+
+/* Default session configuration file path */
+#define DEFAULT_SESSION_PATH                    "sessions"
+/* Auto load session in that directory. */
+#define DEFAULT_SESSION_CONFIG_AUTOLOAD         "auto"
+#define DEFAULT_SESSION_HOME_CONFIGPATH         DEFAULT_LTTNG_HOME_RUNDIR "/" \
+       DEFAULT_SESSION_PATH
+#define DEFAULT_SESSION_SYSTEM_CONFIGPATH       DEFAULT_SYSTEM_CONFIGPATH "/" \
+       DEFAULT_SESSION_PATH
+#define DEFAULT_SESSION_CONFIG_FILE_EXTENSION   ".lttng"
+#define DEFAULT_SESSION_CONFIG_XSD_FILENAME     "session.xsd"
+#define DEFAULT_SESSION_CONFIG_XSD_PATH         CONFIG_LTTNG_SYSTEM_DATADIR "/xml/lttng/"
+#define DEFAULT_SESSION_CONFIG_XSD_PATH_ENV     "LTTNG_SESSION_CONFIG_XSD_PATH"
+
+#define DEFAULT_GLOBAL_APPS_UNIX_SOCK \
+       DEFAULT_LTTNG_RUNDIR "/" LTTNG_UST_SOCK_FILENAME
+#define DEFAULT_HOME_APPS_UNIX_SOCK \
+       DEFAULT_LTTNG_HOME_RUNDIR "/" LTTNG_UST_SOCK_FILENAME
+#define DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH \
+       "/" LTTNG_UST_WAIT_FILENAME
+#define DEFAULT_HOME_APPS_WAIT_SHM_PATH \
+       DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH "-%d"
+
+/*
+ * Value taken from the hard limit allowed by the kernel when using setrlimit
+ * with RLIMIT_NOFILE on an Intel i7 CPU and Linux 3.0.3.
+ */
+#define DEFAULT_POLL_SIZE 65535
+
+/*
+ * Format is %s_%d respectively channel name and CPU number. Eigth bytes
+ * are added here to add space for the CPU number. I guess 2^8 CPUs is more
+ * than enough. We might end up with quantum computing in a cell phone when
+ * reaching this limit.
+ */
+#define DEFAULT_STREAM_NAME_LEN        LTTNG_SYMBOL_NAME_LEN + 8
+
+/* Default channel attributes */
+#define DEFAULT_CHANNEL_NAME            "channel0"
+/* Default JUL domain channel name. */
+#define DEFAULT_JUL_CHANNEL_NAME        "lttng_jul_channel"
+/* Default JUL tracepoint name. This is a wildcard for the JUL domain. */
+#define DEFAULT_JUL_EVENT_COMPONENT     "lttng_jul"
+#define DEFAULT_JUL_EVENT_NAME          DEFAULT_JUL_EVENT_COMPONENT ":*"
+
+/* Default log4j domain channel name. */
+#define DEFAULT_LOG4J_CHANNEL_NAME        "lttng_log4j_channel"
+/* Default log4j tracepoint name. This is a wildcard for the log4j domain. */
+#define DEFAULT_LOG4J_EVENT_COMPONENT     "lttng_log4j"
+#define DEFAULT_LOG4J_EVENT_NAME          DEFAULT_LOG4J_EVENT_COMPONENT ":*"
+
+/* Default Python domain channel name. */
+#define DEFAULT_PYTHON_CHANNEL_NAME       "lttng_python_channel"
+/* Default Python tracepoint name. This is a wildcard for the python domain. */
+#define DEFAULT_PYTHON_EVENT_COMPONENT    "lttng_python"
+#define DEFAULT_PYTHON_EVENT_NAME         DEFAULT_PYTHON_EVENT_COMPONENT ":*"
+
+#define DEFAULT_CHANNEL_OVERWRITE       -1
+#define DEFAULT_CHANNEL_TRACEFILE_SIZE  CONFIG_DEFAULT_CHANNEL_TRACEFILE_SIZE
+#define DEFAULT_CHANNEL_TRACEFILE_COUNT CONFIG_DEFAULT_CHANNEL_TRACEFILE_COUNT
+
+#define _DEFAULT_CHANNEL_SUBBUF_SIZE   CONFIG_DEFAULT_CHANNEL_SUBBUF_SIZE
+#define _DEFAULT_CHANNEL_OUTPUT                        LTTNG_EVENT_MMAP
+
+/* Metadata channel defaults. */
+#define DEFAULT_METADATA_SUBBUF_SIZE    CONFIG_DEFAULT_METADATA_SUBBUF_SIZE
+#define DEFAULT_METADATA_SUBBUF_NUM     CONFIG_DEFAULT_METADATA_SUBBUF_NUM
+#define DEFAULT_METADATA_CACHE_SIZE     CONFIG_DEFAULT_METADATA_CACHE_SIZE
+#define DEFAULT_METADATA_SWITCH_TIMER  0
+#define DEFAULT_METADATA_READ_TIMER    0
+#define DEFAULT_METADATA_OVERWRITE     0
+#define DEFAULT_METADATA_OUTPUT                LTTNG_EVENT_MMAP
+
+/* Kernel has different defaults */
+
+/* DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE must always be a power of 2 */
+#define DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE     CONFIG_DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE
+/*
+ * DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM must always be a power of 2.
+ * Update help manually if override.
+ */
+#define DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM      CONFIG_DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM
+/* See lttng-kernel.h enum lttng_kernel_output for channel output */
+#define DEFAULT_KERNEL_CHANNEL_OUTPUT                  LTTNG_EVENT_SPLICE
+#define DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER    CONFIG_DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER
+#define DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER   CONFIG_DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER
+#define DEFAULT_KERNEL_CHANNEL_READ_TIMER      CONFIG_DEFAULT_KERNEL_CHANNEL_READ_TIMER
+#define DEFAULT_KERNEL_CHANNEL_LIVE_TIMER      CONFIG_DEFAULT_KERNEL_CHANNEL_LIVE_TIMER
+#define DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT        CONFIG_DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT
+
+/* User space defaults */
+
+/* Must be a power of 2 */
+#define DEFAULT_UST_PID_CHANNEL_SUBBUF_SIZE    CONFIG_DEFAULT_UST_PID_CHANNEL_SUBBUF_SIZE
+#define DEFAULT_UST_UID_CHANNEL_SUBBUF_SIZE    CONFIG_DEFAULT_UST_UID_CHANNEL_SUBBUF_SIZE
+/* Must be a power of 2. Update help manuall if override. */
+#define DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM     CONFIG_DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM
+#define DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM     CONFIG_DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM
+/* See lttng-ust.h enum lttng_ust_output */
+#define DEFAULT_UST_PID_CHANNEL_OUTPUT                 _DEFAULT_CHANNEL_OUTPUT
+#define DEFAULT_UST_UID_CHANNEL_OUTPUT                 _DEFAULT_CHANNEL_OUTPUT
+/* Timers in usec. */
+#define DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER   CONFIG_DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER
+#define DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER   CONFIG_DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER
+#define DEFAULT_UST_PID_CHANNEL_LIVE_TIMER     CONFIG_DEFAULT_UST_PID_CHANNEL_LIVE_TIMER
+#define DEFAULT_UST_UID_CHANNEL_LIVE_TIMER     CONFIG_DEFAULT_UST_UID_CHANNEL_LIVE_TIMER
+#define DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER  CONFIG_DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER
+#define DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER  CONFIG_DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER
+
+#define DEFAULT_UST_PID_CHANNEL_READ_TIMER      CONFIG_DEFAULT_UST_PID_CHANNEL_READ_TIMER
+#define DEFAULT_UST_UID_CHANNEL_READ_TIMER      CONFIG_DEFAULT_UST_UID_CHANNEL_READ_TIMER
+
+#define DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT       CONFIG_DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT
+#define DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT       CONFIG_DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT
+
+/*
+ * Default timeout value for the sem_timedwait() call. Blocking forever is not
+ * wanted so a timeout is used to control the data flow and not freeze the
+ * session daemon.
+ */
+#define DEFAULT_SEM_WAIT_TIMEOUT            30    /* in seconds */
+
+/* Default bind addresses for network services. */
+#define DEFAULT_NETWORK_CONTROL_BIND_ADDRESS    CONFIG_DEFAULT_NETWORK_CONTROL_BIND_ADDRESS
+#define DEFAULT_NETWORK_DATA_BIND_ADDRESS              CONFIG_DEFAULT_NETWORK_DATA_BIND_ADDRESS
+#define DEFAULT_NETWORK_VIEWER_BIND_ADDRESS     CONFIG_DEFAULT_NETWORK_VIEWER_BIND_ADDRESS
+#define DEFAULT_AGENT_BIND_ADDRESS              CONFIG_DEFAULT_AGENT_BIND_ADDRESS
+
+/* Default network ports for trace streaming support. */
+#define DEFAULT_NETWORK_CONTROL_PORT        CONFIG_DEFAULT_NETWORK_CONTROL_PORT
+#define DEFAULT_NETWORK_DATA_PORT           CONFIG_DEFAULT_NETWORK_DATA_PORT
+#define DEFAULT_NETWORK_VIEWER_PORT         CONFIG_DEFAULT_NETWORK_VIEWER_PORT
+
+/* Agent registration TCP port range. */
+#define DEFAULT_AGENT_TCP_PORT_RANGE_BEGIN  CONFIG_DEFAULT_AGENT_TCP_PORT_RANGE_BEGIN
+#define DEFAULT_AGENT_TCP_PORT_RANGE_END    CONFIG_DEFAULT_AGENT_TCP_PORT_RANGE_END
+
+/* Number of buckets in the event notifier error count map. */
+#define DEFAULT_EVENT_NOTIFIER_ERROR_COUNT_MAP_SIZE CONFIG_DEFAULT_EVENT_NOTIFIER_ERROR_COUNT_MAP_SIZE
+
+/*
+ * If a thread stalls for this amount of time, it will be considered bogus (bad
+ * health).
+ */
+#define DEFAULT_HEALTH_CHECK_DELTA_S        20
+#define DEFAULT_HEALTH_CHECK_DELTA_NS       0
+
+/*
+ * Wait period before retrying the lttng_data_pending command in the lttng
+ * stop command of liblttng-ctl.
+ */
+#define DEFAULT_DATA_AVAILABILITY_WAIT_TIME_US 200000  /* usec */
+
+/*
+ * Wait period before retrying the lttng_consumer_flushed_cache when
+ * the consumer receives metadata.
+ */
+#define DEFAULT_METADATA_AVAILABILITY_WAIT_TIME 200000  /* usec */
+
+/*
+ * The usual value for the maximum TCP SYN retries time and TCP FIN timeout is
+ * 180 and 60 seconds on most Linux system and the default value since kernel
+ * 2.2 thus using the highest value. See tcp(7) for more details.
+ */
+#define DEFAULT_INET_TCP_TIMEOUT                       180     /* sec */
+
+/* Maximum payload size for a control connection */
+
+#define DEFAULT_NETWORK_RELAYD_CTRL_MAX_PAYLOAD_SIZE CONFIG_DEFAULT_NETWORK_RELAYD_CTRL_MAX_PAYLOAD_SIZE
+
+/*
+ * Default receiving and sending timeout for an application socket.
+ */
+#define DEFAULT_APP_SOCKET_RW_TIMEOUT       CONFIG_DEFAULT_APP_SOCKET_RW_TIMEOUT
+#define DEFAULT_APP_SOCKET_TIMEOUT_ENV      "LTTNG_APP_SOCKET_TIMEOUT"
+
+#define DEFAULT_UST_STREAM_FD_NUM                      2 /* Number of fd per UST stream. */
+
+#define DEFAULT_SNAPSHOT_NAME                          "snapshot"
+#define DEFAULT_SNAPSHOT_MAX_SIZE                      0 /* Unlimited. */
+
+/* Suffix of an index file. */
+#define DEFAULT_INDEX_FILE_SUFFIX                      ".idx"
+#define DEFAULT_INDEX_DIR                                      "index"
+
+/* Default lttng command live timer value in usec. */
+#define DEFAULT_LTTNG_LIVE_TIMER                       CONFIG_DEFAULT_LTTNG_LIVE_TIMER
+
+/* Default runas worker name */
+#define DEFAULT_RUN_AS_WORKER_NAME                     "lttng-runas"
+
+/* Default LTTng MI XML namespace. */
+#define DEFAULT_LTTNG_MI_NAMESPACE             "https://lttng.org/xml/ns/lttng-mi"
+
+/* Default thread stack size; the default mandated by pthread_create(3) */
+#define DEFAULT_LTTNG_THREAD_STACK_SIZE                2097152
+
+/* Default maximal size of message notification channel message payloads. */
+#define DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE   65536
+
+/* Default maximal size of trace archive location. */
+#define DEFAULT_MAX_TRACE_ARCHIVE_LOCATION_PAYLOAD_SIZE                65536
+
+/* Default maximal size of message notification channel message payloads. */
+#define DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT          100
+
+
+#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE"
+#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE_IDLE_TIME"
+#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE_MAX_PROBE_COUNT"
+#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE_PROBE_INTERVAL"
+#define DEFAULT_LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD_ENV "LTTNG_RELAYD_TCP_KEEP_ALIVE_ABORT_THRESHOLD"
+#define DEFAULT_LTTNG_RELAYD_DISALLOW_CLEAR_ENV "LTTNG_RELAYD_DISALLOW_CLEAR"
+
+#define DEFAULT_LTTNG_RELAYD_WORKING_DIRECTORY_ENV "LTTNG_RELAYD_WORKING_DIRECTORY"
+
+/*
+ * Name of the intermediate directory used to rename the trace chunk of a
+ * session's first rotation.
+ */
+#define DEFAULT_CHUNK_TMP_OLD_DIRECTORY                        ".tmp_old_chunk"
+#define DEFAULT_CHUNK_TMP_NEW_DIRECTORY                        ".tmp_new_chunk"
+#define DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY                "archives"
+#define DEFAULT_UNLINKED_FILES_DIRECTORY               ".unlinked"
+
+/*
+ * Default timer value in usec for the rotate pending polling check on the
+ * relay when a rotation has completed on the consumer.
+ */
+#define DEFAULT_ROTATE_PENDING_TIMER   CONFIG_DEFAULT_ROTATE_PENDING_TIMER
+
+/*
+ * Returns the default subbuf size.
+ *
+ * This function depends on a value that is set at constructor time, so it is
+ * unsafe to call it from another constructor.
+ */
+size_t default_get_channel_subbuf_size(void);
+
+/*
+ * Returns the default metadata subbuf size.
+ *
+ * This function depends on a value that is set at constructor time, so it is
+ * unsafe to call it from another constructor.
+ */
+size_t default_get_metadata_subbuf_size(void);
+
+/*
+ * Returns the default subbuf size for the kernel domain.
+ *
+ * This function depends on a value that is set at constructor time, so it is
+ * unsafe to call it from another constructor.
+ */
+size_t default_get_kernel_channel_subbuf_size(void);
+
+/*
+ * Returns the default subbuf size for the UST domain per PID.
+ *
+ * This function depends on a value that is set at constructor time, so it is
+ * unsafe to call it from another constructor.
+ */
+size_t default_get_ust_pid_channel_subbuf_size(void);
+
+/*
+ * Returns the default subbuf size for the UST domain per UID.
+ *
+ * This function depends on a value that is set at constructor time, so it is
+ * unsafe to call it from another constructor.
+ */
+size_t default_get_ust_uid_channel_subbuf_size(void);
+
+/*
+ * Get the default pthread_attr to use on thread creation.
+ *
+ * Some libc, such as musl, don't honor the limit set for the stack size and use
+ * their own empirically chosen static value. This function checks if the
+ * current stack size is smaller than the stack size limit and if so returns a
+ * pthread_attr_t pointer where the thread stack size is set to the soft stack
+ * size limit.
+ */
+pthread_attr_t *default_pthread_attr(void);
+
+#endif /* _DEFAULTS_H */
index fb088faca187751c50e7750bba9075365334dc67..2c39c66e1ac6e4459a2860e09bb833f9034ecf25 100644 (file)
@@ -5,8 +5,8 @@
  *
  */
 
-#include "lttng/domain-internal.h"
-#include "common/macros.h"
+#include "lttng/domain-internal.hpp"
+#include "common/macros.hpp"
 
 const char *lttng_domain_type_str(enum lttng_domain_type domain_type)
 {
index d723ffacb385094097508250b5d28a40e4c3991c..ddc691bb13e76f4e5d0472584f5568b83633f523 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include <common/dynamic-array.h>
+#include <common/dynamic-array.hpp>
 
 void lttng_dynamic_array_init(struct lttng_dynamic_array *array,
                size_t element_size,
diff --git a/src/common/dynamic-array.h b/src/common/dynamic-array.h
deleted file mode 100644 (file)
index 8b08186..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_DYNAMIC_ARRAY_H
-#define LTTNG_DYNAMIC_ARRAY_H
-
-#include <common/dynamic-buffer.h>
-
-typedef void (*lttng_dynamic_array_element_destructor)(void *element);
-typedef void (*lttng_dynamic_pointer_array_destructor)(void *ptr);
-
-struct lttng_dynamic_array {
-       struct lttng_dynamic_buffer buffer;
-       size_t element_size;
-       size_t size;
-       lttng_dynamic_array_element_destructor destructor;
-};
-
-struct lttng_dynamic_pointer_array {
-       struct lttng_dynamic_array array;
-};
-
-/*
- * Initialize a resizable array of fixed-size elements. This performs no
- * allocation and can't fail.
- */
-void lttng_dynamic_array_init(struct lttng_dynamic_array *array,
-               size_t element_size,
-               lttng_dynamic_array_element_destructor destructor);
-
-/*
- * Returns the number of elements in the dynamic array.
- */
-static inline
-size_t lttng_dynamic_array_get_count(
-               const struct lttng_dynamic_array *array)
-{
-       return array->size;
-}
-
-/*
- * Returns a pointer to the element. Mutating operations on the array invalidate
- * the returned pointer.
- */
-static inline
-void *lttng_dynamic_array_get_element(const struct lttng_dynamic_array *array,
-               size_t element_index)
-{
-       LTTNG_ASSERT(element_index < array->size);
-       return array->buffer.data + (element_index * array->element_size);
-}
-
-/*
- * Set the array's element count to new_element_count. Any added element will
- * be zeroed.
- *
- * Be careful to expand the array's element count _before_ calling out external
- * APIs (e.g. read(3)) which may populate the buffer as setting the element
- * count after will zero-out the result of the operation.
- *
- * Shrinking an array does not zero the old content. If the buffer may contain
- * sensititve information, it must be cleared manually _before_ changing the
- * size.
- *
- * NOTE: It is striclty _invalid_ to access memory after _size_, regardless
- *       of prior calls to set_capacity().
- */
-int lttng_dynamic_array_set_count(struct lttng_dynamic_array *array,
-               size_t new_element_count);
-
-/*
- * Add an element to the end of a dynamic array. The array's element count is
- * increased by one and its underlying capacity is adjusted automatically.
- *
- * element is a pointer to the element to add (copy) to the array.
- */
-int lttng_dynamic_array_add_element(struct lttng_dynamic_array *array,
-               const void *element);
-
-/*
- * Remove an element from the dynamic array. The array's element count is
- * decreased by one and the following elements are shifted to take its place
- * (when applicable).
- */
-int lttng_dynamic_array_remove_element(struct lttng_dynamic_array *array,
-               size_t element_index);
-
-/* Release any memory used by the dynamic array. */
-void lttng_dynamic_array_reset(struct lttng_dynamic_array *array);
-
-/* Remove all elements from the dynamic array. */
-void lttng_dynamic_array_clear(struct lttng_dynamic_array *array);
-
-/*
- * Specialization of lttng_dynamic_array for pointers. This utility
- * is built under the assumption that pointer sizes are equal
- * for all data types on supported architectures. Revisit this in the event
- * of a port to an Harvard architecture.
- */
-
-/*
- * Initialize a resizable array of fixed-size elements. This performs no
- * allocation and can't fail.
- */
-void lttng_dynamic_pointer_array_init(
-               struct lttng_dynamic_pointer_array *array,
-               lttng_dynamic_pointer_array_destructor destructor);
-
-/*
- * Returns the number of pointers in the dynamic pointer array.
- */
-static inline
-size_t lttng_dynamic_pointer_array_get_count(
-               const struct lttng_dynamic_pointer_array *array)
-{
-       return lttng_dynamic_array_get_count(&array->array);
-}
-
-/*
- * Returns the pointer at index `index`.
- */
-static inline
-void *lttng_dynamic_pointer_array_get_pointer(
-               const struct lttng_dynamic_pointer_array *array, size_t index)
-{
-       void **element = (void **) lttng_dynamic_array_get_element(&array->array, index);
-
-       return *element;
-}
-
-/*
- * Returns the pointer at index `index`, sets the array slot to NULL. Does not
- * run the destructor.
- */
-
-static inline
-void *lttng_dynamic_pointer_array_steal_pointer(
-               struct lttng_dynamic_pointer_array *array, size_t index)
-{
-       void **p_element = (void **) lttng_dynamic_array_get_element(&array->array, index);
-       void *element = *p_element;
-
-       *p_element = NULL;
-
-       return element;
-}
-
-/*
- * Add a pointer to the end of a dynamic pointer array. The array's element
- * count is increased by one and its underlying capacity is adjusted
- * automatically.
- */
-static inline
-int lttng_dynamic_pointer_array_add_pointer(
-               struct lttng_dynamic_pointer_array *array, void *pointer)
-{
-       return lttng_dynamic_array_add_element(&array->array, &pointer);
-}
-
-/*
- * Remove a pointer from a dynamic pointer array. The array's element
- * count is decreased by one and the following pointers are shifted to
- * take the place of the removed pointer (if applicable).
- */
-int lttng_dynamic_pointer_array_remove_pointer(
-               struct lttng_dynamic_pointer_array *array, size_t index);
-
-/* Release any memory used by the dynamic array. */
-void lttng_dynamic_pointer_array_reset(
-               struct lttng_dynamic_pointer_array *array);
-
-/* Remove all elements from the dynamic pointer array. */
-void lttng_dynamic_pointer_array_clear(
-               struct lttng_dynamic_pointer_array *array);
-
-#endif /* LTTNG_DYNAMIC_ARRAY_H */
diff --git a/src/common/dynamic-array.hpp b/src/common/dynamic-array.hpp
new file mode 100644 (file)
index 0000000..23f3a39
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_DYNAMIC_ARRAY_H
+#define LTTNG_DYNAMIC_ARRAY_H
+
+#include <common/dynamic-buffer.hpp>
+
+typedef void (*lttng_dynamic_array_element_destructor)(void *element);
+typedef void (*lttng_dynamic_pointer_array_destructor)(void *ptr);
+
+struct lttng_dynamic_array {
+       struct lttng_dynamic_buffer buffer;
+       size_t element_size;
+       size_t size;
+       lttng_dynamic_array_element_destructor destructor;
+};
+
+struct lttng_dynamic_pointer_array {
+       struct lttng_dynamic_array array;
+};
+
+/*
+ * Initialize a resizable array of fixed-size elements. This performs no
+ * allocation and can't fail.
+ */
+void lttng_dynamic_array_init(struct lttng_dynamic_array *array,
+               size_t element_size,
+               lttng_dynamic_array_element_destructor destructor);
+
+/*
+ * Returns the number of elements in the dynamic array.
+ */
+static inline
+size_t lttng_dynamic_array_get_count(
+               const struct lttng_dynamic_array *array)
+{
+       return array->size;
+}
+
+/*
+ * Returns a pointer to the element. Mutating operations on the array invalidate
+ * the returned pointer.
+ */
+static inline
+void *lttng_dynamic_array_get_element(const struct lttng_dynamic_array *array,
+               size_t element_index)
+{
+       LTTNG_ASSERT(element_index < array->size);
+       return array->buffer.data + (element_index * array->element_size);
+}
+
+/*
+ * Set the array's element count to new_element_count. Any added element will
+ * be zeroed.
+ *
+ * Be careful to expand the array's element count _before_ calling out external
+ * APIs (e.g. read(3)) which may populate the buffer as setting the element
+ * count after will zero-out the result of the operation.
+ *
+ * Shrinking an array does not zero the old content. If the buffer may contain
+ * sensititve information, it must be cleared manually _before_ changing the
+ * size.
+ *
+ * NOTE: It is striclty _invalid_ to access memory after _size_, regardless
+ *       of prior calls to set_capacity().
+ */
+int lttng_dynamic_array_set_count(struct lttng_dynamic_array *array,
+               size_t new_element_count);
+
+/*
+ * Add an element to the end of a dynamic array. The array's element count is
+ * increased by one and its underlying capacity is adjusted automatically.
+ *
+ * element is a pointer to the element to add (copy) to the array.
+ */
+int lttng_dynamic_array_add_element(struct lttng_dynamic_array *array,
+               const void *element);
+
+/*
+ * Remove an element from the dynamic array. The array's element count is
+ * decreased by one and the following elements are shifted to take its place
+ * (when applicable).
+ */
+int lttng_dynamic_array_remove_element(struct lttng_dynamic_array *array,
+               size_t element_index);
+
+/* Release any memory used by the dynamic array. */
+void lttng_dynamic_array_reset(struct lttng_dynamic_array *array);
+
+/* Remove all elements from the dynamic array. */
+void lttng_dynamic_array_clear(struct lttng_dynamic_array *array);
+
+/*
+ * Specialization of lttng_dynamic_array for pointers. This utility
+ * is built under the assumption that pointer sizes are equal
+ * for all data types on supported architectures. Revisit this in the event
+ * of a port to an Harvard architecture.
+ */
+
+/*
+ * Initialize a resizable array of fixed-size elements. This performs no
+ * allocation and can't fail.
+ */
+void lttng_dynamic_pointer_array_init(
+               struct lttng_dynamic_pointer_array *array,
+               lttng_dynamic_pointer_array_destructor destructor);
+
+/*
+ * Returns the number of pointers in the dynamic pointer array.
+ */
+static inline
+size_t lttng_dynamic_pointer_array_get_count(
+               const struct lttng_dynamic_pointer_array *array)
+{
+       return lttng_dynamic_array_get_count(&array->array);
+}
+
+/*
+ * Returns the pointer at index `index`.
+ */
+static inline
+void *lttng_dynamic_pointer_array_get_pointer(
+               const struct lttng_dynamic_pointer_array *array, size_t index)
+{
+       void **element = (void **) lttng_dynamic_array_get_element(&array->array, index);
+
+       return *element;
+}
+
+/*
+ * Returns the pointer at index `index`, sets the array slot to NULL. Does not
+ * run the destructor.
+ */
+
+static inline
+void *lttng_dynamic_pointer_array_steal_pointer(
+               struct lttng_dynamic_pointer_array *array, size_t index)
+{
+       void **p_element = (void **) lttng_dynamic_array_get_element(&array->array, index);
+       void *element = *p_element;
+
+       *p_element = NULL;
+
+       return element;
+}
+
+/*
+ * Add a pointer to the end of a dynamic pointer array. The array's element
+ * count is increased by one and its underlying capacity is adjusted
+ * automatically.
+ */
+static inline
+int lttng_dynamic_pointer_array_add_pointer(
+               struct lttng_dynamic_pointer_array *array, void *pointer)
+{
+       return lttng_dynamic_array_add_element(&array->array, &pointer);
+}
+
+/*
+ * Remove a pointer from a dynamic pointer array. The array's element
+ * count is decreased by one and the following pointers are shifted to
+ * take the place of the removed pointer (if applicable).
+ */
+int lttng_dynamic_pointer_array_remove_pointer(
+               struct lttng_dynamic_pointer_array *array, size_t index);
+
+/* Release any memory used by the dynamic array. */
+void lttng_dynamic_pointer_array_reset(
+               struct lttng_dynamic_pointer_array *array);
+
+/* Remove all elements from the dynamic pointer array. */
+void lttng_dynamic_pointer_array_clear(
+               struct lttng_dynamic_pointer_array *array);
+
+#endif /* LTTNG_DYNAMIC_ARRAY_H */
index 945434ca9d6f2fd10fe2f357bdfe61d3a8ae2191..a12e1485d02132b77b60d153062c1b06879d21d1 100644 (file)
@@ -5,9 +5,9 @@
  *
  */
 
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <common/utils.h>
+#include <common/dynamic-buffer.hpp>
+#include <common/buffer-view.hpp>
+#include <common/utils.hpp>
 
 /*
  * Round to (upper) power of two, val is returned if it already is a power of
diff --git a/src/common/dynamic-buffer.h b/src/common/dynamic-buffer.h
deleted file mode 100644 (file)
index 0e0dedc..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_DYNAMIC_BUFFER_H
-#define LTTNG_DYNAMIC_BUFFER_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <common/macros.h>
-
-struct lttng_buffer_view;
-
-struct lttng_dynamic_buffer {
-       char *data;
-       /* size is the buffer's currently used capacity. */
-       size_t size;
-       /*
-        * capacity shall not be accessed by users directly, it is meant for
-        * internal use only.
-        */
-       size_t _capacity;
-};
-
-/*
- * Initialize a dynamic buffer. This performs no allocation and is meant
- * to be used instead of memset or explicit initialization of the buffer.
- */
-void lttng_dynamic_buffer_init(struct lttng_dynamic_buffer *buffer);
-
-/*
- * Append the content of a raw memory buffer to the end of a dynamic buffer
- * (after its current "size"). The dynamic buffer's size is increased by
- * "len", and its capacity is adjusted automatically.
- */
-int lttng_dynamic_buffer_append(struct lttng_dynamic_buffer *buffer,
-               const void *buf, size_t len);
-
-/*
- * Performs the same action as lttng_dynamic_buffer_append(), but using another
- * dynamic buffer as the source buffer. The source buffer's size is used in lieu
- * of "len".
- */
-int lttng_dynamic_buffer_append_buffer(struct lttng_dynamic_buffer *dst_buffer,
-               const struct lttng_dynamic_buffer *src_buffer);
-
-/*
- * Performs the same action as lttng_dynamic_buffer_append(), but using a
- * buffer view as the source buffer. The source buffer's size is used in lieu
- * of "len".
- */
-int lttng_dynamic_buffer_append_view(struct lttng_dynamic_buffer *buffer,
-               const struct lttng_buffer_view *view);
-
-/*
- * Set the buffer's size to new_size. The capacity of the buffer will
- * be expanded (if necessary) to accommodates new_size. Areas acquired by
- * a size increase will be zeroed.
- *
- * Be careful to expand the buffer's size _before_ calling out external
- * APIs (e.g. read(3)) which may populate the buffer as setting the size
- * after will zero-out the result of the operation.
- *
- * Shrinking a buffer does not zero the old content. If the buffer may contain
- * sensititve information, it must be cleared manually _before_ changing the
- * size.
- *
- * NOTE: It is striclty _invalid_ to access memory after _size_, regardless
- *       of prior calls to set_capacity().
- */
-int lttng_dynamic_buffer_set_size(struct lttng_dynamic_buffer *buffer,
-               size_t new_size);
-
-/*
- * Set the buffer's capacity to accommodates the new_capacity, allocating memory
- * as necessary. The buffer's content is preserved. Setting a buffer's capacity
- * is meant as a _hint_ to the underlying buffer and is only optimization; no
- * guarantee is offered that subsequent calls to append or set_size will succeed.
- *
- * If the current size > new_capacity, the operation will fail.
- */
-int lttng_dynamic_buffer_set_capacity(struct lttng_dynamic_buffer *buffer,
-               size_t new_capacity);
-
-/* Release any memory used by the dynamic buffer. */
-void lttng_dynamic_buffer_reset(struct lttng_dynamic_buffer *buffer);
-
-/* Get the space left in the buffer before a new resize is needed. */
-size_t lttng_dynamic_buffer_get_capacity_left(
-               struct lttng_dynamic_buffer *buffer);
-
-#endif /* LTTNG_DYNAMIC_BUFFER_H */
diff --git a/src/common/dynamic-buffer.hpp b/src/common/dynamic-buffer.hpp
new file mode 100644 (file)
index 0000000..65b1575
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_DYNAMIC_BUFFER_H
+#define LTTNG_DYNAMIC_BUFFER_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <common/macros.hpp>
+
+struct lttng_buffer_view;
+
+struct lttng_dynamic_buffer {
+       char *data;
+       /* size is the buffer's currently used capacity. */
+       size_t size;
+       /*
+        * capacity shall not be accessed by users directly, it is meant for
+        * internal use only.
+        */
+       size_t _capacity;
+};
+
+/*
+ * Initialize a dynamic buffer. This performs no allocation and is meant
+ * to be used instead of memset or explicit initialization of the buffer.
+ */
+void lttng_dynamic_buffer_init(struct lttng_dynamic_buffer *buffer);
+
+/*
+ * Append the content of a raw memory buffer to the end of a dynamic buffer
+ * (after its current "size"). The dynamic buffer's size is increased by
+ * "len", and its capacity is adjusted automatically.
+ */
+int lttng_dynamic_buffer_append(struct lttng_dynamic_buffer *buffer,
+               const void *buf, size_t len);
+
+/*
+ * Performs the same action as lttng_dynamic_buffer_append(), but using another
+ * dynamic buffer as the source buffer. The source buffer's size is used in lieu
+ * of "len".
+ */
+int lttng_dynamic_buffer_append_buffer(struct lttng_dynamic_buffer *dst_buffer,
+               const struct lttng_dynamic_buffer *src_buffer);
+
+/*
+ * Performs the same action as lttng_dynamic_buffer_append(), but using a
+ * buffer view as the source buffer. The source buffer's size is used in lieu
+ * of "len".
+ */
+int lttng_dynamic_buffer_append_view(struct lttng_dynamic_buffer *buffer,
+               const struct lttng_buffer_view *view);
+
+/*
+ * Set the buffer's size to new_size. The capacity of the buffer will
+ * be expanded (if necessary) to accommodates new_size. Areas acquired by
+ * a size increase will be zeroed.
+ *
+ * Be careful to expand the buffer's size _before_ calling out external
+ * APIs (e.g. read(3)) which may populate the buffer as setting the size
+ * after will zero-out the result of the operation.
+ *
+ * Shrinking a buffer does not zero the old content. If the buffer may contain
+ * sensititve information, it must be cleared manually _before_ changing the
+ * size.
+ *
+ * NOTE: It is striclty _invalid_ to access memory after _size_, regardless
+ *       of prior calls to set_capacity().
+ */
+int lttng_dynamic_buffer_set_size(struct lttng_dynamic_buffer *buffer,
+               size_t new_size);
+
+/*
+ * Set the buffer's capacity to accommodates the new_capacity, allocating memory
+ * as necessary. The buffer's content is preserved. Setting a buffer's capacity
+ * is meant as a _hint_ to the underlying buffer and is only optimization; no
+ * guarantee is offered that subsequent calls to append or set_size will succeed.
+ *
+ * If the current size > new_capacity, the operation will fail.
+ */
+int lttng_dynamic_buffer_set_capacity(struct lttng_dynamic_buffer *buffer,
+               size_t new_capacity);
+
+/* Release any memory used by the dynamic buffer. */
+void lttng_dynamic_buffer_reset(struct lttng_dynamic_buffer *buffer);
+
+/* Get the space left in the buffer before a new resize is needed. */
+size_t lttng_dynamic_buffer_get_capacity_left(
+               struct lttng_dynamic_buffer *buffer);
+
+#endif /* LTTNG_DYNAMIC_BUFFER_H */
index 3a0bbadcbcbcb5af550c815f1543660c4a2083ff..52d3d22d315fabfdcbd711544e869520a4b48b22 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include <lttng/endpoint-internal.h>
+#include <lttng/endpoint-internal.hpp>
 
 static
 struct lttng_endpoint lttng_session_daemon_notification_endpoint_instance = {
index 5d369c9e07563bfdba794694b69b22e1c74bb9a0..c7c735903f9086a090ca013858e0710ef85099fc 100644 (file)
@@ -7,17 +7,17 @@
  *
  */
 
-#include <common/dynamic-array.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/action/action-internal.h>
-#include <lttng/action/list-internal.h>
-#include <lttng/action/path-internal.h>
-#include <lttng/error-query-internal.h>
+#include <common/dynamic-array.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <lttng/action/action-internal.hpp>
+#include <lttng/action/list-internal.hpp>
+#include <lttng/action/path-internal.hpp>
+#include <lttng/error-query-internal.hpp>
 #include <lttng/error-query.h>
-#include <lttng/trigger/trigger-internal.h>
+#include <lttng/trigger/trigger-internal.hpp>
 #include <stddef.h>
 
 struct lttng_error_query {
index 6ca5557f473b3008a3eb1638f3b8a71bc10df474..67a1696ba784ff9b504a2a02b42c05028ea09474 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include <common/common.h>
-#include <common/thread.h>
-#include <common/compat/errno.h>
-#include <common/compat/getenv.h>
+#include <common/common.hpp>
+#include <common/thread.hpp>
+#include <common/compat/errno.hpp>
+#include <common/compat/getenv.hpp>
 #include <lttng/lttng-error.h>
 
-#include "error.h"
+#include "error.hpp"
 
 /*
  * lttng_opt_abort_on_error: unset: -1, disabled: 0, enabled: 1.
diff --git a/src/common/error.h b/src/common/error.h
deleted file mode 100644 (file)
index bcbb51b..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _ERROR_H
-#define _ERROR_H
-
-#include <common/compat/errno.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <urcu/tls-compat.h>
-#include <common/compat/time.h>
-#include <common/string-utils/format.h>
-#include <common/macros.h>
-
-#ifndef _GNU_SOURCE
-#error "lttng-tools error.h needs _GNU_SOURCE"
-#endif
-
-#include <lttng/lttng-error.h>
-#include <common/compat/tid.h>
-
-/* Avoid conflict with Solaris <sys/regset.h> */
-#if defined(ERR) && defined(__sun__)
-#undef ERR
-#endif
-
-/* Stringify the expansion of a define */
-#define XSTR(d) STR(d)
-#define STR(s) #s
-
-/*
- * Contains the string of the log entry time. This is used as a thread local
- * storage so we don't race between thread and also avoid memory allocation
- * every time a log is fired.
- */
-struct log_time {
-       /* Format: 00:00:00.000000000 plus NULL byte. */
-       char str[19];
-};
-extern LTTNG_EXPORT  DECLARE_URCU_TLS(struct log_time, error_log_time);
-extern DECLARE_URCU_TLS(const char *, logger_thread_name);
-
-extern int lttng_opt_quiet;
-extern int lttng_opt_verbose;
-extern int lttng_opt_mi;
-
-/* Error type. */
-enum lttng_error_level {
-       PRINT_ERR =     0,
-       PRINT_BUG =     1,
-       PRINT_WARN =    2,
-       PRINT_MSG =     3,
-       PRINT_DBG =     4,
-       PRINT_DBG2 =    5,
-       PRINT_DBG3 =    6,
-};
-
-static inline bool __lttng_print_check_opt(enum lttng_error_level type)
-{
-       /* lttng_opt_mi and lttng_opt_quiet. */
-       switch (type) {
-       case PRINT_DBG3:
-       case PRINT_DBG2:
-       case PRINT_DBG:
-       case PRINT_MSG:
-               if (lttng_opt_mi) {
-                       return false;
-               }
-               /* Fall-through. */
-       case PRINT_WARN:
-       case PRINT_BUG:
-       case PRINT_ERR:
-               if (lttng_opt_quiet) {
-                       return false;
-               }
-       }
-
-       /* lttng_opt_verbose */
-       switch (type) {
-       case PRINT_DBG3:
-               if (lttng_opt_verbose < 3) {
-                       return false;
-               }
-               break;
-       case PRINT_DBG2:
-               if (lttng_opt_verbose < 2) {
-                       return false;
-               }
-               break;
-       case PRINT_DBG:
-               if (lttng_opt_verbose < 1) {
-                       return false;
-               }
-               break;
-       case PRINT_MSG:
-       case PRINT_WARN:
-       case PRINT_BUG:
-       case PRINT_ERR:
-               break;
-       }
-
-       return true;
-}
-
-C_LINKAGE void lttng_abort_on_error(void);
-
-static inline void __lttng_print_check_abort(enum lttng_error_level type)
-{
-       switch (type) {
-       case PRINT_DBG3:
-       case PRINT_DBG2:
-       case PRINT_DBG:
-       case PRINT_MSG:
-       case PRINT_WARN:
-               break;
-       case PRINT_BUG:
-       case PRINT_ERR:
-               lttng_abort_on_error();
-       }
-}
-
-/*
- * Macro for printing message depending on command line option and verbosity.
- *
- * Machine interface:
- * We use lttng_opt_mi to suppress all normal msg to stdout. We don't
- * want any nested msg to show up when printing mi to stdout(if it's the case).
- * All warnings and errors should be printed to stderr as normal.
- */
-#define __lttng_print(type, fmt, args...)                                              \
-       do {                                                                            \
-               if (__lttng_print_check_opt(type)) {                                    \
-                       fprintf((type) == PRINT_MSG ? stdout : stderr, fmt, ## args);   \
-               }                                                                       \
-               __lttng_print_check_abort(type);                                        \
-       } while (0)
-
-/* Three level of debug. Use -v, -vv or -vvv for the levels */
-#define _ERRMSG(msg, type, fmt, args...)                                \
-       do {                                                            \
-               if (caa_unlikely(__lttng_print_check_opt(type))) {      \
-                       char generic_name[MAX_INT_DEC_LEN(long) +       \
-                                         MAX_INT_DEC_LEN(long)];       \
-                                                                        \
-                       snprintf(generic_name, sizeof(generic_name),    \
-                                       "%ld/%ld", (long) getpid(),     \
-                                       (long) lttng_gettid());         \
-                                                                        \
-                       __lttng_print(type,                             \
-                                       msg " - %s [%s]: " fmt          \
-                                           " (in %s() at " __FILE__    \
-                                           ":" XSTR(__LINE__) ")\n",   \
-                                       log_add_time(),                 \
-                                       URCU_TLS(logger_thread_name) ?: \
-                                                       generic_name,   \
-                                       ##args, __func__);              \
-               }                                                       \
-       } while (0)
-
-#define _ERRMSG_NO_LOC(msg, type, fmt, args...)                          \
-       do {                                                             \
-               if (caa_unlikely(__lttng_print_check_opt(type))) {       \
-                       char generic_name[MAX_INT_DEC_LEN(long) +        \
-                                         MAX_INT_DEC_LEN(long)];        \
-                                                                         \
-                       snprintf(generic_name, sizeof(generic_name),     \
-                                       "%ld/%ld", (long) getpid(),      \
-                                       (long) lttng_gettid());          \
-                                                                         \
-                       __lttng_print(type, msg " - %s [%s]: " fmt "\n", \
-                                       log_add_time(),                  \
-                                       URCU_TLS(logger_thread_name) ?:  \
-                                                       generic_name,    \
-                                       ##args);                         \
-               }                                                        \
-       } while (0)
-
-#define MSG(fmt, args...) \
-       __lttng_print(PRINT_MSG, fmt "\n", ## args)
-#define _MSG(fmt, args...) \
-       __lttng_print(PRINT_MSG, fmt, ## args)
-#define ERR(fmt, args...) \
-       __lttng_print(PRINT_ERR, "Error: " fmt "\n", ## args)
-#define WARN(fmt, args...) \
-       __lttng_print(PRINT_WARN, "Warning: " fmt "\n", ## args)
-
-#define BUG(fmt, args...) _ERRMSG("BUG", PRINT_BUG, fmt, ## args)
-
-#define DBG(fmt, args...) _ERRMSG("DBG1", PRINT_DBG, fmt, ## args)
-#define DBG_NO_LOC(fmt, args...) _ERRMSG_NO_LOC("DBG1", PRINT_DBG, fmt, ## args)
-#define DBG2(fmt, args...) _ERRMSG("DBG2", PRINT_DBG2, fmt, ## args)
-#define DBG3(fmt, args...) _ERRMSG("DBG3", PRINT_DBG3, fmt, ## args)
-#define LOG(type, fmt, args...)                        \
-       do {                                    \
-               switch (type) {                 \
-               case PRINT_ERR:                 \
-                       ERR(fmt, ## args);      \
-                       break;                  \
-               case PRINT_WARN:                \
-                       WARN(fmt, ## args);     \
-                       break;                  \
-               case PRINT_BUG:                 \
-                       BUG(fmt, ## args);      \
-                       break;                  \
-               case PRINT_MSG:                 \
-                       MSG(fmt, ## args);      \
-                       break;                  \
-               case PRINT_DBG:                 \
-                       DBG(fmt, ## args);      \
-                       break;                  \
-               case PRINT_DBG2:                \
-                       DBG2(fmt, ## args);     \
-                       break;                  \
-               case PRINT_DBG3:                \
-                       DBG3(fmt, ## args);     \
-                       break;                  \
-               default:                        \
-                       abort();                \
-               }                               \
-       } while(0);
-
-#define _PERROR(fmt, args...) _ERRMSG("PERROR", PRINT_ERR, fmt, ## args)
-
-#if !defined(__GLIBC__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined(_GNU_SOURCE))
-
-/*
- * Version using XSI strerror_r.
- */
-#define PERROR(call, args...)                                        \
-       do {                                                         \
-               char _perror_buf[200];                               \
-               strerror_r(errno, _perror_buf, sizeof(_perror_buf)); \
-               _PERROR(call ": %s", ##args, _perror_buf);           \
-       } while (0);
-#else
-/*
- * Version using GNU strerror_r, for linux with appropriate defines.
- */
-#define PERROR(call, args...)                                             \
-       do {                                                              \
-               char *_perror_buf;                                        \
-               char _perror_tmp[200];                                    \
-               _perror_buf = strerror_r(                                 \
-                               errno, _perror_tmp, sizeof(_perror_tmp)); \
-               _PERROR(call ": %s", ##args, _perror_buf);                \
-       } while (0);
-#endif
-
-const char *error_get_str(int32_t code);
-
-/*
- * Function that format the time and return the reference of log_time.str to
- * the caller. On error, an empty string is returned thus no time will be
- * printed in the log.
- */
-const char *log_add_time(void);
-
-/* Name must be a statically-allocated string. */
-void logger_set_thread_name(const char *name, bool set_pthread_name);
-
-#endif /* _ERROR_H */
diff --git a/src/common/error.hpp b/src/common/error.hpp
new file mode 100644 (file)
index 0000000..88d93ec
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _ERROR_H
+#define _ERROR_H
+
+#include <common/compat/errno.hpp>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <urcu/tls-compat.h>
+#include <common/compat/time.hpp>
+#include <common/string-utils/format.hpp>
+#include <common/macros.hpp>
+
+#ifndef _GNU_SOURCE
+#error "lttng-tools error.h needs _GNU_SOURCE"
+#endif
+
+#include <lttng/lttng-error.h>
+#include <common/compat/tid.hpp>
+
+/* Avoid conflict with Solaris <sys/regset.h> */
+#if defined(ERR) && defined(__sun__)
+#undef ERR
+#endif
+
+/* Stringify the expansion of a define */
+#define XSTR(d) STR(d)
+#define STR(s) #s
+
+/*
+ * Contains the string of the log entry time. This is used as a thread local
+ * storage so we don't race between thread and also avoid memory allocation
+ * every time a log is fired.
+ */
+struct log_time {
+       /* Format: 00:00:00.000000000 plus NULL byte. */
+       char str[19];
+};
+extern LTTNG_EXPORT  DECLARE_URCU_TLS(struct log_time, error_log_time);
+extern DECLARE_URCU_TLS(const char *, logger_thread_name);
+
+extern int lttng_opt_quiet;
+extern int lttng_opt_verbose;
+extern int lttng_opt_mi;
+
+/* Error type. */
+enum lttng_error_level {
+       PRINT_ERR =     0,
+       PRINT_BUG =     1,
+       PRINT_WARN =    2,
+       PRINT_MSG =     3,
+       PRINT_DBG =     4,
+       PRINT_DBG2 =    5,
+       PRINT_DBG3 =    6,
+};
+
+static inline bool __lttng_print_check_opt(enum lttng_error_level type)
+{
+       /* lttng_opt_mi and lttng_opt_quiet. */
+       switch (type) {
+       case PRINT_DBG3:
+       case PRINT_DBG2:
+       case PRINT_DBG:
+       case PRINT_MSG:
+               if (lttng_opt_mi) {
+                       return false;
+               }
+               /* Fall-through. */
+       case PRINT_WARN:
+       case PRINT_BUG:
+       case PRINT_ERR:
+               if (lttng_opt_quiet) {
+                       return false;
+               }
+       }
+
+       /* lttng_opt_verbose */
+       switch (type) {
+       case PRINT_DBG3:
+               if (lttng_opt_verbose < 3) {
+                       return false;
+               }
+               break;
+       case PRINT_DBG2:
+               if (lttng_opt_verbose < 2) {
+                       return false;
+               }
+               break;
+       case PRINT_DBG:
+               if (lttng_opt_verbose < 1) {
+                       return false;
+               }
+               break;
+       case PRINT_MSG:
+       case PRINT_WARN:
+       case PRINT_BUG:
+       case PRINT_ERR:
+               break;
+       }
+
+       return true;
+}
+
+C_LINKAGE void lttng_abort_on_error(void);
+
+static inline void __lttng_print_check_abort(enum lttng_error_level type)
+{
+       switch (type) {
+       case PRINT_DBG3:
+       case PRINT_DBG2:
+       case PRINT_DBG:
+       case PRINT_MSG:
+       case PRINT_WARN:
+               break;
+       case PRINT_BUG:
+       case PRINT_ERR:
+               lttng_abort_on_error();
+       }
+}
+
+/*
+ * Macro for printing message depending on command line option and verbosity.
+ *
+ * Machine interface:
+ * We use lttng_opt_mi to suppress all normal msg to stdout. We don't
+ * want any nested msg to show up when printing mi to stdout(if it's the case).
+ * All warnings and errors should be printed to stderr as normal.
+ */
+#define __lttng_print(type, fmt, args...)                                              \
+       do {                                                                            \
+               if (__lttng_print_check_opt(type)) {                                    \
+                       fprintf((type) == PRINT_MSG ? stdout : stderr, fmt, ## args);   \
+               }                                                                       \
+               __lttng_print_check_abort(type);                                        \
+       } while (0)
+
+/* Three level of debug. Use -v, -vv or -vvv for the levels */
+#define _ERRMSG(msg, type, fmt, args...)                                \
+       do {                                                            \
+               if (caa_unlikely(__lttng_print_check_opt(type))) {      \
+                       char generic_name[MAX_INT_DEC_LEN(long) +       \
+                                         MAX_INT_DEC_LEN(long)];       \
+                                                                        \
+                       snprintf(generic_name, sizeof(generic_name),    \
+                                       "%ld/%ld", (long) getpid(),     \
+                                       (long) lttng_gettid());         \
+                                                                        \
+                       __lttng_print(type,                             \
+                                       msg " - %s [%s]: " fmt          \
+                                           " (in %s() at " __FILE__    \
+                                           ":" XSTR(__LINE__) ")\n",   \
+                                       log_add_time(),                 \
+                                       URCU_TLS(logger_thread_name) ?: \
+                                                       generic_name,   \
+                                       ##args, __func__);              \
+               }                                                       \
+       } while (0)
+
+#define _ERRMSG_NO_LOC(msg, type, fmt, args...)                          \
+       do {                                                             \
+               if (caa_unlikely(__lttng_print_check_opt(type))) {       \
+                       char generic_name[MAX_INT_DEC_LEN(long) +        \
+                                         MAX_INT_DEC_LEN(long)];        \
+                                                                         \
+                       snprintf(generic_name, sizeof(generic_name),     \
+                                       "%ld/%ld", (long) getpid(),      \
+                                       (long) lttng_gettid());          \
+                                                                         \
+                       __lttng_print(type, msg " - %s [%s]: " fmt "\n", \
+                                       log_add_time(),                  \
+                                       URCU_TLS(logger_thread_name) ?:  \
+                                                       generic_name,    \
+                                       ##args);                         \
+               }                                                        \
+       } while (0)
+
+#define MSG(fmt, args...) \
+       __lttng_print(PRINT_MSG, fmt "\n", ## args)
+#define _MSG(fmt, args...) \
+       __lttng_print(PRINT_MSG, fmt, ## args)
+#define ERR(fmt, args...) \
+       __lttng_print(PRINT_ERR, "Error: " fmt "\n", ## args)
+#define WARN(fmt, args...) \
+       __lttng_print(PRINT_WARN, "Warning: " fmt "\n", ## args)
+
+#define BUG(fmt, args...) _ERRMSG("BUG", PRINT_BUG, fmt, ## args)
+
+#define DBG(fmt, args...) _ERRMSG("DBG1", PRINT_DBG, fmt, ## args)
+#define DBG_NO_LOC(fmt, args...) _ERRMSG_NO_LOC("DBG1", PRINT_DBG, fmt, ## args)
+#define DBG2(fmt, args...) _ERRMSG("DBG2", PRINT_DBG2, fmt, ## args)
+#define DBG3(fmt, args...) _ERRMSG("DBG3", PRINT_DBG3, fmt, ## args)
+#define LOG(type, fmt, args...)                        \
+       do {                                    \
+               switch (type) {                 \
+               case PRINT_ERR:                 \
+                       ERR(fmt, ## args);      \
+                       break;                  \
+               case PRINT_WARN:                \
+                       WARN(fmt, ## args);     \
+                       break;                  \
+               case PRINT_BUG:                 \
+                       BUG(fmt, ## args);      \
+                       break;                  \
+               case PRINT_MSG:                 \
+                       MSG(fmt, ## args);      \
+                       break;                  \
+               case PRINT_DBG:                 \
+                       DBG(fmt, ## args);      \
+                       break;                  \
+               case PRINT_DBG2:                \
+                       DBG2(fmt, ## args);     \
+                       break;                  \
+               case PRINT_DBG3:                \
+                       DBG3(fmt, ## args);     \
+                       break;                  \
+               default:                        \
+                       abort();                \
+               }                               \
+       } while(0);
+
+#define _PERROR(fmt, args...) _ERRMSG("PERROR", PRINT_ERR, fmt, ## args)
+
+#if !defined(__GLIBC__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined(_GNU_SOURCE))
+
+/*
+ * Version using XSI strerror_r.
+ */
+#define PERROR(call, args...)                                        \
+       do {                                                         \
+               char _perror_buf[200];                               \
+               strerror_r(errno, _perror_buf, sizeof(_perror_buf)); \
+               _PERROR(call ": %s", ##args, _perror_buf);           \
+       } while (0);
+#else
+/*
+ * Version using GNU strerror_r, for linux with appropriate defines.
+ */
+#define PERROR(call, args...)                                             \
+       do {                                                              \
+               char *_perror_buf;                                        \
+               char _perror_tmp[200];                                    \
+               _perror_buf = strerror_r(                                 \
+                               errno, _perror_tmp, sizeof(_perror_tmp)); \
+               _PERROR(call ": %s", ##args, _perror_buf);                \
+       } while (0);
+#endif
+
+const char *error_get_str(int32_t code);
+
+/*
+ * Function that format the time and return the reference of log_time.str to
+ * the caller. On error, an empty string is returned thus no time will be
+ * printed in the log.
+ */
+const char *log_add_time(void);
+
+/* Name must be a statically-allocated string. */
+void logger_set_thread_name(const char *name, bool set_pthread_name);
+
+#endif /* _ERROR_H */
index 6b3e634947253812329f099770d2345f999622b1..a0fbc9dd905e1c247eedd3f16ae7837341158099 100644 (file)
@@ -5,14 +5,14 @@
  *
  */
 
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/evaluation-internal.h>
-#include <lttng/condition/buffer-usage-internal.h>
-#include <lttng/condition/session-consumed-size-internal.h>
-#include <lttng/condition/session-rotation-internal.h>
-#include <lttng/condition/event-rule-matches-internal.h>
-#include <common/macros.h>
-#include <common/error.h>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/evaluation-internal.hpp>
+#include <lttng/condition/buffer-usage-internal.hpp>
+#include <lttng/condition/session-consumed-size-internal.hpp>
+#include <lttng/condition/session-rotation-internal.hpp>
+#include <lttng/condition/event-rule-matches-internal.hpp>
+#include <common/macros.hpp>
+#include <common/error.hpp>
 #include <stdbool.h>
 
 void lttng_evaluation_init(struct lttng_evaluation *evaluation,
index e80fb1d5df4d269627847bb0ccb74f7d246fb666..9306dbeee76571c0cb210b99f0360cf9b0f1464a 100644 (file)
 #define _LGPL_SOURCE
 #include <stddef.h>
 
-#include <common/bytecode/bytecode.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <lttng/event-expr-internal.h>
+#include <common/bytecode/bytecode.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/event-expr-internal.hpp>
 #include <lttng/event-expr.h>
 #include <stdio.h>
 
index 7572713137ae810b21eef141e7b57a370ea3907b..816017a2da77fe1e316fdf0f347c1bcfa0512df4 100644 (file)
@@ -13,9 +13,9 @@
 #include <stddef.h>
 #include <stdbool.h>
 
-#include <common/error.h>
-#include <common/macros.h>
-#include <lttng/event-field-value-internal.h>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <lttng/event-field-value-internal.hpp>
 
 static
 struct lttng_event_field_value *create_empty_field_val(
index 7e3f7248ee3a562448ebf0574443eee5048b834a..8c1b81dbd3ee77e1594a3663da4007ccb72f9ca3 100644 (file)
@@ -6,22 +6,22 @@
  *
  */
 
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/jul-logging-internal.h>
-#include <lttng/event-rule/kernel-kprobe-internal.h>
-#include <lttng/event-rule/kernel-syscall-internal.h>
-#include <lttng/event-rule/kernel-tracepoint-internal.h>
-#include <lttng/event-rule/kernel-uprobe-internal.h>
-#include <lttng/event-rule/log4j-logging-internal.h>
-#include <lttng/event-rule/python-logging-internal.h>
-#include <lttng/event-rule/user-tracepoint-internal.h>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/jul-logging-internal.hpp>
+#include <lttng/event-rule/kernel-kprobe-internal.hpp>
+#include <lttng/event-rule/kernel-syscall-internal.hpp>
+#include <lttng/event-rule/kernel-tracepoint-internal.hpp>
+#include <lttng/event-rule/kernel-uprobe-internal.hpp>
+#include <lttng/event-rule/log4j-logging-internal.hpp>
+#include <lttng/event-rule/python-logging-internal.hpp>
+#include <lttng/event-rule/user-tracepoint-internal.hpp>
 #include <stdbool.h>
 
 enum lttng_event_rule_type lttng_event_rule_get_type(
index 77ae3800c2fc30a98efdc68a8e66af85a3949332..02cb1d354030d15f2c521ae25a4e3b415bb488d3 100644 (file)
@@ -5,19 +5,19 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/optional.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/runas.h>
-#include <common/string-utils/string-utils.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/jul-logging-internal.h>
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/jul-logging-internal.hpp>
 #include <lttng/event.h>
 #include <lttng/log-level-rule.h>
 
index d33d446055c2f1f152276aad719ee2ba3c02f539..72b87c8a5feca36a94e7b2f8fd130eabcfc9c92e 100644 (file)
@@ -5,21 +5,21 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/runas.h>
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
 #include <ctype.h>
 #include <lttng/constant.h>
-#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/event-rule-internal.hpp>
 #include <lttng/event-rule/event-rule.h>
-#include <lttng/event-rule/kernel-kprobe-internal.h>
-#include <lttng/kernel-probe-internal.h>
+#include <lttng/event-rule/kernel-kprobe-internal.hpp>
+#include <lttng/kernel-probe-internal.hpp>
 #include <lttng/kernel-probe.h>
 #include <stdio.h>
 
index 3f8e64ed804cd7ce98b1cd9579cfc10135586a60..74b7f4b1895c06c6bc7b76d8a0b174be71938d89 100644 (file)
@@ -5,18 +5,18 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/runas.h>
-#include <common/string-utils/string-utils.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/kernel-syscall-internal.h>
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/kernel-syscall-internal.hpp>
 
 #define IS_SYSCALL_EVENT_RULE(rule) \
        (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL)
index cff3048f30995b7dff94f436c0a0312fa50f3f04..513e8a7131b2dee3acfb940e04faab19f9caab4d 100644 (file)
@@ -5,19 +5,19 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/optional.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/runas.h>
-#include <common/string-utils/string-utils.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/kernel-tracepoint-internal.h>
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/kernel-tracepoint-internal.hpp>
 #include <lttng/event.h>
 
 #define IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) \
index d53958df6e20c40e49902c6bc3f38a62c1962390..efec01981c9d27302e59880b5f3b6344ec71c466 100644 (file)
@@ -5,18 +5,18 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/runas.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/kernel-uprobe-internal.h>
-#include <lttng/userspace-probe-internal.h>
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/kernel-uprobe-internal.hpp>
+#include <lttng/userspace-probe-internal.hpp>
 
 #define IS_UPROBE_EVENT_RULE(rule) \
        (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE)
index 25f2c4c0e7ee5d5344bc228a018262365f0af3e6..30ea0bc55cbf9b08b8b4f5348b26c3de11cd9166 100644 (file)
@@ -5,19 +5,19 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/optional.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/runas.h>
-#include <common/string-utils/string-utils.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/log4j-logging-internal.h>
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/log4j-logging-internal.hpp>
 #include <lttng/event.h>
 #include <lttng/log-level-rule.h>
 
index 1ccd495cdf6f909b191e6d4c7e573717ecc8b18d..29ff3fc5602ddc84659fefe847ed1defa9485245 100644 (file)
@@ -5,19 +5,19 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/optional.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/runas.h>
-#include <common/string-utils/string-utils.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/python-logging-internal.h>
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/python-logging-internal.hpp>
 #include <lttng/event.h>
 #include <lttng/log-level-rule.h>
 
index 5158eeaa072c992a57aa777e4ee8fe0552ea40b5..e094d71c962fd88f913289a7fc71361755ff7034 100644 (file)
@@ -5,19 +5,19 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/optional.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/runas.h>
-#include <common/string-utils/string-utils.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/user-tracepoint-internal.h>
+#include <common/credentials.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/runas.hpp>
+#include <common/string-utils/string-utils.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/user-tracepoint-internal.hpp>
 #include <lttng/event.h>
 #include <lttng/log-level-rule.h>
 
index 6b22fecf52799f1bd7a26fc97f84d5ab0db18fef..7cd26b60b39ce9ad9b4c456443be8b5d7b11622e 100644 (file)
@@ -5,8 +5,8 @@
  *
  */
 
-#include <lttng/event-internal.h>
-#include <common/error.h>
+#include <lttng/event-internal.hpp>
+#include <common/error.hpp>
 
 struct lttng_event *lttng_event_copy(const struct lttng_event *event)
 {
index d8b5b785d11679d25d045a08e4df0e93592c7072..7473f071789982ca1c169812ef6d109430269269 100644 (file)
@@ -8,8 +8,8 @@
 #include <unistd.h>
 #include <urcu/ref.h>
 
-#include "fd-handle.h"
-#include <common/error.h>
+#include "fd-handle.hpp"
+#include <common/error.hpp>
 
 struct fd_handle {
        struct urcu_ref ref;
diff --git a/src/common/fd-handle.h b/src/common/fd-handle.h
deleted file mode 100644 (file)
index dab9e2b..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef FD_HANDLE_H
-#define FD_HANDLE_H
-
-#include <common/macros.h>
-
-/*
- * Wrapper around a file descriptor providing reference counting semantics.
- *
- * An fd_handle will close() the underlying file descriptor when its reference
- * count reaches zero.
- */
-struct fd_handle;
-
-/* Create a file descriptor handle. */
-struct fd_handle *fd_handle_create(int fd);
-
-/* Acquire reference to a file descriptor handle. */
-void fd_handle_get(struct fd_handle *handle);
-
-/* Release reference to a file descriptor handle. */
-void fd_handle_put(struct fd_handle *handle);
-
-/*
- * Return the underlying file descriptor of a file descriptor handle.
- *
- * This function can't fail.
- */
-int fd_handle_get_fd(struct fd_handle *handle);
-
-/*
- * Obtain a copy of a file descriptor handle.
- *
- * On success, the caller becomes the sole owner of the returned file descriptor
- * handle. The underlying file descriptor is duplicated using dup(). Refer to
- * the system documentation for the semantics of dup() for this particular file
- * descriptor type.
- */
-struct fd_handle *fd_handle_copy(const struct fd_handle *handle);
-
-#endif /* FS_HANDLE_H */
diff --git a/src/common/fd-handle.hpp b/src/common/fd-handle.hpp
new file mode 100644 (file)
index 0000000..877e88a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef FD_HANDLE_H
+#define FD_HANDLE_H
+
+#include <common/macros.hpp>
+
+/*
+ * Wrapper around a file descriptor providing reference counting semantics.
+ *
+ * An fd_handle will close() the underlying file descriptor when its reference
+ * count reaches zero.
+ */
+struct fd_handle;
+
+/* Create a file descriptor handle. */
+struct fd_handle *fd_handle_create(int fd);
+
+/* Acquire reference to a file descriptor handle. */
+void fd_handle_get(struct fd_handle *handle);
+
+/* Release reference to a file descriptor handle. */
+void fd_handle_put(struct fd_handle *handle);
+
+/*
+ * Return the underlying file descriptor of a file descriptor handle.
+ *
+ * This function can't fail.
+ */
+int fd_handle_get_fd(struct fd_handle *handle);
+
+/*
+ * Obtain a copy of a file descriptor handle.
+ *
+ * On success, the caller becomes the sole owner of the returned file descriptor
+ * handle. The underlying file descriptor is duplicated using dup(). Refer to
+ * the system documentation for the semantics of dup() for this particular file
+ * descriptor type.
+ */
+struct fd_handle *fd_handle_copy(const struct fd_handle *handle);
+
+#endif /* FS_HANDLE_H */
diff --git a/src/common/fd-tracker/Makefile.am b/src/common/fd-tracker/Makefile.am
deleted file mode 100644 (file)
index 68e63d4..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libfd-tracker.la
-
-libfd_tracker_la_SOURCES = \
-       fd-tracker.cpp \
-       fd-tracker.h \
-       inode.cpp \
-       inode.h \
-       utils.cpp \
-       utils.h \
-       utils-poll.cpp
index e511d6901884cb7992f7da3b6020a1b8625c9b4d..bd156dc03938676e626bd3255a2ce950d0d58832 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/fs-handle-internal.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/optional.h>
-
-#include "fd-tracker.h"
-#include "inode.h"
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/fs-handle-internal.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+
+#include "fd-tracker.hpp"
+#include "inode.hpp"
 
 /* Tracker lock must be taken by the user. */
 #define TRACKED_COUNT(tracker)                                 \
diff --git a/src/common/fd-tracker/fd-tracker.h b/src/common/fd-tracker/fd-tracker.h
deleted file mode 100644 (file)
index 5c98107..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef FD_TRACKER_H
-#define FD_TRACKER_H
-
-#include <common/compat/directory-handle.h>
-#include <common/macros.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-struct fs_handle;
-struct fd_tracker;
-
-/*
- * Callback which returns a file descriptor to track through the fd
- * tracker. This callback must not make use of the fd_tracker as a deadlock
- * may occur.
- *
- * The int pointer argument is an output parameter that should be used to return
- * the advertised number of file descriptors.
- *
- * Must return zero on success. Negative values should map to a UNIX error code.
- */
-typedef int (*fd_open_cb)(void *, int *out_fds);
-
-/*
- * Callback to allow the user to close a now-untracked file descriptor. This
- * callback must not make use of the fd_tracker as a deadlock may occur.
- *
- * The callback can freely modify the in_fds argument as it is copied by the
- * fd_tracker before being used. The fd tracker assumes in_fds to be closed by
- * the time the callback returns.
- *
- * Must return zero on success. Negative values should map to a UNIX error code.
- */
-typedef int (*fd_close_cb)(void *, int *in_fds);
-
-/*
- * Set the maximal number of fds that the process should be allowed to open at
- * any given time. This function must be called before any other of this
- * interface.
- *
- * The unlinked_file_path is an absolute path (which does not need to exist)
- * under which unlinked files will be stored for as long as a reference to them
- * is held.
- */
-struct fd_tracker *fd_tracker_create(const char *unlinked_file_path,
-               unsigned int capacity);
-
-/* Returns an error if file descriptors are leaked. */
-int fd_tracker_destroy(struct fd_tracker *tracker);
-
-/*
- * Open a handle to a suspendable filesystem file descriptor.
- *
- * See OPEN(3) for an explanation of flags and mode. NULL is returned in case of
- * error and errno is left untouched. Note that passing NULL as mode will result
- * in open()'s default behaviour being used (using the process' umask).
- *
- * A fs_handle wraps a file descriptor created by OPEN(3). It is suspendable
- * meaning that the underlying file may be closed at any time unless the
- * handle is marked as being in-use (see fs_handle_get_fd() and
- * fs_handle_put_fd()).
- *
- * If the tracker opted to close the underlying file descriptor, it will
- * be restored to its last known state when it is obtained through
- * the fs_handle's fs_handle_get_fd() method.
- *
- * Note that a suspendable file descriptor can be closed by the fd tracker at
- * anytime when it is not in use. This means that the user should not rely on it
- * being safe to unlink the file. Moreover, concurent modifications to the file
- * (e.g. truncation) may react differently than if the file descriptor was kept
- * open.
- */
-struct fs_handle *fd_tracker_open_fs_handle(struct fd_tracker *tracker,
-               struct lttng_directory_handle *directory,
-               const char *path,
-               int flags,
-               mode_t *mode);
-
-/*
- * Open a tracked unsuspendable file descriptor.
- *
- * This function allows the fd tracker to keep track of unsuspendable
- * file descriptors. A callback, open, is passed to allow the tracker
- * to atomically reserve an entry for a given count of new file descriptors,
- * suspending file descriptors as needed, and invoke the provided callback
- * without ever exceeding the tracker's capacity.
- *
- * fd_count indicates the count of file descriptors that will be opened and
- * returned by the open callback. The storage location at out_fds is assumed
- * to be large enough to hold 'fd_count * sizeof(int)'.
- *
- * Names may be provided to allow easier debugging of file descriptor
- * exhaustions.
- *
- * The callback's return value is returned to the user. Additionally, two
- * negative tracker-specific codes may be returned:
- *   - ENOMEM: allocation of a new entry failed,
- *   - EMFILE: too many unsuspendable fds are opened and the tracker can't
- *             accommodates the request for a new unsuspendable entry.
- */
-int fd_tracker_open_unsuspendable_fd(struct fd_tracker *tracker,
-               int *out_fds,
-               const char **names,
-               unsigned int fd_count,
-               fd_open_cb open,
-               void *data);
-
-/*
- * Close a tracked unsuspendable file descriptor.
- *
- * This function allows the fd tracker to keep track of unsuspendable
- * file descriptors. A callback, close, is passed to allow the tracker
- * to atomically release a file descriptor entry.
- *
- * Returns 0 if the close callback returned success. Returns the value returned
- * by the close callback if it is negative. Additionally, a tracker-specific
- * code may be returned:
- *   - EINVAL: a file descriptor was unknown to the tracker
- *
- * Closed fds are set to -1 in the fds array which, in the event of an error,
- * allows the user to know which file descriptors are no longer being tracked.
- */
-int fd_tracker_close_unsuspendable_fd(struct fd_tracker *tracker,
-               int *fds,
-               unsigned int fd_count,
-               fd_close_cb close,
-               void *data);
-
-/*
- * Log the contents of the fd_tracker.
- */
-void fd_tracker_log(struct fd_tracker *tracker);
-
-#endif /* FD_TRACKER_H */
diff --git a/src/common/fd-tracker/fd-tracker.hpp b/src/common/fd-tracker/fd-tracker.hpp
new file mode 100644 (file)
index 0000000..a38c880
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef FD_TRACKER_H
+#define FD_TRACKER_H
+
+#include <common/compat/directory-handle.hpp>
+#include <common/macros.hpp>
+#include <stdint.h>
+#include <sys/types.h>
+
+struct fs_handle;
+struct fd_tracker;
+
+/*
+ * Callback which returns a file descriptor to track through the fd
+ * tracker. This callback must not make use of the fd_tracker as a deadlock
+ * may occur.
+ *
+ * The int pointer argument is an output parameter that should be used to return
+ * the advertised number of file descriptors.
+ *
+ * Must return zero on success. Negative values should map to a UNIX error code.
+ */
+typedef int (*fd_open_cb)(void *, int *out_fds);
+
+/*
+ * Callback to allow the user to close a now-untracked file descriptor. This
+ * callback must not make use of the fd_tracker as a deadlock may occur.
+ *
+ * The callback can freely modify the in_fds argument as it is copied by the
+ * fd_tracker before being used. The fd tracker assumes in_fds to be closed by
+ * the time the callback returns.
+ *
+ * Must return zero on success. Negative values should map to a UNIX error code.
+ */
+typedef int (*fd_close_cb)(void *, int *in_fds);
+
+/*
+ * Set the maximal number of fds that the process should be allowed to open at
+ * any given time. This function must be called before any other of this
+ * interface.
+ *
+ * The unlinked_file_path is an absolute path (which does not need to exist)
+ * under which unlinked files will be stored for as long as a reference to them
+ * is held.
+ */
+struct fd_tracker *fd_tracker_create(const char *unlinked_file_path,
+               unsigned int capacity);
+
+/* Returns an error if file descriptors are leaked. */
+int fd_tracker_destroy(struct fd_tracker *tracker);
+
+/*
+ * Open a handle to a suspendable filesystem file descriptor.
+ *
+ * See OPEN(3) for an explanation of flags and mode. NULL is returned in case of
+ * error and errno is left untouched. Note that passing NULL as mode will result
+ * in open()'s default behaviour being used (using the process' umask).
+ *
+ * A fs_handle wraps a file descriptor created by OPEN(3). It is suspendable
+ * meaning that the underlying file may be closed at any time unless the
+ * handle is marked as being in-use (see fs_handle_get_fd() and
+ * fs_handle_put_fd()).
+ *
+ * If the tracker opted to close the underlying file descriptor, it will
+ * be restored to its last known state when it is obtained through
+ * the fs_handle's fs_handle_get_fd() method.
+ *
+ * Note that a suspendable file descriptor can be closed by the fd tracker at
+ * anytime when it is not in use. This means that the user should not rely on it
+ * being safe to unlink the file. Moreover, concurent modifications to the file
+ * (e.g. truncation) may react differently than if the file descriptor was kept
+ * open.
+ */
+struct fs_handle *fd_tracker_open_fs_handle(struct fd_tracker *tracker,
+               struct lttng_directory_handle *directory,
+               const char *path,
+               int flags,
+               mode_t *mode);
+
+/*
+ * Open a tracked unsuspendable file descriptor.
+ *
+ * This function allows the fd tracker to keep track of unsuspendable
+ * file descriptors. A callback, open, is passed to allow the tracker
+ * to atomically reserve an entry for a given count of new file descriptors,
+ * suspending file descriptors as needed, and invoke the provided callback
+ * without ever exceeding the tracker's capacity.
+ *
+ * fd_count indicates the count of file descriptors that will be opened and
+ * returned by the open callback. The storage location at out_fds is assumed
+ * to be large enough to hold 'fd_count * sizeof(int)'.
+ *
+ * Names may be provided to allow easier debugging of file descriptor
+ * exhaustions.
+ *
+ * The callback's return value is returned to the user. Additionally, two
+ * negative tracker-specific codes may be returned:
+ *   - ENOMEM: allocation of a new entry failed,
+ *   - EMFILE: too many unsuspendable fds are opened and the tracker can't
+ *             accommodates the request for a new unsuspendable entry.
+ */
+int fd_tracker_open_unsuspendable_fd(struct fd_tracker *tracker,
+               int *out_fds,
+               const char **names,
+               unsigned int fd_count,
+               fd_open_cb open,
+               void *data);
+
+/*
+ * Close a tracked unsuspendable file descriptor.
+ *
+ * This function allows the fd tracker to keep track of unsuspendable
+ * file descriptors. A callback, close, is passed to allow the tracker
+ * to atomically release a file descriptor entry.
+ *
+ * Returns 0 if the close callback returned success. Returns the value returned
+ * by the close callback if it is negative. Additionally, a tracker-specific
+ * code may be returned:
+ *   - EINVAL: a file descriptor was unknown to the tracker
+ *
+ * Closed fds are set to -1 in the fds array which, in the event of an error,
+ * allows the user to know which file descriptors are no longer being tracked.
+ */
+int fd_tracker_close_unsuspendable_fd(struct fd_tracker *tracker,
+               int *fds,
+               unsigned int fd_count,
+               fd_close_cb close,
+               void *data);
+
+/*
+ * Log the contents of the fd_tracker.
+ */
+void fd_tracker_log(struct fd_tracker *tracker);
+
+#endif /* FD_TRACKER_H */
index 404ba360b2ab40f8ee3d4c35bfd93d4622651c6e..4790b8bf190721150baf7cd49ff435b6871ec904 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/optional.h>
-#include <common/string-utils/format.h>
-#include <common/utils.h>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <common/string-utils/format.hpp>
+#include <common/utils.hpp>
 #include <inttypes.h>
 #include <lttng/constant.h>
 #include <sys/stat.h>
@@ -21,7 +21,7 @@
 #include <urcu/rculfhash.h>
 #include <urcu/ref.h>
 
-#include "inode.h"
+#include "inode.hpp"
 
 struct inode_id {
        dev_t device;
diff --git a/src/common/fd-tracker/inode.h b/src/common/fd-tracker/inode.h
deleted file mode 100644 (file)
index 7e95c07..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef FD_TRACKER_INODE_H
-#define FD_TRACKER_INODE_H
-
-#include <common/compat/directory-handle.h>
-#include <stdbool.h>
-
-struct lttng_inode;
-struct lttng_inode_registry;
-struct lttng_unlinked_file_directory;
-struct lttng_directory_handle;
-
-/*
- * The unlinked file pool is protected by the fd-tracker's lock.
- *
- * NOTE: the unlinked file pool can use a single file desriptor when unlinked
- * files are present in the pool. This file descriptor is not accounted-for
- * by the fd-tracker. Users of the fd-tracker should account for this extra
- * file descriptor.
- */
-struct lttng_unlinked_file_pool *lttng_unlinked_file_pool_create(
-               const char *path);
-
-void lttng_unlinked_file_pool_destroy(
-               struct lttng_unlinked_file_pool *pool);
-
-/* The inode registry is protected by the fd-tracker's lock. */
-struct lttng_inode_registry *lttng_inode_registry_create(void);
-
-struct lttng_inode *lttng_inode_registry_get_inode(
-               struct lttng_inode_registry *registry,
-               struct lttng_directory_handle *handle,
-               const char *path,
-               int fd,
-               struct lttng_unlinked_file_pool *pool);
-
-void lttng_inode_registry_destroy(struct lttng_inode_registry *registry);
-
-void lttng_inode_borrow_location(struct lttng_inode *inode,
-               const struct lttng_directory_handle **out_directory_handle,
-               const char **out_path);
-
-/* Returns a new reference to the inode's location directory handle. */
-struct lttng_directory_handle *lttng_inode_get_location_directory_handle(
-               struct lttng_inode *inode);
-
-int lttng_inode_rename(struct lttng_inode *inode,
-               struct lttng_directory_handle *old_directory_handle,
-               const char *old_path,
-               struct lttng_directory_handle *new_directory_handle,
-               const char *new_path,
-               bool overwrite);
-
-int lttng_inode_unlink(struct lttng_inode *inode);
-
-void lttng_inode_put(struct lttng_inode *inode);
-
-#endif /* FD_TRACKER_INODE_H */
diff --git a/src/common/fd-tracker/inode.hpp b/src/common/fd-tracker/inode.hpp
new file mode 100644 (file)
index 0000000..d4cb282
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef FD_TRACKER_INODE_H
+#define FD_TRACKER_INODE_H
+
+#include <common/compat/directory-handle.hpp>
+#include <stdbool.h>
+
+struct lttng_inode;
+struct lttng_inode_registry;
+struct lttng_unlinked_file_directory;
+struct lttng_directory_handle;
+
+/*
+ * The unlinked file pool is protected by the fd-tracker's lock.
+ *
+ * NOTE: the unlinked file pool can use a single file desriptor when unlinked
+ * files are present in the pool. This file descriptor is not accounted-for
+ * by the fd-tracker. Users of the fd-tracker should account for this extra
+ * file descriptor.
+ */
+struct lttng_unlinked_file_pool *lttng_unlinked_file_pool_create(
+               const char *path);
+
+void lttng_unlinked_file_pool_destroy(
+               struct lttng_unlinked_file_pool *pool);
+
+/* The inode registry is protected by the fd-tracker's lock. */
+struct lttng_inode_registry *lttng_inode_registry_create(void);
+
+struct lttng_inode *lttng_inode_registry_get_inode(
+               struct lttng_inode_registry *registry,
+               struct lttng_directory_handle *handle,
+               const char *path,
+               int fd,
+               struct lttng_unlinked_file_pool *pool);
+
+void lttng_inode_registry_destroy(struct lttng_inode_registry *registry);
+
+void lttng_inode_borrow_location(struct lttng_inode *inode,
+               const struct lttng_directory_handle **out_directory_handle,
+               const char **out_path);
+
+/* Returns a new reference to the inode's location directory handle. */
+struct lttng_directory_handle *lttng_inode_get_location_directory_handle(
+               struct lttng_inode *inode);
+
+int lttng_inode_rename(struct lttng_inode *inode,
+               struct lttng_directory_handle *old_directory_handle,
+               const char *old_path,
+               struct lttng_directory_handle *new_directory_handle,
+               const char *new_path,
+               bool overwrite);
+
+int lttng_inode_unlink(struct lttng_inode *inode);
+
+void lttng_inode_put(struct lttng_inode *inode);
+
+#endif /* FD_TRACKER_INODE_H */
index 4949d8160f104bad611ed35f928a76fbb9141194..d9066807182fb35c664745b099756c6179a75a13 100644 (file)
@@ -5,9 +5,9 @@
  *
  */
 
-#include <common/compat/poll.h>
+#include <common/compat/poll.hpp>
 
-#include "utils.h"
+#include "utils.hpp"
 
 #if HAVE_EPOLL
 
index be6c65df6aed6e0c836ca7d075342618a46a5687..62c4deef263a50180a95c3070db8ca113af11533 100644 (file)
@@ -5,9 +5,9 @@
  *
  */
 
-#include <common/error.h>
-#include <common/fd-tracker/utils.h>
-#include <common/utils.h>
+#include <common/error.hpp>
+#include <common/fd-tracker/utils.hpp>
+#include <common/utils.hpp>
 #include <lttng/constant.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/src/common/fd-tracker/utils.h b/src/common/fd-tracker/utils.h
deleted file mode 100644 (file)
index 829b56b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef FD_TRACKER_UTILS_H
-#define FD_TRACKER_UTILS_H
-
-#include <common/compat/directory-handle.h>
-#include <common/fd-tracker/fd-tracker.h>
-#include <common/macros.h>
-
-struct lttng_poll_event;
-
-/*
- * Utility implementing a close_fd callback which receives one file descriptor
- * and closes it, returning close()'s return value.
- */
-int fd_tracker_util_close_fd(void *, int *fd);
-
-/*
- * Create a pipe and track its underlying fds.
- */
-int fd_tracker_util_pipe_open_cloexec(
-               struct fd_tracker *tracker, const char *name, int *pipe);
-int fd_tracker_util_pipe_close(struct fd_tracker *tracker, int *pipe);
-
-/*
- * Create a poll event and track its underlying fd, if applicable.
- */
-int fd_tracker_util_poll_create(struct fd_tracker *tracker,
-               const char *name,
-               struct lttng_poll_event *events,
-               int size,
-               int flags);
-int fd_tracker_util_poll_clean(
-               struct fd_tracker *tracker, struct lttng_poll_event *events);
-
-struct lttng_directory_handle *fd_tracker_create_directory_handle(
-               struct fd_tracker *tracker, const char *path);
-
-struct lttng_directory_handle *fd_tracker_create_directory_handle_from_handle(
-               struct fd_tracker *tracker,
-               struct lttng_directory_handle *handle,
-               const char *path);
-
-#endif /* FD_TRACKER_UTILS_H */
diff --git a/src/common/fd-tracker/utils.hpp b/src/common/fd-tracker/utils.hpp
new file mode 100644 (file)
index 0000000..0507c39
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef FD_TRACKER_UTILS_H
+#define FD_TRACKER_UTILS_H
+
+#include <common/compat/directory-handle.hpp>
+#include <common/fd-tracker/fd-tracker.hpp>
+#include <common/macros.hpp>
+
+struct lttng_poll_event;
+
+/*
+ * Utility implementing a close_fd callback which receives one file descriptor
+ * and closes it, returning close()'s return value.
+ */
+int fd_tracker_util_close_fd(void *, int *fd);
+
+/*
+ * Create a pipe and track its underlying fds.
+ */
+int fd_tracker_util_pipe_open_cloexec(
+               struct fd_tracker *tracker, const char *name, int *pipe);
+int fd_tracker_util_pipe_close(struct fd_tracker *tracker, int *pipe);
+
+/*
+ * Create a poll event and track its underlying fd, if applicable.
+ */
+int fd_tracker_util_poll_create(struct fd_tracker *tracker,
+               const char *name,
+               struct lttng_poll_event *events,
+               int size,
+               int flags);
+int fd_tracker_util_poll_clean(
+               struct fd_tracker *tracker, struct lttng_poll_event *events);
+
+struct lttng_directory_handle *fd_tracker_create_directory_handle(
+               struct fd_tracker *tracker, const char *path);
+
+struct lttng_directory_handle *fd_tracker_create_directory_handle_from_handle(
+               struct fd_tracker *tracker,
+               struct lttng_directory_handle *handle,
+               const char *path);
+
+#endif /* FD_TRACKER_UTILS_H */
index 75eb2c6ca38b30f243673cd9cbac0a214e79e559..5b8082fd48da905e3f95280201dfa682668e444e 100644 (file)
@@ -15,9 +15,9 @@
 #include <stdlib.h>
 #include <inttypes.h>
 
-#include <common/compat/errno.h>
-#include <common/bytecode/bytecode.h>
-#include <common/filter/filter-ast.h>
+#include <common/compat/errno.hpp>
+#include <common/bytecode/bytecode.hpp>
+#include <common/filter/filter-ast.hpp>
 #include <common/filter/filter-parser.hpp>
 
 /* For error.h */
index f74b6374bcea3dcbb4b1405361917a334e23591b..2bff02031f2b97d5220bf034af286f2e3e386682 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include "filter.h"
+#include "filter.hpp"
 #include <stddef.h>
 
 struct bytecode_symbol_iterator {
diff --git a/src/common/filter.h b/src/common/filter.h
deleted file mode 100644 (file)
index 305434b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_COMMON_FILTER_H
-#define LTTNG_COMMON_FILTER_H
-
-#include <common/sessiond-comm/sessiond-comm.h>
-
-struct bytecode_symbol_iterator;
-
-/*
- * Create an iterator on a bytecode's symbols. The iterator points to the
- * first element after creation.
- */
-struct bytecode_symbol_iterator *bytecode_symbol_iterator_create(
-               struct lttng_bytecode *bytecode);
-
-/*
- * Advance iterator of one element.
- *
- * Returns 0 if a next element exists or a negative value at the end.
- */
-int bytecode_symbol_iterator_next(struct bytecode_symbol_iterator *it);
-
-int bytecode_symbol_iterator_get_type(struct bytecode_symbol_iterator *it);
-
-const char *bytecode_symbol_iterator_get_name(
-               struct bytecode_symbol_iterator *it);
-
-void bytecode_symbol_iterator_destroy(struct bytecode_symbol_iterator *it);
-
-#endif /* LTTNG_COMMON_FILTER_H */
diff --git a/src/common/filter.hpp b/src/common/filter.hpp
new file mode 100644 (file)
index 0000000..085d6d0
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_COMMON_FILTER_H
+#define LTTNG_COMMON_FILTER_H
+
+#include <common/sessiond-comm/sessiond-comm.hpp>
+
+struct bytecode_symbol_iterator;
+
+/*
+ * Create an iterator on a bytecode's symbols. The iterator points to the
+ * first element after creation.
+ */
+struct bytecode_symbol_iterator *bytecode_symbol_iterator_create(
+               struct lttng_bytecode *bytecode);
+
+/*
+ * Advance iterator of one element.
+ *
+ * Returns 0 if a next element exists or a negative value at the end.
+ */
+int bytecode_symbol_iterator_next(struct bytecode_symbol_iterator *it);
+
+int bytecode_symbol_iterator_get_type(struct bytecode_symbol_iterator *it);
+
+const char *bytecode_symbol_iterator_get_name(
+               struct bytecode_symbol_iterator *it);
+
+void bytecode_symbol_iterator_destroy(struct bytecode_symbol_iterator *it);
+
+#endif /* LTTNG_COMMON_FILTER_H */
diff --git a/src/common/filter/Makefile.am b/src/common/filter/Makefile.am
deleted file mode 100644 (file)
index 4a6e4ff..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-AM_CPPFLAGS += -I$(srcdir) -I$(builddir)
-
-noinst_LTLIBRARIES = libfilter.la
-noinst_HEADERS = filter-ast.h \
-               filter-symbols.h
-
-BUILT_SOURCES = filter-parser.hpp
-
-libfilter_la_SOURCES = \
-       filter-lexer.lpp \
-       filter-parser.ypp \
-       filter-visitor-xml.cpp \
-       filter-visitor-generate-ir.cpp \
-       filter-visitor-ir-check-binary-op-nesting.cpp \
-       filter-visitor-ir-validate-string.cpp \
-       filter-visitor-ir-validate-globbing.cpp \
-       filter-visitor-ir-normalize-glob-patterns.cpp \
-       filter-visitor-generate-bytecode.cpp \
-       filter-ast.h \
-       filter-ir.h \
-       memstream.h
-libfilter_la_CXXFLAGS = -include filter-symbols.h $(AM_CXXFLAGS)
-libfilter_la_LIBADD = $(top_builddir)/src/common/string-utils/libstring-utils.la
-
-AM_YFLAGS = -t -d -v -Wno-yacc
-
-# start with empty files to clean
-CLEANFILES =
-
-if HAVE_BISON
-# we have bison: we can clean the generated parser files
-CLEANFILES += filter-parser.cpp filter-parser.hpp filter-parser.output
-else # HAVE_BISON
-# create target used to stop the build if we want to build the parser,
-# but we don't have the necessary tool to do so
-ERR_MSG = "Error: Cannot build target because bison is missing."
-ERR_MSG += "Make sure bison is installed and run the configure script again."
-
-filter-parser.cpp filter-parser.hpp: filter-parser.ypp
-       @echo $(ERR_MSG)
-       @false
-
-all-local: filter-parser.cpp filter-parser.hpp
-endif # HAVE_BISON
-
-if HAVE_FLEX
-# we have flex: we can clean the generated lexer files
-CLEANFILES += filter-lexer.cpp
-else # HAVE_FLEX
-# create target used to stop the build if we want to build the lexer,
-# but we don't have the necessary tool to do so
-ERR_MSG = "Error: Cannot build target because flex is missing."
-ERR_MSG += "Make sure flex is installed and run the configure script again."
-
-filter-lexer.cpp: filter-lexer.lpp
-       @echo $(ERR_MSG)
-       @false
-
-all-local: filter-lexer.cpp
-endif # HAVE_FLEX
diff --git a/src/common/filter/filter-ast.h b/src/common/filter/filter-ast.h
deleted file mode 100644 (file)
index 2b460b4..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-#ifndef _FILTER_AST_H
-#define _FILTER_AST_H
-
-/*
- * filter-ast.h
- *
- * LTTng filter AST
- *
- * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-/*
- * Note: filter-ast.h should be included before filter-parser.h.
- */
-
-#include <urcu/list.h>
-#include <stdio.h>
-#include <stdint.h>
-
-#define printf_debug(fmt, args...)                                     \
-       do {                                                            \
-               if (filter_parser_debug)                                \
-                       fprintf(stdout, "[debug] " fmt, ## args);       \
-       } while (0)
-
-// the parameter name (of the reentrant 'yyparse' function)
-// data is a pointer to a 'SParserParam' structure
-//#define YYPARSE_PARAM        parser_ctx
-
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-extern int filter_parser_debug;
-
-struct filter_node;
-struct filter_parser;
-
-enum node_type {
-       NODE_UNKNOWN = 0,
-       NODE_ROOT,
-
-       NODE_EXPRESSION,
-       NODE_OP,
-       NODE_UNARY_OP,
-
-       NR_NODE_TYPES,
-};
-
-enum op_type {
-       AST_OP_UNKNOWN = 0,
-       AST_OP_MUL,
-       AST_OP_DIV,
-       AST_OP_MOD,
-       AST_OP_PLUS,
-       AST_OP_MINUS,
-       AST_OP_BIT_RSHIFT,
-       AST_OP_BIT_LSHIFT,
-       AST_OP_AND,
-       AST_OP_OR,
-       AST_OP_BIT_AND,
-       AST_OP_BIT_OR,
-       AST_OP_BIT_XOR,
-
-       AST_OP_EQ,
-       AST_OP_NE,
-       AST_OP_GT,
-       AST_OP_LT,
-       AST_OP_GE,
-       AST_OP_LE,
-};
-
-enum unary_op_type {
-       AST_UNARY_UNKNOWN = 0,
-       AST_UNARY_PLUS,
-       AST_UNARY_MINUS,
-       AST_UNARY_NOT,
-       AST_UNARY_BIT_NOT,
-};
-
-enum ast_link_type {
-       AST_LINK_UNKNOWN = 0,
-       AST_LINK_DOT,
-       AST_LINK_RARROW,
-       AST_LINK_BRACKET,
-};
-
-enum ast_expt_type {
-       AST_EXP_UNKNOWN = 0,
-       AST_EXP_STRING,
-       AST_EXP_CONSTANT,
-       AST_EXP_FLOAT_CONSTANT,
-       AST_EXP_IDENTIFIER,
-       AST_EXP_GLOBAL_IDENTIFIER,
-       AST_EXP_NESTED,
-};
-
-struct filter_node {
-       /*
-        * Parent node is only set on demand by specific visitor.
-        */
-       struct filter_node *parent;
-       struct cds_list_head gc;
-
-       enum node_type type;
-       union {
-               struct {
-                       /* Avoid -Wextern-c-compat warning with clang++. */
-                       char unused;
-               } unknown;
-               struct {
-                       struct filter_node *child;
-               } root;
-               struct {
-                       enum ast_expt_type type;
-                       enum ast_link_type post_op;     /* reverse */
-                       enum ast_link_type pre_op;      /* forward */
-                       union {
-                               const char *string;
-                               uint64_t constant;
-                               double float_constant;
-                               const char *identifier;
-                               /*
-                                * child can be nested.
-                                */
-                               struct filter_node *child;
-                       } u;
-                       /* prev: backward dot/arrow chain (postfix expression) */
-                       struct filter_node *prev;
-                       /* next: forward dot/arrow chain, generated by a visitor. */
-                       struct filter_node *next;
-                       /* next_bracket: linked bracket chain (prefix expression) */
-                       struct filter_node *next_bracket;
-               } expression;
-               struct {
-                       enum op_type type;
-                       struct filter_node *lchild;
-                       struct filter_node *rchild;
-               } op;
-               struct {
-                       enum unary_op_type type;
-                       struct filter_node *child;
-               } unary_op;
-       } u;
-};
-
-struct filter_ast {
-       struct filter_node root;
-       struct cds_list_head allocated_nodes;
-};
-
-const char *node_type(struct filter_node *node);
-
-struct ir_op;
-
-struct filter_parser_ctx {
-       yyscan_t scanner;
-       struct filter_ast *ast;
-       struct cds_list_head allocated_strings;
-       struct ir_op *ir_root;
-       struct lttng_bytecode_alloc *bytecode;
-       struct lttng_bytecode_alloc *bytecode_reloc;
-};
-
-struct filter_parser_ctx *filter_parser_ctx_alloc(FILE *input);
-void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx);
-int filter_parser_ctx_append_ast(struct filter_parser_ctx *parser_ctx);
-int filter_parser_ctx_create_from_filter_expression(
-               const char *filter_expression, struct filter_parser_ctx **ctxp);
-
-static inline
-struct filter_ast *filter_parser_get_ast(struct filter_parser_ctx *parser_ctx)
-{
-       return parser_ctx->ast;
-}
-
-int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream,
-                       int indent);
-int filter_visitor_ir_generate(struct filter_parser_ctx *ctx);
-void filter_ir_free(struct filter_parser_ctx *ctx);
-int filter_visitor_bytecode_generate(struct filter_parser_ctx *ctx);
-void filter_bytecode_free(struct filter_parser_ctx *ctx);
-int filter_visitor_ir_check_binary_op_nesting(struct filter_parser_ctx *ctx);
-int filter_visitor_ir_check_binary_comparator(struct filter_parser_ctx *ctx);
-int filter_visitor_ir_validate_string(struct filter_parser_ctx *ctx);
-int filter_visitor_ir_normalize_glob_patterns(struct filter_parser_ctx *ctx);
-int filter_visitor_ir_validate_globbing(struct filter_parser_ctx *ctx);
-
-#endif /* _FILTER_AST_H */
diff --git a/src/common/filter/filter-ast.hpp b/src/common/filter/filter-ast.hpp
new file mode 100644 (file)
index 0000000..2b460b4
--- /dev/null
@@ -0,0 +1,193 @@
+#ifndef _FILTER_AST_H
+#define _FILTER_AST_H
+
+/*
+ * filter-ast.h
+ *
+ * LTTng filter AST
+ *
+ * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+/*
+ * Note: filter-ast.h should be included before filter-parser.h.
+ */
+
+#include <urcu/list.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#define printf_debug(fmt, args...)                                     \
+       do {                                                            \
+               if (filter_parser_debug)                                \
+                       fprintf(stdout, "[debug] " fmt, ## args);       \
+       } while (0)
+
+// the parameter name (of the reentrant 'yyparse' function)
+// data is a pointer to a 'SParserParam' structure
+//#define YYPARSE_PARAM        parser_ctx
+
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+extern int filter_parser_debug;
+
+struct filter_node;
+struct filter_parser;
+
+enum node_type {
+       NODE_UNKNOWN = 0,
+       NODE_ROOT,
+
+       NODE_EXPRESSION,
+       NODE_OP,
+       NODE_UNARY_OP,
+
+       NR_NODE_TYPES,
+};
+
+enum op_type {
+       AST_OP_UNKNOWN = 0,
+       AST_OP_MUL,
+       AST_OP_DIV,
+       AST_OP_MOD,
+       AST_OP_PLUS,
+       AST_OP_MINUS,
+       AST_OP_BIT_RSHIFT,
+       AST_OP_BIT_LSHIFT,
+       AST_OP_AND,
+       AST_OP_OR,
+       AST_OP_BIT_AND,
+       AST_OP_BIT_OR,
+       AST_OP_BIT_XOR,
+
+       AST_OP_EQ,
+       AST_OP_NE,
+       AST_OP_GT,
+       AST_OP_LT,
+       AST_OP_GE,
+       AST_OP_LE,
+};
+
+enum unary_op_type {
+       AST_UNARY_UNKNOWN = 0,
+       AST_UNARY_PLUS,
+       AST_UNARY_MINUS,
+       AST_UNARY_NOT,
+       AST_UNARY_BIT_NOT,
+};
+
+enum ast_link_type {
+       AST_LINK_UNKNOWN = 0,
+       AST_LINK_DOT,
+       AST_LINK_RARROW,
+       AST_LINK_BRACKET,
+};
+
+enum ast_expt_type {
+       AST_EXP_UNKNOWN = 0,
+       AST_EXP_STRING,
+       AST_EXP_CONSTANT,
+       AST_EXP_FLOAT_CONSTANT,
+       AST_EXP_IDENTIFIER,
+       AST_EXP_GLOBAL_IDENTIFIER,
+       AST_EXP_NESTED,
+};
+
+struct filter_node {
+       /*
+        * Parent node is only set on demand by specific visitor.
+        */
+       struct filter_node *parent;
+       struct cds_list_head gc;
+
+       enum node_type type;
+       union {
+               struct {
+                       /* Avoid -Wextern-c-compat warning with clang++. */
+                       char unused;
+               } unknown;
+               struct {
+                       struct filter_node *child;
+               } root;
+               struct {
+                       enum ast_expt_type type;
+                       enum ast_link_type post_op;     /* reverse */
+                       enum ast_link_type pre_op;      /* forward */
+                       union {
+                               const char *string;
+                               uint64_t constant;
+                               double float_constant;
+                               const char *identifier;
+                               /*
+                                * child can be nested.
+                                */
+                               struct filter_node *child;
+                       } u;
+                       /* prev: backward dot/arrow chain (postfix expression) */
+                       struct filter_node *prev;
+                       /* next: forward dot/arrow chain, generated by a visitor. */
+                       struct filter_node *next;
+                       /* next_bracket: linked bracket chain (prefix expression) */
+                       struct filter_node *next_bracket;
+               } expression;
+               struct {
+                       enum op_type type;
+                       struct filter_node *lchild;
+                       struct filter_node *rchild;
+               } op;
+               struct {
+                       enum unary_op_type type;
+                       struct filter_node *child;
+               } unary_op;
+       } u;
+};
+
+struct filter_ast {
+       struct filter_node root;
+       struct cds_list_head allocated_nodes;
+};
+
+const char *node_type(struct filter_node *node);
+
+struct ir_op;
+
+struct filter_parser_ctx {
+       yyscan_t scanner;
+       struct filter_ast *ast;
+       struct cds_list_head allocated_strings;
+       struct ir_op *ir_root;
+       struct lttng_bytecode_alloc *bytecode;
+       struct lttng_bytecode_alloc *bytecode_reloc;
+};
+
+struct filter_parser_ctx *filter_parser_ctx_alloc(FILE *input);
+void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx);
+int filter_parser_ctx_append_ast(struct filter_parser_ctx *parser_ctx);
+int filter_parser_ctx_create_from_filter_expression(
+               const char *filter_expression, struct filter_parser_ctx **ctxp);
+
+static inline
+struct filter_ast *filter_parser_get_ast(struct filter_parser_ctx *parser_ctx)
+{
+       return parser_ctx->ast;
+}
+
+int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream,
+                       int indent);
+int filter_visitor_ir_generate(struct filter_parser_ctx *ctx);
+void filter_ir_free(struct filter_parser_ctx *ctx);
+int filter_visitor_bytecode_generate(struct filter_parser_ctx *ctx);
+void filter_bytecode_free(struct filter_parser_ctx *ctx);
+int filter_visitor_ir_check_binary_op_nesting(struct filter_parser_ctx *ctx);
+int filter_visitor_ir_check_binary_comparator(struct filter_parser_ctx *ctx);
+int filter_visitor_ir_validate_string(struct filter_parser_ctx *ctx);
+int filter_visitor_ir_normalize_glob_patterns(struct filter_parser_ctx *ctx);
+int filter_visitor_ir_validate_globbing(struct filter_parser_ctx *ctx);
+
+#endif /* _FILTER_AST_H */
diff --git a/src/common/filter/filter-ir.h b/src/common/filter/filter-ir.h
deleted file mode 100644 (file)
index 5775e80..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-#ifndef _FILTER_IR_H
-#define _FILTER_IR_H
-
-/*
- * filter-ir.h
- *
- * LTTng filter ir
- *
- * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include "filter-ast.h"
-
-enum ir_op_signedness {
-       IR_SIGN_UNKNOWN = 0,
-       IR_SIGNED,
-       IR_UNSIGNED,
-       IR_SIGN_DYN,            /* signedness determined dynamically */
-};
-
-enum ir_data_type {
-       IR_DATA_UNKNOWN = 0,
-       IR_DATA_STRING,
-       IR_DATA_NUMERIC,        /* numeric and boolean */
-       IR_DATA_FLOAT,
-       IR_DATA_FIELD_REF,
-       IR_DATA_GET_CONTEXT_REF,
-       IR_DATA_EXPRESSION,
-};
-
-static inline
-const char *ir_data_type_str(enum ir_data_type type)
-{
-       switch (type) {
-       case IR_DATA_UNKNOWN:
-               return "IR_DATA_UNKNOWN";
-       case IR_DATA_STRING:
-               return "IR_DATA_STRING";
-       case IR_DATA_NUMERIC:
-               return "IR_DATA_NUMERIC";
-       case IR_DATA_FLOAT:
-               return "IR_DATA_FLOAT";
-       case IR_DATA_FIELD_REF:
-               return "IR_DATA_FIELD_REF";
-       case IR_DATA_GET_CONTEXT_REF:
-               return "IR_DATA_GET_CONTEXT_REF";
-       case IR_DATA_EXPRESSION:
-               return "IR_DATA_EXPRESSION";
-       default:
-               abort();
-       }
-}
-
-enum ir_op_type {
-       IR_OP_UNKNOWN = 0,
-       IR_OP_ROOT,
-       IR_OP_LOAD,
-       IR_OP_UNARY,
-       IR_OP_BINARY,
-       IR_OP_LOGICAL,
-};
-
-static inline
-const char *ir_op_type_str(enum ir_op_type type)
-{
-       switch (type) {
-       case IR_OP_UNKNOWN:
-               return "IR_OP_UNKNOWN";
-       case IR_OP_ROOT:
-               return "IR_OP_ROOT";
-       case IR_OP_LOAD:
-               return "IR_OP_LOAD";
-       case IR_OP_UNARY:
-               return "IR_OP_UNARY";
-       case IR_OP_BINARY:
-               return "IR_OP_BINARY";
-       case IR_OP_LOGICAL:
-               return "IR_OP_LOGICAL";
-       default:
-               abort();
-       }
-}
-
-/* left or right child */
-enum ir_side {
-       IR_SIDE_UNKNOWN = 0,
-       IR_LEFT,
-       IR_RIGHT,
-};
-
-enum ir_load_string_type {
-       /* Plain, no globbing at all: `hello world`. */
-       IR_LOAD_STRING_TYPE_PLAIN = 0,
-
-       /* Star at the end only: `hello *`. */
-       IR_LOAD_STRING_TYPE_GLOB_STAR_END,
-
-       /* At least one star, anywhere, but not at the end only: `he*wor*`. */
-       IR_LOAD_STRING_TYPE_GLOB_STAR,
-};
-
-struct ir_op_root {
-       struct ir_op *child;
-};
-
-enum ir_load_expression_type {
-       IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT,
-       IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT,
-       IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT,
-       IR_LOAD_EXPRESSION_GET_SYMBOL,
-       IR_LOAD_EXPRESSION_GET_INDEX,
-       IR_LOAD_EXPRESSION_LOAD_FIELD,
-};
-
-static inline
-const char *ir_load_expression_type_str(enum ir_load_expression_type type)
-{
-       switch (type) {
-       case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
-               return "IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT";
-       case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
-               return "IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT";
-       case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
-               return "IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT";
-       case IR_LOAD_EXPRESSION_GET_SYMBOL:
-               return "IR_LOAD_EXPRESSION_GET_SYMBOL";
-       case IR_LOAD_EXPRESSION_GET_INDEX:
-               return "IR_LOAD_EXPRESSION_GET_INDEX";
-       case IR_LOAD_EXPRESSION_LOAD_FIELD:
-               return "IR_LOAD_EXPRESSION_LOAD_FIELD";
-       default:
-               abort();
-       }
-}
-
-struct ir_load_expression_op {
-       struct ir_load_expression_op *next;
-       enum ir_load_expression_type type;
-       union {
-               char *symbol;
-               uint64_t index;
-       } u;
-};
-
-struct ir_load_expression {
-       struct ir_load_expression_op *child;
-};
-
-struct ir_op_load {
-       union {
-               struct {
-                       enum ir_load_string_type type;
-                       char *value;
-               } string;
-               int64_t num;
-               double flt;
-               char *ref;
-               struct ir_load_expression *expression;
-       } u;
-};
-
-struct ir_op_unary {
-       enum unary_op_type type;
-       struct ir_op *child;
-};
-
-struct ir_op_binary {
-       enum op_type type;
-       struct ir_op *left;
-       struct ir_op *right;
-};
-
-struct ir_op_logical {
-       enum op_type type;
-       struct ir_op *left;
-       struct ir_op *right;
-};
-
-struct ir_op {
-       /* common to all ops */
-       enum ir_op_type op;
-       enum ir_data_type data_type;
-       enum ir_op_signedness signedness;
-       enum ir_side side;
-
-       union {
-               struct ir_op_root root;
-               struct ir_op_load load;
-               struct ir_op_unary unary;
-               struct ir_op_binary binary;
-               struct ir_op_logical logical;
-       } u;
-};
-
-#endif /* _FILTER_IR_H */
diff --git a/src/common/filter/filter-ir.hpp b/src/common/filter/filter-ir.hpp
new file mode 100644 (file)
index 0000000..068d3aa
--- /dev/null
@@ -0,0 +1,198 @@
+#ifndef _FILTER_IR_H
+#define _FILTER_IR_H
+
+/*
+ * filter-ir.h
+ *
+ * LTTng filter ir
+ *
+ * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include "filter-ast.hpp"
+
+enum ir_op_signedness {
+       IR_SIGN_UNKNOWN = 0,
+       IR_SIGNED,
+       IR_UNSIGNED,
+       IR_SIGN_DYN,            /* signedness determined dynamically */
+};
+
+enum ir_data_type {
+       IR_DATA_UNKNOWN = 0,
+       IR_DATA_STRING,
+       IR_DATA_NUMERIC,        /* numeric and boolean */
+       IR_DATA_FLOAT,
+       IR_DATA_FIELD_REF,
+       IR_DATA_GET_CONTEXT_REF,
+       IR_DATA_EXPRESSION,
+};
+
+static inline
+const char *ir_data_type_str(enum ir_data_type type)
+{
+       switch (type) {
+       case IR_DATA_UNKNOWN:
+               return "IR_DATA_UNKNOWN";
+       case IR_DATA_STRING:
+               return "IR_DATA_STRING";
+       case IR_DATA_NUMERIC:
+               return "IR_DATA_NUMERIC";
+       case IR_DATA_FLOAT:
+               return "IR_DATA_FLOAT";
+       case IR_DATA_FIELD_REF:
+               return "IR_DATA_FIELD_REF";
+       case IR_DATA_GET_CONTEXT_REF:
+               return "IR_DATA_GET_CONTEXT_REF";
+       case IR_DATA_EXPRESSION:
+               return "IR_DATA_EXPRESSION";
+       default:
+               abort();
+       }
+}
+
+enum ir_op_type {
+       IR_OP_UNKNOWN = 0,
+       IR_OP_ROOT,
+       IR_OP_LOAD,
+       IR_OP_UNARY,
+       IR_OP_BINARY,
+       IR_OP_LOGICAL,
+};
+
+static inline
+const char *ir_op_type_str(enum ir_op_type type)
+{
+       switch (type) {
+       case IR_OP_UNKNOWN:
+               return "IR_OP_UNKNOWN";
+       case IR_OP_ROOT:
+               return "IR_OP_ROOT";
+       case IR_OP_LOAD:
+               return "IR_OP_LOAD";
+       case IR_OP_UNARY:
+               return "IR_OP_UNARY";
+       case IR_OP_BINARY:
+               return "IR_OP_BINARY";
+       case IR_OP_LOGICAL:
+               return "IR_OP_LOGICAL";
+       default:
+               abort();
+       }
+}
+
+/* left or right child */
+enum ir_side {
+       IR_SIDE_UNKNOWN = 0,
+       IR_LEFT,
+       IR_RIGHT,
+};
+
+enum ir_load_string_type {
+       /* Plain, no globbing at all: `hello world`. */
+       IR_LOAD_STRING_TYPE_PLAIN = 0,
+
+       /* Star at the end only: `hello *`. */
+       IR_LOAD_STRING_TYPE_GLOB_STAR_END,
+
+       /* At least one star, anywhere, but not at the end only: `he*wor*`. */
+       IR_LOAD_STRING_TYPE_GLOB_STAR,
+};
+
+struct ir_op_root {
+       struct ir_op *child;
+};
+
+enum ir_load_expression_type {
+       IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT,
+       IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT,
+       IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT,
+       IR_LOAD_EXPRESSION_GET_SYMBOL,
+       IR_LOAD_EXPRESSION_GET_INDEX,
+       IR_LOAD_EXPRESSION_LOAD_FIELD,
+};
+
+static inline
+const char *ir_load_expression_type_str(enum ir_load_expression_type type)
+{
+       switch (type) {
+       case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
+               return "IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT";
+       case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
+               return "IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT";
+       case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
+               return "IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT";
+       case IR_LOAD_EXPRESSION_GET_SYMBOL:
+               return "IR_LOAD_EXPRESSION_GET_SYMBOL";
+       case IR_LOAD_EXPRESSION_GET_INDEX:
+               return "IR_LOAD_EXPRESSION_GET_INDEX";
+       case IR_LOAD_EXPRESSION_LOAD_FIELD:
+               return "IR_LOAD_EXPRESSION_LOAD_FIELD";
+       default:
+               abort();
+       }
+}
+
+struct ir_load_expression_op {
+       struct ir_load_expression_op *next;
+       enum ir_load_expression_type type;
+       union {
+               char *symbol;
+               uint64_t index;
+       } u;
+};
+
+struct ir_load_expression {
+       struct ir_load_expression_op *child;
+};
+
+struct ir_op_load {
+       union {
+               struct {
+                       enum ir_load_string_type type;
+                       char *value;
+               } string;
+               int64_t num;
+               double flt;
+               char *ref;
+               struct ir_load_expression *expression;
+       } u;
+};
+
+struct ir_op_unary {
+       enum unary_op_type type;
+       struct ir_op *child;
+};
+
+struct ir_op_binary {
+       enum op_type type;
+       struct ir_op *left;
+       struct ir_op *right;
+};
+
+struct ir_op_logical {
+       enum op_type type;
+       struct ir_op *left;
+       struct ir_op *right;
+};
+
+struct ir_op {
+       /* common to all ops */
+       enum ir_op_type op;
+       enum ir_data_type data_type;
+       enum ir_op_signedness signedness;
+       enum ir_side side;
+
+       union {
+               struct ir_op_root root;
+               struct ir_op_load load;
+               struct ir_op_unary unary;
+               struct ir_op_binary binary;
+               struct ir_op_logical logical;
+       } u;
+};
+
+#endif /* _FILTER_IR_H */
index acd4c0be82eb33ae550b21b376538b636cecb26c..12164af0174306ad716b5231767e6a82df1217b7 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #include <stdio.h>
-#include "filter-ast.h"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
 #include <lttng/lttng-export.h>
 %}
index d654ecc84ab7ac539925d4973d50027172d1ece8..89f6b43d911f7de5a17db2dd25dadfb2aaf74262 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <inttypes.h>
-#include "common/bytecode/bytecode.h"
-#include "filter-ast.h"
+#include "common/bytecode/bytecode.hpp"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
-#include "memstream.h"
+#include "memstream.hpp"
 
-#include <common/compat/errno.h>
-#include <common/macros.h>
+#include <common/compat/errno.hpp>
+#include <common/macros.hpp>
 
 #define WIDTH_u64_SCANF_IS_A_BROKEN_API        "20"
 #define WIDTH_o64_SCANF_IS_A_BROKEN_API        "22"
@@ -428,7 +428,7 @@ error:
 
 %code provides
 {
-#include "common/macros.h"
+#include "common/macros.hpp"
 
 void setstring(struct filter_parser_ctx *parser_ctx, YYSTYPE *lvalp, const char *src);
 }
diff --git a/src/common/filter/filter-symbols.h b/src/common/filter/filter-symbols.h
deleted file mode 100644 (file)
index 27aaada..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef _FILTER_SYMBOLS_H
-#define _FILTER_SYMBOLS_H
-
-/*
- * filter-symbols.h
- *
- * LTTng filter flex/bison symbol prefixes
- *
- * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define yy_create_buffer lttng_filter_yy_create_buffer
-#define yy_delete_buffer lttng_filter_yy_delete_buffer
-#define yy_flush_buffer lttng_filter_yy_flush_buffer
-#define yy_scan_buffer lttng_filter_yy_scan_buffer
-#define yy_scan_bytes lttng_filter_yy_scan_bytes
-#define yy_scan_string lttng_filter_yy_scan_string
-#define yy_switch_to_buffer lttng_filter_yy_switch_to_buffer
-#define yyalloc lttng_filter_yyalloc
-#define yyfree lttng_filter_yyfree
-#define yyget_column lttng_filter_yyget_column
-#define yyget_debug lttng_filter_yyget_debug
-#define yyget_extra lttng_filter_yyget_extra
-#define yyget_in lttng_filter_yyget_in
-#define yyget_leng lttng_filter_yyget_leng
-#define yyget_lineno lttng_filter_yyget_lineno
-#define yyget_lval lttng_filter_yyget_lval
-#define yyget_out lttng_filter_yyget_out
-#define yyget_text lttng_filter_yyget_text
-#define yylex_init lttng_filter_yylex_init
-#define yypop_buffer_state lttng_filter_yypop_buffer_state
-#define yypush_buffer_state lttng_filter_yypush_buffer_state
-#define yyrealloc lttng_filter_yyrealloc
-#define yyset_column lttng_filter_yyset_column
-#define yyset_debug lttng_filter_yyset_debug
-#define yyset_extra lttng_filter_yyset_extra
-#define yyset_in lttng_filter_yyset_in
-#define yyset_lineno lttng_filter_yyset_lineno
-#define yyset_lval lttng_filter_yyset_lval
-#define yyset_out lttng_filter_yyset_out
-
-#endif /* _FILTER_SYMBOLS_H */
diff --git a/src/common/filter/filter-symbols.hpp b/src/common/filter/filter-symbols.hpp
new file mode 100644 (file)
index 0000000..27aaada
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _FILTER_SYMBOLS_H
+#define _FILTER_SYMBOLS_H
+
+/*
+ * filter-symbols.h
+ *
+ * LTTng filter flex/bison symbol prefixes
+ *
+ * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define yy_create_buffer lttng_filter_yy_create_buffer
+#define yy_delete_buffer lttng_filter_yy_delete_buffer
+#define yy_flush_buffer lttng_filter_yy_flush_buffer
+#define yy_scan_buffer lttng_filter_yy_scan_buffer
+#define yy_scan_bytes lttng_filter_yy_scan_bytes
+#define yy_scan_string lttng_filter_yy_scan_string
+#define yy_switch_to_buffer lttng_filter_yy_switch_to_buffer
+#define yyalloc lttng_filter_yyalloc
+#define yyfree lttng_filter_yyfree
+#define yyget_column lttng_filter_yyget_column
+#define yyget_debug lttng_filter_yyget_debug
+#define yyget_extra lttng_filter_yyget_extra
+#define yyget_in lttng_filter_yyget_in
+#define yyget_leng lttng_filter_yyget_leng
+#define yyget_lineno lttng_filter_yyget_lineno
+#define yyget_lval lttng_filter_yyget_lval
+#define yyget_out lttng_filter_yyget_out
+#define yyget_text lttng_filter_yyget_text
+#define yylex_init lttng_filter_yylex_init
+#define yypop_buffer_state lttng_filter_yypop_buffer_state
+#define yypush_buffer_state lttng_filter_yypush_buffer_state
+#define yyrealloc lttng_filter_yyrealloc
+#define yyset_column lttng_filter_yyset_column
+#define yyset_debug lttng_filter_yyset_debug
+#define yyset_extra lttng_filter_yyset_extra
+#define yyset_in lttng_filter_yyset_in
+#define yyset_lineno lttng_filter_yyset_lineno
+#define yyset_lval lttng_filter_yyset_lval
+#define yyset_out lttng_filter_yyset_out
+
+#endif /* _FILTER_SYMBOLS_H */
index c7e1be782666f7f0fdf292d57564ea2cdda91688..252a83870e87032b1ab101286c9bf89e783d2dcc 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
-#include <common/align.h>
-#include <common/compat/errno.h>
-#include <common/compat/string.h>
-
-#include "common/align.h"
-#include "common/bytecode/bytecode.h"
-#include "common/compat/string.h"
-#include "common/macros.h"
-#include "common/string-utils/string-utils.h"
-#include "filter-ast.h"
-#include "filter-ir.h"
-
-#ifndef max_t
-#define max_t(type, a, b)      ((type) ((a) > (b) ? (a) : (b)))
-#endif
+#include <common/align.hpp>
+#include <common/compat/errno.hpp>
+#include <common/compat/string.hpp>
+
+#include "common/align.hpp"
+#include "common/bytecode/bytecode.hpp"
+#include "common/compat/string.hpp"
+#include "common/macros.hpp"
+#include "common/string-utils/string-utils.hpp"
+#include "filter-ast.hpp"
+#include "filter-ir.hpp"
 
 static
 int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx,
index 3705ce4f283453ed190e4f9d75bdca02bdc2d6ca..a7236bd104f7e7314301507dc7442bb3a82b6f6a 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <inttypes.h>
-#include "filter-ast.h"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
-#include "filter-ir.h"
+#include "filter-ir.hpp"
 
-#include <common/compat/errno.h>
-#include <common/macros.h>
-#include <common/string-utils/string-utils.h>
+#include <common/compat/errno.hpp>
+#include <common/macros.hpp>
+#include <common/string-utils/string-utils.hpp>
 
 static
 struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
index 480100f25c535a83c2433e81bae202017d1ae7ea..2699abde8b5379d52f81673d1d0b12ba1affc0e3 100644 (file)
 #include <stdlib.h>
 #include <inttypes.h>
 
-#include <common/compat/errno.h>
+#include <common/compat/errno.hpp>
 
-#include "filter-ast.h"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
-#include "filter-ir.h"
+#include "filter-ir.hpp"
 
 static
 int check_bin_comparator(struct ir_op *node)
index 290ea0367aa80d4742862abac7ec01cb5939d4cf..9c3dd76737f64f57e3d1a5a5aea34768d4190c54 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <inttypes.h>
-#include "filter-ast.h"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
-#include "filter-ir.h"
+#include "filter-ir.hpp"
 
-#include <common/compat/errno.h>
-#include <common/macros.h>
+#include <common/compat/errno.hpp>
+#include <common/macros.hpp>
 
 static
 int check_bin_op_nesting_recursive(struct ir_op *node, int nesting)
index a091b812305cb10a470a54cc6e2641f99a7424e0..446c720db635e9ea0e0eb1d33c9c625f408980d8 100644 (file)
 #include <stdlib.h>
 #include <inttypes.h>
 
-#include <common/compat/errno.h>
-#include <common/macros.h>
-#include <common/string-utils/string-utils.h>
+#include <common/compat/errno.hpp>
+#include <common/macros.hpp>
+#include <common/string-utils/string-utils.hpp>
 
-#include "filter-ast.h"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
-#include "filter-ir.h"
+#include "filter-ir.hpp"
 
 static
 int normalize_glob_patterns(struct ir_op *node)
index 8f9c785c49b231925822581fe3019e4ca8212467..718098a433403bea810158b9e8b5b2fe27ca030a 100644 (file)
 #include <stdlib.h>
 #include <inttypes.h>
 
-#include <common/compat/errno.h>
-#include <common/macros.h>
+#include <common/compat/errno.hpp>
+#include <common/macros.hpp>
 
-#include "filter-ast.h"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
-#include "filter-ir.h"
+#include "filter-ir.hpp"
 
 static
 int validate_globbing(struct ir_op *node)
index 0c18f98bc7b25959eeb98b71d12d4bf040484933..9e060ce2b64e4fe77817c0af71fe76e150be308a 100644 (file)
 #include <stdlib.h>
 #include <inttypes.h>
 
-#include <common/macros.h>
-#include <common/compat/errno.h>
+#include <common/macros.hpp>
+#include <common/compat/errno.hpp>
 
-#include "filter-ast.h"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
-#include "filter-ir.h"
+#include "filter-ir.hpp"
 
 enum parse_char_result {
        PARSE_CHAR_UNKNOWN = -2,
index eb12452a60d0918f08d9264a7aac39b0b6944dac..5b531a28979ad7a09eb788fdf55b47d62493cbd8 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <inttypes.h>
-#include "filter-ast.h"
+#include "filter-ast.hpp"
 #include "filter-parser.hpp"
 
-#include <common/compat/errno.h>
-#include <common/macros.h>
+#include <common/compat/errno.hpp>
+#include <common/macros.hpp>
 
 #define fprintf_dbg(fd, fmt, args...)  fprintf(fd, "%s: " fmt, __func__, ## args)
 
diff --git a/src/common/filter/memstream.h b/src/common/filter/memstream.h
deleted file mode 100644 (file)
index 41c7681..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012 (C) Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef _LTTNG_CTL_MEMSTREAM_H
-#define _LTTNG_CTL_MEMSTREAM_H
-
-#ifdef LTTNG_HAVE_FMEMOPEN
-#include <stdio.h>
-
-static inline
-FILE *lttng_fmemopen(void *buf, size_t size, const char *mode)
-{
-       return fmemopen(buf, size, mode);
-}
-
-#else /* LTTNG_HAVE_FMEMOPEN */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <common/error.h>
-
-/*
- * Fallback for systems which don't have fmemopen. Copy buffer to a
- * temporary file, and use that file as FILE * input.
- */
-static inline
-FILE *lttng_fmemopen(void *buf, size_t size, const char *mode)
-{
-       char tmpname[PATH_MAX];
-       size_t len;
-       FILE *fp;
-       int ret;
-
-       /*
-        * Support reading only.
-        */
-       if (strcmp(mode, "rb") != 0) {
-               return NULL;
-       }
-       strncpy(tmpname, "/tmp/lttng-tmp-XXXXXX", PATH_MAX);
-       ret = mkstemp(tmpname);
-       if (ret < 0) {
-               return NULL;
-       }
-       /*
-        * We need to write to the file.
-        */
-       fp = fdopen(ret, "w+");
-       if (!fp) {
-               goto error_unlink;
-       }
-       /* Copy the entire buffer to the file */
-       len = fwrite(buf, sizeof(char), size, fp);
-       if (len != size) {
-               goto error_close;
-       }
-       ret = fseek(fp, 0L, SEEK_SET);
-       if (ret < 0) {
-               PERROR("fseek");
-               goto error_close;
-       }
-       /* We keep the handle open, but can unlink the file on the VFS. */
-       ret = unlink(tmpname);
-       if (ret < 0) {
-               PERROR("unlink");
-       }
-       return fp;
-
-error_close:
-       ret = fclose(fp);
-       if (ret < 0) {
-               PERROR("close");
-       }
-error_unlink:
-       ret = unlink(tmpname);
-       if (ret < 0) {
-               PERROR("unlink");
-       }
-       return NULL;
-}
-
-#endif /* LTTNG_HAVE_FMEMOPEN */
-
-#endif /* _LTTNG_CTL_MEMSTREAM_H */
diff --git a/src/common/filter/memstream.hpp b/src/common/filter/memstream.hpp
new file mode 100644 (file)
index 0000000..26b124a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 (C) Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef _LTTNG_CTL_MEMSTREAM_H
+#define _LTTNG_CTL_MEMSTREAM_H
+
+#ifdef LTTNG_HAVE_FMEMOPEN
+#include <stdio.h>
+
+static inline
+FILE *lttng_fmemopen(void *buf, size_t size, const char *mode)
+{
+       return fmemopen(buf, size, mode);
+}
+
+#else /* LTTNG_HAVE_FMEMOPEN */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <common/error.hpp>
+
+/*
+ * Fallback for systems which don't have fmemopen. Copy buffer to a
+ * temporary file, and use that file as FILE * input.
+ */
+static inline
+FILE *lttng_fmemopen(void *buf, size_t size, const char *mode)
+{
+       char tmpname[PATH_MAX];
+       size_t len;
+       FILE *fp;
+       int ret;
+
+       /*
+        * Support reading only.
+        */
+       if (strcmp(mode, "rb") != 0) {
+               return NULL;
+       }
+       strncpy(tmpname, "/tmp/lttng-tmp-XXXXXX", PATH_MAX);
+       ret = mkstemp(tmpname);
+       if (ret < 0) {
+               return NULL;
+       }
+       /*
+        * We need to write to the file.
+        */
+       fp = fdopen(ret, "w+");
+       if (!fp) {
+               goto error_unlink;
+       }
+       /* Copy the entire buffer to the file */
+       len = fwrite(buf, sizeof(char), size, fp);
+       if (len != size) {
+               goto error_close;
+       }
+       ret = fseek(fp, 0L, SEEK_SET);
+       if (ret < 0) {
+               PERROR("fseek");
+               goto error_close;
+       }
+       /* We keep the handle open, but can unlink the file on the VFS. */
+       ret = unlink(tmpname);
+       if (ret < 0) {
+               PERROR("unlink");
+       }
+       return fp;
+
+error_close:
+       ret = fclose(fp);
+       if (ret < 0) {
+               PERROR("close");
+       }
+error_unlink:
+       ret = unlink(tmpname);
+       if (ret < 0) {
+               PERROR("unlink");
+       }
+       return NULL;
+}
+
+#endif /* LTTNG_HAVE_FMEMOPEN */
+
+#endif /* _LTTNG_CTL_MEMSTREAM_H */
diff --git a/src/common/fs-handle-internal.h b/src/common/fs-handle-internal.h
deleted file mode 100644 (file)
index 0882467..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef FS_HANDLE_INTERNAL_H
-#define FS_HANDLE_INTERNAL_H
-
-struct fs_handle;
-
-/*
- * Multiple internal APIs return fs_handles. For the moment, this internal
- * interface allows the use of different fs_handle implementations in different
- * daemons. For instance, the trace chunk interface returns fs_handles that
- * behave diffently depending on whether or not the trace chunk was configured
- * to use an fd-tracker.
- */
-
-typedef int (*fs_handle_get_fd_cb)(struct fs_handle *);
-typedef void (*fs_handle_put_fd_cb)(struct fs_handle *);
-typedef int (*fs_handle_unlink_cb)(struct fs_handle *);
-typedef int (*fs_handle_close_cb)(struct fs_handle *);
-
-struct fs_handle {
-       fs_handle_get_fd_cb get_fd;
-       fs_handle_put_fd_cb put_fd;
-       fs_handle_unlink_cb unlink;
-       fs_handle_close_cb close;
-};
-
-#endif /* FS_HANDLE_INTERNAL_H */
diff --git a/src/common/fs-handle-internal.hpp b/src/common/fs-handle-internal.hpp
new file mode 100644 (file)
index 0000000..0882467
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef FS_HANDLE_INTERNAL_H
+#define FS_HANDLE_INTERNAL_H
+
+struct fs_handle;
+
+/*
+ * Multiple internal APIs return fs_handles. For the moment, this internal
+ * interface allows the use of different fs_handle implementations in different
+ * daemons. For instance, the trace chunk interface returns fs_handles that
+ * behave diffently depending on whether or not the trace chunk was configured
+ * to use an fd-tracker.
+ */
+
+typedef int (*fs_handle_get_fd_cb)(struct fs_handle *);
+typedef void (*fs_handle_put_fd_cb)(struct fs_handle *);
+typedef int (*fs_handle_unlink_cb)(struct fs_handle *);
+typedef int (*fs_handle_close_cb)(struct fs_handle *);
+
+struct fs_handle {
+       fs_handle_get_fd_cb get_fd;
+       fs_handle_put_fd_cb put_fd;
+       fs_handle_unlink_cb unlink;
+       fs_handle_close_cb close;
+};
+
+#endif /* FS_HANDLE_INTERNAL_H */
index bed0010e76d9f850b5f88e40035f5ae0099ca59f..ffdb883bd61c86921c8dc4e1cf14350093283236 100644 (file)
@@ -5,9 +5,9 @@
  *
  */
 
-#include <common/fs-handle-internal.h>
-#include <common/fs-handle.h>
-#include <common/readwrite.h>
+#include <common/fs-handle-internal.hpp>
+#include <common/fs-handle.hpp>
+#include <common/readwrite.hpp>
 
 int fs_handle_get_fd(struct fs_handle *handle)
 {
diff --git a/src/common/fs-handle.h b/src/common/fs-handle.h
deleted file mode 100644 (file)
index be6419c..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef FS_HANDLE_H
-#define FS_HANDLE_H
-
-#include <common/macros.h>
-#include <stdio.h>
-
-struct fs_handle;
-
-/*
- * Marks the handle as the most recently used and marks the 'fd' as
- * "in-use". This prevents the tracker from recycling the underlying
- * file descriptor while it is actively being used by a thread.
- *
- * Don't forget that the tracker may be initiating an fd 'suspension'
- * from another thread as the need to free an fd slot may arise from any
- * thread within the daemon.
- *
- * Note that a restorable fd should never be held for longer than
- * strictly necessary (e.g. the duration of a syscall()).
- *
- * Returns the fd on success, otherwise a negative value may be returned
- * if the restoration of the fd failed.
- */
-int fs_handle_get_fd(struct fs_handle *handle);
-
-/*
- * Used by the caller to signal that it is no longer using the underlying fd and
- * that it may be safely suspended.
- */
-void fs_handle_put_fd(struct fs_handle *handle);
-
-/*
- * Unlink the file associated to an fs_handle. Note that the unlink
- * operation will not be performed immediately. It will only be performed
- * once all references to the underlying file (through other fs_handle objects)
- * have been released.
- *
- * However, note that the file will be renamed so as to provide the observable
- * effect of an unlink(), that is removing a name from the filesystem.
- *
- * Returns 0 on success, otherwise a negative value will be returned
- * if the operation failed.
- */
-int fs_handle_unlink(struct fs_handle *handle);
-
-/*
- * Frees the handle and discards the underlying fd.
- */
-int fs_handle_close(struct fs_handle *handle);
-
-ssize_t fs_handle_read(struct fs_handle *handle, void *buf, size_t count);
-
-ssize_t fs_handle_write(struct fs_handle *handle, const void *buf, size_t count);
-
-int fs_handle_truncate(struct fs_handle *handle, off_t offset);
-
-off_t fs_handle_seek(struct fs_handle *handle, off_t offset, int whence);
-
-#endif /* FS_HANDLE_H */
diff --git a/src/common/fs-handle.hpp b/src/common/fs-handle.hpp
new file mode 100644 (file)
index 0000000..8b3a882
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef FS_HANDLE_H
+#define FS_HANDLE_H
+
+#include <common/macros.hpp>
+#include <stdio.h>
+
+struct fs_handle;
+
+/*
+ * Marks the handle as the most recently used and marks the 'fd' as
+ * "in-use". This prevents the tracker from recycling the underlying
+ * file descriptor while it is actively being used by a thread.
+ *
+ * Don't forget that the tracker may be initiating an fd 'suspension'
+ * from another thread as the need to free an fd slot may arise from any
+ * thread within the daemon.
+ *
+ * Note that a restorable fd should never be held for longer than
+ * strictly necessary (e.g. the duration of a syscall()).
+ *
+ * Returns the fd on success, otherwise a negative value may be returned
+ * if the restoration of the fd failed.
+ */
+int fs_handle_get_fd(struct fs_handle *handle);
+
+/*
+ * Used by the caller to signal that it is no longer using the underlying fd and
+ * that it may be safely suspended.
+ */
+void fs_handle_put_fd(struct fs_handle *handle);
+
+/*
+ * Unlink the file associated to an fs_handle. Note that the unlink
+ * operation will not be performed immediately. It will only be performed
+ * once all references to the underlying file (through other fs_handle objects)
+ * have been released.
+ *
+ * However, note that the file will be renamed so as to provide the observable
+ * effect of an unlink(), that is removing a name from the filesystem.
+ *
+ * Returns 0 on success, otherwise a negative value will be returned
+ * if the operation failed.
+ */
+int fs_handle_unlink(struct fs_handle *handle);
+
+/*
+ * Frees the handle and discards the underlying fd.
+ */
+int fs_handle_close(struct fs_handle *handle);
+
+ssize_t fs_handle_read(struct fs_handle *handle, void *buf, size_t count);
+
+ssize_t fs_handle_write(struct fs_handle *handle, const void *buf, size_t count);
+
+int fs_handle_truncate(struct fs_handle *handle, off_t offset);
+
+off_t fs_handle_seek(struct fs_handle *handle, off_t offset, int whence);
+
+#endif /* FS_HANDLE_H */
index d0f95abc8b8175ebb4bf158bd7df364cad2f4bcd..c77521b190293de1f7127bcc4cfdced6ef30c066 100644 (file)
@@ -12,9 +12,9 @@
 #include <urcu.h>
 #include <urcu/futex.h>
 
-#include <common/common.h>
+#include <common/common.hpp>
 
-#include "futex.h"
+#include "futex.hpp"
 
 /*
  * This futex wait/wake scheme only works for N wakers / 1 waiters. Hence the
diff --git a/src/common/futex.h b/src/common/futex.h
deleted file mode 100644 (file)
index 602be31..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_FUTEX_H
-#define _LTT_FUTEX_H
-
-void futex_wait_update(int32_t *futex, int active);
-void futex_nto1_prepare(int32_t *futex);
-void futex_nto1_wait(int32_t *futex);
-void futex_nto1_wake(int32_t *futex);
-
-#endif /* _LTT_FUTEX_H */
diff --git a/src/common/futex.hpp b/src/common/futex.hpp
new file mode 100644 (file)
index 0000000..602be31
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_FUTEX_H
+#define _LTT_FUTEX_H
+
+void futex_wait_update(int32_t *futex, int active);
+void futex_nto1_prepare(int32_t *futex);
+void futex_nto1_wait(int32_t *futex);
+void futex_nto1_wake(int32_t *futex);
+
+#endif /* _LTT_FUTEX_H */
diff --git a/src/common/hashtable/Makefile.am b/src/common/hashtable/Makefile.am
deleted file mode 100644 (file)
index b14254b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libhashtable.la
-
-libhashtable_la_SOURCES = \
-       hashtable.cpp \
-       hashtable.h \
-       hashtable-symbols.h \
-        utils.cpp \
-       utils.h
-
-libhashtable_la_LIBADD = $(URCU_LIBS) $(URCU_CDS_LIBS)
diff --git a/src/common/hashtable/hashtable-symbols.h b/src/common/hashtable/hashtable-symbols.h
deleted file mode 100644 (file)
index 5f22c0e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _HASHTABLE_SYMBOLS_H
-#define _HASHTABLE_SYMBOLS_H
-
-/*
- * hashtable-symbols.h
- *
- * LTTng hash table symbol prefixing
- *
- * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#define _cds_lfht_new lttng__cds_lfht_new
-#define cds_lfht_add lttng_cds_lfht_add
-#define cds_lfht_add_replace lttng_cds_lfht_add_replace
-#define cds_lfht_add_unique lttng_cds_lfht_add_unique
-#define cds_lfht_count_nodes lttng_cds_lfht_count_nodes
-#define cds_lfht_del lttng_cds_lfht_del
-#define cds_lfht_destroy lttng_cds_lfht_destroy
-#define cds_lfht_first lttng_cds_lfht_first
-#define cds_lfht_fls_ulong lttng_cds_lfht_fls_ulong
-#define cds_lfht_get_count_order_u32 lttng_cds_lfht_get_count_order_u32
-#define cds_lfht_get_count_order_ulong lttng_cds_lfht_get_count_order_ulong
-#define cds_lfht_is_node_deleted lttng_cds_lfht_is_node_deleted
-#define cds_lfht_lookup lttng_cds_lfht_lookup
-#define cds_lfht_next lttng_cds_lfht_next
-#define cds_lfht_next_duplicate lttng_cds_lfht_next_duplicate
-#define cds_lfht_replace lttng_cds_lfht_replace
-#define cds_lfht_resize lttng_cds_lfht_resize
-
-#endif /* _HASHTABLE_SYMBOLS_H */
diff --git a/src/common/hashtable/hashtable-symbols.hpp b/src/common/hashtable/hashtable-symbols.hpp
new file mode 100644 (file)
index 0000000..5f22c0e
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _HASHTABLE_SYMBOLS_H
+#define _HASHTABLE_SYMBOLS_H
+
+/*
+ * hashtable-symbols.h
+ *
+ * LTTng hash table symbol prefixing
+ *
+ * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _cds_lfht_new lttng__cds_lfht_new
+#define cds_lfht_add lttng_cds_lfht_add
+#define cds_lfht_add_replace lttng_cds_lfht_add_replace
+#define cds_lfht_add_unique lttng_cds_lfht_add_unique
+#define cds_lfht_count_nodes lttng_cds_lfht_count_nodes
+#define cds_lfht_del lttng_cds_lfht_del
+#define cds_lfht_destroy lttng_cds_lfht_destroy
+#define cds_lfht_first lttng_cds_lfht_first
+#define cds_lfht_fls_ulong lttng_cds_lfht_fls_ulong
+#define cds_lfht_get_count_order_u32 lttng_cds_lfht_get_count_order_u32
+#define cds_lfht_get_count_order_ulong lttng_cds_lfht_get_count_order_ulong
+#define cds_lfht_is_node_deleted lttng_cds_lfht_is_node_deleted
+#define cds_lfht_lookup lttng_cds_lfht_lookup
+#define cds_lfht_next lttng_cds_lfht_next
+#define cds_lfht_next_duplicate lttng_cds_lfht_next_duplicate
+#define cds_lfht_replace lttng_cds_lfht_replace
+#define cds_lfht_resize lttng_cds_lfht_resize
+
+#endif /* _HASHTABLE_SYMBOLS_H */
index 7112debf28eae58a63bc6bb7d367ffac81f6a6c1..7985c07e4b377b61fd3ab6689ef21284c8bca28b 100644 (file)
 #include <urcu.h>
 #include <urcu/compiler.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
+#include <common/common.hpp>
+#include <common/defaults.hpp>
 
-#include "hashtable.h"
-#include "utils.h"
+#include "hashtable.hpp"
+#include "utils.hpp"
 
 /* seed_lock protects both seed_init and lttng_ht_seed. */
 static pthread_mutex_t seed_lock = PTHREAD_MUTEX_INITIALIZER;
diff --git a/src/common/hashtable/hashtable.h b/src/common/hashtable/hashtable.h
deleted file mode 100644 (file)
index 3a515fd..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_HT_H
-#define _LTT_HT_H
-
-#include <urcu.h>
-#include <stdint.h>
-
-#include <common/macros.h>
-#include <lttng/lttng-export.h>
-#include <urcu/rculfhash.h>
-
-LTTNG_EXPORT extern unsigned long lttng_ht_seed;
-
-typedef unsigned long (*hash_fct_type)(const void *_key, unsigned long seed);
-typedef cds_lfht_match_fct hash_match_fct;
-
-enum lttng_ht_type {
-       LTTNG_HT_TYPE_STRING,
-       LTTNG_HT_TYPE_ULONG,
-       LTTNG_HT_TYPE_U64,
-       LTTNG_HT_TYPE_TWO_U64,
-};
-
-struct lttng_ht {
-       struct cds_lfht *ht;
-       cds_lfht_match_fct match_fct;
-       hash_fct_type hash_fct;
-};
-
-struct lttng_ht_iter {
-       struct cds_lfht_iter iter;
-};
-
-struct lttng_ht_node_str {
-       char *key;
-       struct cds_lfht_node node;
-       struct rcu_head head;
-};
-
-struct lttng_ht_node_ulong {
-       unsigned long key;
-       struct cds_lfht_node node;
-       struct rcu_head head;
-};
-
-struct lttng_ht_node_u64 {
-       uint64_t key;
-       struct cds_lfht_node node;
-       struct rcu_head head;
-};
-
-struct lttng_ht_two_u64 {
-       uint64_t key1;
-       uint64_t key2;
-};
-
-struct lttng_ht_node_two_u64 {
-       struct lttng_ht_two_u64 key;
-       struct cds_lfht_node node;
-       struct rcu_head head;
-};
-
-/* Hashtable new and destroy */
-struct lttng_ht *lttng_ht_new(unsigned long size, enum lttng_ht_type type);
-void lttng_ht_destroy(struct lttng_ht *ht);
-
-/* Specialized node init and free functions */
-void lttng_ht_node_init_str(struct lttng_ht_node_str *node, char *key);
-void lttng_ht_node_init_ulong(struct lttng_ht_node_ulong *node,
-               unsigned long key);
-void lttng_ht_node_init_u64(struct lttng_ht_node_u64 *node,
-               uint64_t key);
-void lttng_ht_node_init_two_u64(struct lttng_ht_node_two_u64 *node,
-               uint64_t key1, uint64_t key2);
-void lttng_ht_node_free_str(struct lttng_ht_node_str *node);
-void lttng_ht_node_free_ulong(struct lttng_ht_node_ulong *node);
-void lttng_ht_node_free_u64(struct lttng_ht_node_u64 *node);
-void lttng_ht_node_free_two_u64(struct lttng_ht_node_two_u64 *node);
-
-void lttng_ht_lookup(struct lttng_ht *ht, const void *key,
-               struct lttng_ht_iter *iter);
-
-/* Specialized add unique functions */
-void lttng_ht_add_unique_str(struct lttng_ht *ht,
-               struct lttng_ht_node_str *node);
-void lttng_ht_add_unique_ulong(struct lttng_ht *ht,
-               struct lttng_ht_node_ulong *node);
-void lttng_ht_add_unique_u64(struct lttng_ht *ht,
-               struct lttng_ht_node_u64 *node);
-void lttng_ht_add_unique_two_u64(struct lttng_ht *ht,
-               struct lttng_ht_node_two_u64 *node);
-struct lttng_ht_node_ulong *lttng_ht_add_replace_ulong(
-               struct lttng_ht *ht, struct lttng_ht_node_ulong *node);
-struct lttng_ht_node_u64 *lttng_ht_add_replace_u64(
-               struct lttng_ht *ht, struct lttng_ht_node_u64 *node);
-void lttng_ht_add_str(struct lttng_ht *ht,
-               struct lttng_ht_node_str *node);
-void lttng_ht_add_ulong(struct lttng_ht *ht,
-               struct lttng_ht_node_ulong *node);
-void lttng_ht_add_u64(struct lttng_ht *ht,
-               struct lttng_ht_node_u64 *node);
-
-int lttng_ht_del(struct lttng_ht *ht, struct lttng_ht_iter *iter);
-
-void lttng_ht_get_first(struct lttng_ht *ht,
-               struct lttng_ht_iter *iter);
-void lttng_ht_get_next(struct lttng_ht *ht, struct lttng_ht_iter *iter);
-
-unsigned long lttng_ht_get_count(struct lttng_ht *ht);
-
-struct lttng_ht_node_str *lttng_ht_iter_get_node_str(
-               struct lttng_ht_iter *iter);
-struct lttng_ht_node_ulong *lttng_ht_iter_get_node_ulong(
-               struct lttng_ht_iter *iter);
-struct lttng_ht_node_u64 *lttng_ht_iter_get_node_u64(
-               struct lttng_ht_iter *iter);
-struct lttng_ht_node_two_u64 *lttng_ht_iter_get_node_two_u64(
-               struct lttng_ht_iter *iter);
-
-#endif /* _LTT_HT_H */
diff --git a/src/common/hashtable/hashtable.hpp b/src/common/hashtable/hashtable.hpp
new file mode 100644 (file)
index 0000000..3dc3ed4
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_HT_H
+#define _LTT_HT_H
+
+#include <urcu.h>
+#include <stdint.h>
+
+#include <common/macros.hpp>
+#include <lttng/lttng-export.h>
+#include <urcu/rculfhash.h>
+
+LTTNG_EXPORT extern unsigned long lttng_ht_seed;
+
+typedef unsigned long (*hash_fct_type)(const void *_key, unsigned long seed);
+typedef cds_lfht_match_fct hash_match_fct;
+
+enum lttng_ht_type {
+       LTTNG_HT_TYPE_STRING,
+       LTTNG_HT_TYPE_ULONG,
+       LTTNG_HT_TYPE_U64,
+       LTTNG_HT_TYPE_TWO_U64,
+};
+
+struct lttng_ht {
+       struct cds_lfht *ht;
+       cds_lfht_match_fct match_fct;
+       hash_fct_type hash_fct;
+};
+
+struct lttng_ht_iter {
+       struct cds_lfht_iter iter;
+};
+
+struct lttng_ht_node_str {
+       char *key;
+       struct cds_lfht_node node;
+       struct rcu_head head;
+};
+
+struct lttng_ht_node_ulong {
+       unsigned long key;
+       struct cds_lfht_node node;
+       struct rcu_head head;
+};
+
+struct lttng_ht_node_u64 {
+       uint64_t key;
+       struct cds_lfht_node node;
+       struct rcu_head head;
+};
+
+struct lttng_ht_two_u64 {
+       uint64_t key1;
+       uint64_t key2;
+};
+
+struct lttng_ht_node_two_u64 {
+       struct lttng_ht_two_u64 key;
+       struct cds_lfht_node node;
+       struct rcu_head head;
+};
+
+/* Hashtable new and destroy */
+struct lttng_ht *lttng_ht_new(unsigned long size, enum lttng_ht_type type);
+void lttng_ht_destroy(struct lttng_ht *ht);
+
+/* Specialized node init and free functions */
+void lttng_ht_node_init_str(struct lttng_ht_node_str *node, char *key);
+void lttng_ht_node_init_ulong(struct lttng_ht_node_ulong *node,
+               unsigned long key);
+void lttng_ht_node_init_u64(struct lttng_ht_node_u64 *node,
+               uint64_t key);
+void lttng_ht_node_init_two_u64(struct lttng_ht_node_two_u64 *node,
+               uint64_t key1, uint64_t key2);
+void lttng_ht_node_free_str(struct lttng_ht_node_str *node);
+void lttng_ht_node_free_ulong(struct lttng_ht_node_ulong *node);
+void lttng_ht_node_free_u64(struct lttng_ht_node_u64 *node);
+void lttng_ht_node_free_two_u64(struct lttng_ht_node_two_u64 *node);
+
+void lttng_ht_lookup(struct lttng_ht *ht, const void *key,
+               struct lttng_ht_iter *iter);
+
+/* Specialized add unique functions */
+void lttng_ht_add_unique_str(struct lttng_ht *ht,
+               struct lttng_ht_node_str *node);
+void lttng_ht_add_unique_ulong(struct lttng_ht *ht,
+               struct lttng_ht_node_ulong *node);
+void lttng_ht_add_unique_u64(struct lttng_ht *ht,
+               struct lttng_ht_node_u64 *node);
+void lttng_ht_add_unique_two_u64(struct lttng_ht *ht,
+               struct lttng_ht_node_two_u64 *node);
+struct lttng_ht_node_ulong *lttng_ht_add_replace_ulong(
+               struct lttng_ht *ht, struct lttng_ht_node_ulong *node);
+struct lttng_ht_node_u64 *lttng_ht_add_replace_u64(
+               struct lttng_ht *ht, struct lttng_ht_node_u64 *node);
+void lttng_ht_add_str(struct lttng_ht *ht,
+               struct lttng_ht_node_str *node);
+void lttng_ht_add_ulong(struct lttng_ht *ht,
+               struct lttng_ht_node_ulong *node);
+void lttng_ht_add_u64(struct lttng_ht *ht,
+               struct lttng_ht_node_u64 *node);
+
+int lttng_ht_del(struct lttng_ht *ht, struct lttng_ht_iter *iter);
+
+void lttng_ht_get_first(struct lttng_ht *ht,
+               struct lttng_ht_iter *iter);
+void lttng_ht_get_next(struct lttng_ht *ht, struct lttng_ht_iter *iter);
+
+unsigned long lttng_ht_get_count(struct lttng_ht *ht);
+
+struct lttng_ht_node_str *lttng_ht_iter_get_node_str(
+               struct lttng_ht_iter *iter);
+struct lttng_ht_node_ulong *lttng_ht_iter_get_node_ulong(
+               struct lttng_ht_iter *iter);
+struct lttng_ht_node_u64 *lttng_ht_iter_get_node_u64(
+               struct lttng_ht_iter *iter);
+struct lttng_ht_node_two_u64 *lttng_ht_iter_get_node_two_u64(
+               struct lttng_ht_iter *iter);
+
+#endif /* _LTT_HT_H */
index 3bc2b5e914f05266b7fa711369ee1b7395c2287c..1613f7e6399bb24af813c51c8bdfca9f70444794 100644 (file)
 #include <time.h>       /* defines time_t for timings in the test */
 #include <urcu/compiler.h>
 
-#include "utils.h"
-#include <common/compat/endian.h>    /* attempt to define endianness */
-#include <common/common.h>
-#include <common/hashtable/hashtable.h>
+#include "utils.hpp"
+#include <common/compat/endian.hpp>    /* attempt to define endianness */
+#include <common/common.hpp>
+#include <common/hashtable/hashtable.hpp>
 
 /*
  * My best guess at if you are big-endian or little-endian.  This may
diff --git a/src/common/hashtable/utils.h b/src/common/hashtable/utils.h
deleted file mode 100644 (file)
index 9926439..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_HT_UTILS_H
-#define _LTT_HT_UTILS_H
-
-#include <stdint.h>
-
-unsigned long hash_key_ulong(const void *_key, unsigned long seed);
-unsigned long hash_key_u64(const void *_key, unsigned long seed);
-unsigned long hash_key_str(const void *key, unsigned long seed);
-unsigned long hash_key_two_u64(const void *key, unsigned long seed);
-int hash_match_key_ulong(const void *key1, const void *key2);
-int hash_match_key_u64(const void *key1, const void *key2);
-int hash_match_key_str(const void *key1, const void *key2);
-int hash_match_key_two_u64(const void *key1, const void *key2);
-
-#endif /* _LTT_HT_UTILS_H */
diff --git a/src/common/hashtable/utils.hpp b/src/common/hashtable/utils.hpp
new file mode 100644 (file)
index 0000000..9926439
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_HT_UTILS_H
+#define _LTT_HT_UTILS_H
+
+#include <stdint.h>
+
+unsigned long hash_key_ulong(const void *_key, unsigned long seed);
+unsigned long hash_key_u64(const void *_key, unsigned long seed);
+unsigned long hash_key_str(const void *key, unsigned long seed);
+unsigned long hash_key_two_u64(const void *key, unsigned long seed);
+int hash_match_key_ulong(const void *key1, const void *key2);
+int hash_match_key_u64(const void *key1, const void *key2);
+int hash_match_key_str(const void *key1, const void *key2);
+int hash_match_key_two_u64(const void *key1, const void *key2);
+
+#endif /* _LTT_HT_UTILS_H */
diff --git a/src/common/health/Makefile.am b/src/common/health/Makefile.am
deleted file mode 100644 (file)
index cb10139..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libhealth.la
-
-libhealth_la_SOURCES = health.cpp
index 8a07e642607cb6cb401a57c845043ca63870f97e..9d33ffd2fc7b8e487885bc69d0fbce0c6875f09d 100644 (file)
 #include <stdlib.h>
 #include <time.h>
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/sessiond-comm/inet.h>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/sessiond-comm/inet.hpp>
 
-#include <lttng/health-internal.h>
+#include <lttng/health-internal.hpp>
 
 /*
  * An application-specific error state for unregistered thread keeps
index c48d708d0ea2759e8806aa5558d949ae2ec12e8d..7fe18eb1862cd41674b38c359d425de62f1365ad 100644 (file)
 #include <urcu.h>
 #include <urcu/list.h>
 
-#include "macros.h"
-#include "error.h"
+#include "macros.hpp"
+#include "error.hpp"
 
-#include "index-allocator.h"
+#include "index-allocator.hpp"
 
 struct lttng_index_allocator {
        struct cds_list_head unused_list;
diff --git a/src/common/index-allocator.h b/src/common/index-allocator.h
deleted file mode 100644 (file)
index ee7c2ec..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMMON_INDEX_ALLOCATOR_H
-#define _COMMON_INDEX_ALLOCATOR_H
-
-#include <inttypes.h>
-#include <lttng/lttng-export.h>
-
-struct lttng_index_allocator;
-
-enum lttng_index_allocator_status {
-       LTTNG_INDEX_ALLOCATOR_STATUS_OK,
-       LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY,
-       LTTNG_INDEX_ALLOCATOR_STATUS_ERROR,
-};
-
-/*
- * Create an index allocator of `index_count` slots.
- */
-extern "C" LTTNG_EXPORT
-struct lttng_index_allocator *lttng_index_allocator_create(
-               uint64_t index_count);
-
-/*
- * Get the number of indexes currently in use.
- */
-extern "C" LTTNG_EXPORT
-uint64_t lttng_index_allocator_get_index_count(
-       struct lttng_index_allocator *allocator);
-
-/*
- * Allocate (i.e. reserve) a slot.
- */
-extern "C" LTTNG_EXPORT
-enum lttng_index_allocator_status lttng_index_allocator_alloc(
-               struct lttng_index_allocator *allocator,
-               uint64_t *index);
-
-/*
- * Release a slot by index. The slot will be re-used by the index allocator
- * in future 'alloc' calls.
- */
-extern "C" LTTNG_EXPORT
-enum lttng_index_allocator_status lttng_index_allocator_release(
-               struct lttng_index_allocator *allocator, uint64_t index);
-
-/*
- * Destroy an index allocator.
- */
-extern "C" LTTNG_EXPORT
-void lttng_index_allocator_destroy(struct lttng_index_allocator *allocator);
-
-#endif /* _COMMON_INDEX_ALLOCATOR_H */
diff --git a/src/common/index-allocator.hpp b/src/common/index-allocator.hpp
new file mode 100644 (file)
index 0000000..ee7c2ec
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMMON_INDEX_ALLOCATOR_H
+#define _COMMON_INDEX_ALLOCATOR_H
+
+#include <inttypes.h>
+#include <lttng/lttng-export.h>
+
+struct lttng_index_allocator;
+
+enum lttng_index_allocator_status {
+       LTTNG_INDEX_ALLOCATOR_STATUS_OK,
+       LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY,
+       LTTNG_INDEX_ALLOCATOR_STATUS_ERROR,
+};
+
+/*
+ * Create an index allocator of `index_count` slots.
+ */
+extern "C" LTTNG_EXPORT
+struct lttng_index_allocator *lttng_index_allocator_create(
+               uint64_t index_count);
+
+/*
+ * Get the number of indexes currently in use.
+ */
+extern "C" LTTNG_EXPORT
+uint64_t lttng_index_allocator_get_index_count(
+       struct lttng_index_allocator *allocator);
+
+/*
+ * Allocate (i.e. reserve) a slot.
+ */
+extern "C" LTTNG_EXPORT
+enum lttng_index_allocator_status lttng_index_allocator_alloc(
+               struct lttng_index_allocator *allocator,
+               uint64_t *index);
+
+/*
+ * Release a slot by index. The slot will be re-used by the index allocator
+ * in future 'alloc' calls.
+ */
+extern "C" LTTNG_EXPORT
+enum lttng_index_allocator_status lttng_index_allocator_release(
+               struct lttng_index_allocator *allocator, uint64_t index);
+
+/*
+ * Destroy an index allocator.
+ */
+extern "C" LTTNG_EXPORT
+void lttng_index_allocator_destroy(struct lttng_index_allocator *allocator);
+
+#endif /* _COMMON_INDEX_ALLOCATOR_H */
diff --git a/src/common/index/Makefile.am b/src/common/index/Makefile.am
deleted file mode 100644 (file)
index d62a31c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libindex.la
-
-libindex_la_SOURCES = \
-       ctf-index.h \
-       index.cpp \
-       index.h
diff --git a/src/common/index/ctf-index.h b/src/common/index/ctf-index.h
deleted file mode 100644 (file)
index 7fc7fd8..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef LTTNG_INDEX_H
-#define LTTNG_INDEX_H
-
-#include <common/compat/endian.h>
-#include <common/macros.h>
-
-#include <stdint.h>
-#include <limits.h>
-#include <stddef.h>
-
-#define CTF_INDEX_MAGIC 0xC1F1DCC1
-#define CTF_INDEX_MAJOR 1
-#define CTF_INDEX_MINOR 1
-
-/*
- * Header at the beginning of each index file.
- * All integer fields are stored in big endian.
- */
-struct ctf_packet_index_file_hdr {
-       uint32_t magic;
-       uint32_t index_major;
-       uint32_t index_minor;
-       /* struct packet_index_len, in bytes */
-       uint32_t packet_index_len;
-} __attribute__((__packed__));
-
-/*
- * Packet index generated for each trace packet stored in a trace file.
- * All integer fields are stored in big endian.
- */
-struct ctf_packet_index {
-       uint64_t offset;                /* offset of the packet in the file, in bytes */
-       uint64_t packet_size;           /* packet size, in bits */
-       uint64_t content_size;          /* content size, in bits */
-       uint64_t timestamp_begin;
-       uint64_t timestamp_end;
-       uint64_t events_discarded;
-       uint64_t stream_id;             /* ID of the channel */
-       /* CTF_INDEX 1.0 limit */
-       uint64_t stream_instance_id;    /* ID of the channel instance */
-       uint64_t packet_seq_num;        /* packet sequence number */
-} __attribute__((__packed__));
-
-static inline size_t ctf_packet_index_len(uint32_t major, uint32_t minor)
-{
-       if (major == 1) {
-               switch (minor) {
-               case 0:
-                       return offsetof(struct ctf_packet_index, stream_id)
-                               + member_sizeof(struct ctf_packet_index,
-                                               stream_id);
-               case 1:
-                       return offsetof(struct ctf_packet_index, packet_seq_num)
-                               + member_sizeof(struct ctf_packet_index,
-                                               packet_seq_num);
-               default:
-                       abort();
-               }
-       }
-       abort();
-}
-
-static inline uint32_t lttng_to_index_major(uint32_t lttng_major,
-               uint32_t lttng_minor __attribute__((unused)))
-{
-       if (lttng_major == 2) {
-               return 1;
-       }
-       abort();
-}
-
-static inline uint32_t lttng_to_index_minor(uint32_t lttng_major,
-               uint32_t lttng_minor)
-{
-       if (lttng_major == 2) {
-               if (lttng_minor < 8) {
-                       return 0;
-               } else {
-                       return 1;
-               }
-       }
-       abort();
-}
-
-static inline void ctf_packet_index_file_hdr_init(
-               struct ctf_packet_index_file_hdr *hdr,
-               uint32_t idx_major, uint32_t idx_minor)
-{
-       memset(hdr, 0, sizeof(*hdr));
-       hdr->magic = htobe32(CTF_INDEX_MAGIC);
-       hdr->index_major = htobe32(idx_major);
-       hdr->index_minor = htobe32(idx_minor);
-       hdr->packet_index_len = htobe32(
-                       ctf_packet_index_len(idx_major, idx_minor));
-}
-
-#endif /* LTTNG_INDEX_H */
diff --git a/src/common/index/ctf-index.hpp b/src/common/index/ctf-index.hpp
new file mode 100644 (file)
index 0000000..2b9bc54
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef LTTNG_INDEX_H
+#define LTTNG_INDEX_H
+
+#include <common/compat/endian.hpp>
+#include <common/macros.hpp>
+
+#include <stdint.h>
+#include <limits.h>
+#include <stddef.h>
+
+#define CTF_INDEX_MAGIC 0xC1F1DCC1
+#define CTF_INDEX_MAJOR 1
+#define CTF_INDEX_MINOR 1
+
+/*
+ * Header at the beginning of each index file.
+ * All integer fields are stored in big endian.
+ */
+struct ctf_packet_index_file_hdr {
+       uint32_t magic;
+       uint32_t index_major;
+       uint32_t index_minor;
+       /* struct packet_index_len, in bytes */
+       uint32_t packet_index_len;
+} __attribute__((__packed__));
+
+/*
+ * Packet index generated for each trace packet stored in a trace file.
+ * All integer fields are stored in big endian.
+ */
+struct ctf_packet_index {
+       uint64_t offset;                /* offset of the packet in the file, in bytes */
+       uint64_t packet_size;           /* packet size, in bits */
+       uint64_t content_size;          /* content size, in bits */
+       uint64_t timestamp_begin;
+       uint64_t timestamp_end;
+       uint64_t events_discarded;
+       uint64_t stream_id;             /* ID of the channel */
+       /* CTF_INDEX 1.0 limit */
+       uint64_t stream_instance_id;    /* ID of the channel instance */
+       uint64_t packet_seq_num;        /* packet sequence number */
+} __attribute__((__packed__));
+
+static inline size_t ctf_packet_index_len(uint32_t major, uint32_t minor)
+{
+       if (major == 1) {
+               switch (minor) {
+               case 0:
+                       return offsetof(struct ctf_packet_index, stream_id)
+                               + member_sizeof(struct ctf_packet_index,
+                                               stream_id);
+               case 1:
+                       return offsetof(struct ctf_packet_index, packet_seq_num)
+                               + member_sizeof(struct ctf_packet_index,
+                                               packet_seq_num);
+               default:
+                       abort();
+               }
+       }
+       abort();
+}
+
+static inline uint32_t lttng_to_index_major(uint32_t lttng_major,
+               uint32_t lttng_minor __attribute__((unused)))
+{
+       if (lttng_major == 2) {
+               return 1;
+       }
+       abort();
+}
+
+static inline uint32_t lttng_to_index_minor(uint32_t lttng_major,
+               uint32_t lttng_minor)
+{
+       if (lttng_major == 2) {
+               if (lttng_minor < 8) {
+                       return 0;
+               } else {
+                       return 1;
+               }
+       }
+       abort();
+}
+
+static inline void ctf_packet_index_file_hdr_init(
+               struct ctf_packet_index_file_hdr *hdr,
+               uint32_t idx_major, uint32_t idx_minor)
+{
+       memset(hdr, 0, sizeof(*hdr));
+       hdr->magic = htobe32(CTF_INDEX_MAGIC);
+       hdr->index_major = htobe32(idx_major);
+       hdr->index_minor = htobe32(idx_minor);
+       hdr->packet_index_len = htobe32(
+                       ctf_packet_index_len(idx_major, idx_minor));
+}
+
+#endif /* LTTNG_INDEX_H */
index 48d30e428253518412c276c89012d0cc71c1e2f0..9d6895baea9817af1a7e4c34dafffbce53e131ea 100644 (file)
 #include <fcntl.h>
 
 #include <lttng/constant.h>
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/compat/endian.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/compat/endian.hpp>
+#include <common/utils.hpp>
 
-#include "index.h"
+#include "index.hpp"
 
 #define WRITE_FILE_FLAGS       (O_WRONLY | O_CREAT | O_TRUNC)
 #define READ_ONLY_FILE_FLAGS   O_RDONLY
diff --git a/src/common/index/index.h b/src/common/index/index.h
deleted file mode 100644 (file)
index 25ecc19..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _INDEX_H
-#define _INDEX_H
-
-#include <inttypes.h>
-#include <urcu/ref.h>
-
-#include "ctf-index.h"
-#include <common/fs-handle.h>
-#include <common/trace-chunk.h>
-
-struct lttng_index_file {
-       struct fs_handle *file;
-       uint32_t major;
-       uint32_t minor;
-       uint32_t element_len;
-       struct lttng_trace_chunk *trace_chunk;
-       struct urcu_ref ref;
-};
-
-/*
- * create and open have refcount of 1. Use put to decrement the
- * refcount. Destroys when reaching 0. Use "get" to increment refcount.
- */
-enum lttng_trace_chunk_status lttng_index_file_create_from_trace_chunk(
-               struct lttng_trace_chunk *chunk,
-               const char *channel_path, const char *stream_name,
-               uint64_t stream_file_size, uint64_t stream_count,
-               uint32_t index_major, uint32_t index_minor,
-               bool unlink_existing_file, struct lttng_index_file **file);
-
-enum lttng_trace_chunk_status lttng_index_file_create_from_trace_chunk_read_only(
-               struct lttng_trace_chunk *chunk,
-               const char *channel_path, const char *stream_name,
-               uint64_t stream_file_size, uint64_t stream_file_index,
-               uint32_t index_major, uint32_t index_minor,
-               bool expect_no_file, struct lttng_index_file **file);
-
-int lttng_index_file_write(const struct lttng_index_file *index_file,
-               const struct ctf_packet_index *element);
-int lttng_index_file_read(const struct lttng_index_file *index_file,
-               struct ctf_packet_index *element);
-
-void lttng_index_file_get(struct lttng_index_file *index_file);
-void lttng_index_file_put(struct lttng_index_file *index_file);
-
-#endif /* _INDEX_H */
diff --git a/src/common/index/index.hpp b/src/common/index/index.hpp
new file mode 100644 (file)
index 0000000..00d8203
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _INDEX_H
+#define _INDEX_H
+
+#include <inttypes.h>
+#include <urcu/ref.h>
+
+#include "ctf-index.hpp"
+#include <common/fs-handle.hpp>
+#include <common/trace-chunk.hpp>
+
+struct lttng_index_file {
+       struct fs_handle *file;
+       uint32_t major;
+       uint32_t minor;
+       uint32_t element_len;
+       struct lttng_trace_chunk *trace_chunk;
+       struct urcu_ref ref;
+};
+
+/*
+ * create and open have refcount of 1. Use put to decrement the
+ * refcount. Destroys when reaching 0. Use "get" to increment refcount.
+ */
+enum lttng_trace_chunk_status lttng_index_file_create_from_trace_chunk(
+               struct lttng_trace_chunk *chunk,
+               const char *channel_path, const char *stream_name,
+               uint64_t stream_file_size, uint64_t stream_count,
+               uint32_t index_major, uint32_t index_minor,
+               bool unlink_existing_file, struct lttng_index_file **file);
+
+enum lttng_trace_chunk_status lttng_index_file_create_from_trace_chunk_read_only(
+               struct lttng_trace_chunk *chunk,
+               const char *channel_path, const char *stream_name,
+               uint64_t stream_file_size, uint64_t stream_file_index,
+               uint32_t index_major, uint32_t index_minor,
+               bool expect_no_file, struct lttng_index_file **file);
+
+int lttng_index_file_write(const struct lttng_index_file *index_file,
+               const struct ctf_packet_index *element);
+int lttng_index_file_read(const struct lttng_index_file *index_file,
+               struct ctf_packet_index *element);
+
+void lttng_index_file_get(struct lttng_index_file *index_file);
+void lttng_index_file_put(struct lttng_index_file *index_file);
+
+#endif /* _INDEX_H */
diff --git a/src/common/ini-config/Makefile.am b/src/common/ini-config/Makefile.am
deleted file mode 100644 (file)
index 7f0ee8d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libini-config.la
-
-libini_config_la_SOURCES = \
-       ini.cpp \
-       ini.h \
-       ini-config.cpp \
-       ini-config.h
index 797de0164d35303716c880a4d306cee10a5b5b8b..98308c9f348ee2946b86da36654c6897194779db 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include "ini-config.h"
+#include "ini-config.hpp"
 
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/ini-config/ini.h>
-#include <common/macros.h>
-#include <common/utils.h>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/ini-config/ini.hpp>
+#include <common/macros.hpp>
+#include <common/utils.hpp>
 #include <ctype.h>
 
 LTTNG_EXPORT const char *config_str_yes = "yes";
diff --git a/src/common/ini-config/ini-config.h b/src/common/ini-config/ini-config.h
deleted file mode 100644 (file)
index 3e41605..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef INI_CONFIG_H
-#define INI_CONFIG_H
-
-struct config_entry {
-       /* section is NULL if the entry is not in a section */
-       const char *section;
-       const char *name;
-       const char *value;
-};
-
-/*
- * A config_entry_handler_cb receives config_entry structures belonging to the
- * sections the handler has been registered to.
- *
- * The config_entry and its members are only valid for the duration of the call
- * and must not be freed.
- *
- * config_entry_handler_cb may return negative value to indicate an error in
- * the configuration file.
- */
-typedef int (*config_entry_handler_cb)(const struct config_entry *, void *);
-
-/*
- * Read a section's entries in an INI configuration file.
- *
- * path may be NULL, in which case the following paths will be tried:
- *     1) $HOME/.lttng/lttng.conf
- *     2) /etc/lttng/lttng.conf
- *
- * handler will only be called with entries belonging to the provided section.
- * If section is NULL, all entries will be relayed to handler. If section is
- * "", only the global entries are relayed.
- *
- * Returns 0 on success. Negative values are error codes. If the return value
- * is positive, it represents the line number on which a parsing error occurred.
- */
-int config_get_section_entries(const char *path, const char *section,
-               config_entry_handler_cb handler, void *user_data);
-
-/*
- * Parse a configuration value.
- *
- * This function expects either an unsigned integer or a boolean text option.
- * The following strings are recognized: true, yes, on, false, no and off.
- *
- * Returns either the value of the parsed integer, or 0/1 if a boolean text
- * string was recognized. Negative values indicate an error.
- */
-int config_parse_value(const char *value);
-
-#endif /* INI_CONFIG_H */
diff --git a/src/common/ini-config/ini-config.hpp b/src/common/ini-config/ini-config.hpp
new file mode 100644 (file)
index 0000000..3e41605
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef INI_CONFIG_H
+#define INI_CONFIG_H
+
+struct config_entry {
+       /* section is NULL if the entry is not in a section */
+       const char *section;
+       const char *name;
+       const char *value;
+};
+
+/*
+ * A config_entry_handler_cb receives config_entry structures belonging to the
+ * sections the handler has been registered to.
+ *
+ * The config_entry and its members are only valid for the duration of the call
+ * and must not be freed.
+ *
+ * config_entry_handler_cb may return negative value to indicate an error in
+ * the configuration file.
+ */
+typedef int (*config_entry_handler_cb)(const struct config_entry *, void *);
+
+/*
+ * Read a section's entries in an INI configuration file.
+ *
+ * path may be NULL, in which case the following paths will be tried:
+ *     1) $HOME/.lttng/lttng.conf
+ *     2) /etc/lttng/lttng.conf
+ *
+ * handler will only be called with entries belonging to the provided section.
+ * If section is NULL, all entries will be relayed to handler. If section is
+ * "", only the global entries are relayed.
+ *
+ * Returns 0 on success. Negative values are error codes. If the return value
+ * is positive, it represents the line number on which a parsing error occurred.
+ */
+int config_get_section_entries(const char *path, const char *section,
+               config_entry_handler_cb handler, void *user_data);
+
+/*
+ * Parse a configuration value.
+ *
+ * This function expects either an unsigned integer or a boolean text option.
+ * The following strings are recognized: true, yes, on, false, no and off.
+ *
+ * Returns either the value of the parsed integer, or 0/1 if a boolean text
+ * string was recognized. Negative values indicate an error.
+ */
+int config_parse_value(const char *value);
+
+#endif /* INI_CONFIG_H */
index 1d967a49d0b0da6de531da8d37a7ba1c0d2b05cb..d8ec8cf3e375545b36416867704e45fa2b16f2cc 100644 (file)
@@ -36,9 +36,9 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
-#include <common/common.h>
+#include <common/common.hpp>
 
-#include "ini.h"
+#include "ini.hpp"
 
 #if !INI_USE_STACK
 #include <stdlib.h>
diff --git a/src/common/ini-config/ini.h b/src/common/ini-config/ini.h
deleted file mode 100644 (file)
index 34b3654..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * inih -- simple .INI file parser
- *
- * The "inih" library is distributed under the New BSD license:
- *
- * Copyright (C) 2009 Brush Technology - All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *     * Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *     * Neither the name of Brush Technology nor the names of its contributors
- *     may be used to endorse or promote products derived from this software
- *     without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * http://code.google.com/p/inih/
- */
-
-#ifndef __INI_H__
-#define __INI_H__
-
-/* Make this header file easier to include in C++ code */
-#include <stdio.h>
-
-typedef int (*ini_entry_handler)(void *, const char *, const char *,
-               const char *);
-
-/*
- * Parse given INI-style file. May have [section]s, name=value pairs
- * (whitespace stripped), and comments starting with ';' (semicolon). Section
- * is "" if name=value pair parsed before any section heading. name:value
- * pairs are also supported as a concession to Python's ConfigParser.
- *
- * For each name=value pair parsed, call handler function with given user
- * pointer as well as section, name, and value (data only valid for duration
- * of handler call). Handler should return zero on success, < 0 on error.
- *
- * Returns 0 on success, line number of first error on parse error (doesn't
- * stop on first error), -1 on file open error, or -2 on memory allocation
- * error (only when INI_USE_STACK is zero).
- */
-int ini_parse(const char *filename, ini_entry_handler handler, void *user);
-
-/*
- * Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
- * close the file when it's finished -- the caller must do that.
- */
-int ini_parse_file(FILE *file, ini_entry_handler handler, void *user);
-
-/*
- * Nonzero to allow multi-line value parsing, in the style of Python's
- * ConfigParser. If allowed, ini_parse() will call the handler with the same
- * name for each subsequent line parsed.
- */
-#ifndef INI_ALLOW_MULTILINE
-#define INI_ALLOW_MULTILINE 1
-#endif
-
-/*
- * Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
- * the file. See http://code.google.com/p/inih/issues/detail?id=21
- */
-#ifndef INI_ALLOW_BOM
-#define INI_ALLOW_BOM 1
-#endif
-
-/* Nonzero to use stack, zero to use heap (malloc/free). */
-#ifndef INI_USE_STACK
-#define INI_USE_STACK 1
-#endif
-
-/* Maximum line length for any line in INI file. */
-#ifndef INI_MAX_LINE
-#define INI_MAX_LINE 200
-#endif
-
-#endif /* __INI_H__ */
diff --git a/src/common/ini-config/ini.hpp b/src/common/ini-config/ini.hpp
new file mode 100644 (file)
index 0000000..34b3654
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * inih -- simple .INI file parser
+ *
+ * The "inih" library is distributed under the New BSD license:
+ *
+ * Copyright (C) 2009 Brush Technology - All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Brush Technology nor the names of its contributors
+ *     may be used to endorse or promote products derived from this software
+ *     without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://code.google.com/p/inih/
+ */
+
+#ifndef __INI_H__
+#define __INI_H__
+
+/* Make this header file easier to include in C++ code */
+#include <stdio.h>
+
+typedef int (*ini_entry_handler)(void *, const char *, const char *,
+               const char *);
+
+/*
+ * Parse given INI-style file. May have [section]s, name=value pairs
+ * (whitespace stripped), and comments starting with ';' (semicolon). Section
+ * is "" if name=value pair parsed before any section heading. name:value
+ * pairs are also supported as a concession to Python's ConfigParser.
+ *
+ * For each name=value pair parsed, call handler function with given user
+ * pointer as well as section, name, and value (data only valid for duration
+ * of handler call). Handler should return zero on success, < 0 on error.
+ *
+ * Returns 0 on success, line number of first error on parse error (doesn't
+ * stop on first error), -1 on file open error, or -2 on memory allocation
+ * error (only when INI_USE_STACK is zero).
+ */
+int ini_parse(const char *filename, ini_entry_handler handler, void *user);
+
+/*
+ * Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
+ * close the file when it's finished -- the caller must do that.
+ */
+int ini_parse_file(FILE *file, ini_entry_handler handler, void *user);
+
+/*
+ * Nonzero to allow multi-line value parsing, in the style of Python's
+ * ConfigParser. If allowed, ini_parse() will call the handler with the same
+ * name for each subsequent line parsed.
+ */
+#ifndef INI_ALLOW_MULTILINE
+#define INI_ALLOW_MULTILINE 1
+#endif
+
+/*
+ * Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
+ * the file. See http://code.google.com/p/inih/issues/detail?id=21
+ */
+#ifndef INI_ALLOW_BOM
+#define INI_ALLOW_BOM 1
+#endif
+
+/* Nonzero to use stack, zero to use heap (malloc/free). */
+#ifndef INI_USE_STACK
+#define INI_USE_STACK 1
+#endif
+
+/* Maximum line length for any line in INI file. */
+#ifndef INI_MAX_LINE
+#define INI_MAX_LINE 200
+#endif
+
+#endif /* __INI_H__ */
diff --git a/src/common/kernel-consumer/Makefile.am b/src/common/kernel-consumer/Makefile.am
deleted file mode 100644 (file)
index b118413..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libkernel-consumer.la
-
-libkernel_consumer_la_SOURCES = \
-       kernel-consumer.cpp \
-       kernel-consumer.h
-
-libkernel_consumer_la_LIBADD = \
-                  $(top_builddir)/src/common/kernel-ctl/libkernel-ctl.la \
-                  $(top_builddir)/src/common/relayd/librelayd.la
index 8a6ef2a2760e14b7047785add29632589855cfb3..fe634ae5a4250aa46fdbe88a8d6aafdf6d4a9abe 100644 (file)
 #include <sys/stat.h>
 #include <stdint.h>
 
-#include <bin/lttng-consumerd/health-consumerd.h>
-#include <common/common.h>
-#include <common/kernel-ctl/kernel-ctl.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/sessiond-comm/relayd.h>
-#include <common/compat/fcntl.h>
-#include <common/compat/endian.h>
-#include <common/pipe.h>
-#include <common/relayd/relayd.h>
-#include <common/utils.h>
-#include <common/consumer/consumer-stream.h>
-#include <common/index/index.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/optional.h>
-#include <common/buffer-view.h>
-#include <common/consumer/consumer.h>
-#include <common/consumer/metadata-bucket.h>
-
-#include "kernel-consumer.h"
+#include <bin/lttng-consumerd/health-consumerd.hpp>
+#include <common/common.hpp>
+#include <common/kernel-ctl/kernel-ctl.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/compat/fcntl.hpp>
+#include <common/compat/endian.hpp>
+#include <common/pipe.hpp>
+#include <common/relayd/relayd.hpp>
+#include <common/utils.hpp>
+#include <common/consumer/consumer-stream.hpp>
+#include <common/index/index.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/optional.hpp>
+#include <common/buffer-view.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/consumer/metadata-bucket.hpp>
+
+#include "kernel-consumer.hpp"
 
 extern struct lttng_consumer_global_data the_consumer_data;
 extern int consumer_poll_timeout;
@@ -1773,7 +1773,7 @@ int lttng_kconsumer_set_stream_ops(
 {
        int ret = 0;
 
-       if (stream->metadata_flag && stream->chan->is_live) {
+       if (stream->metadata_flag) {
                DBG("Attempting to enable metadata bucketization for live consumers");
                if (is_get_next_check_metadata_available(stream->wait_fd)) {
                        DBG("Kernel tracer supports get_next_subbuffer_metadata_check, metadata will be accumulated until a coherent state is reached");
diff --git a/src/common/kernel-consumer/kernel-consumer.h b/src/common/kernel-consumer/kernel-consumer.h
deleted file mode 100644 (file)
index 004becb..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_KCONSUMER_H
-#define _LTTNG_KCONSUMER_H
-
-#include <stdbool.h>
-#include <common/consumer/consumer.h>
-
-int lttng_kconsumer_take_snapshot(struct lttng_consumer_stream *stream);
-int lttng_kconsumer_sample_snapshot_positions(
-               struct lttng_consumer_stream *stream);
-int lttng_kconsumer_get_produced_snapshot(struct lttng_consumer_stream *stream,
-               unsigned long *pos);
-int lttng_kconsumer_get_consumed_snapshot(struct lttng_consumer_stream *stream,
-               unsigned long *pos);
-int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
-               int sock, struct pollfd *consumer_sockpoll);
-int lttng_kconsumer_on_recv_stream(struct lttng_consumer_stream *stream);
-int lttng_kconsumer_data_pending(struct lttng_consumer_stream *stream);
-enum sync_metadata_status lttng_kconsumer_sync_metadata(
-               struct lttng_consumer_stream *metadata);
-
-#endif /* _LTTNG_KCONSUMER_H */
diff --git a/src/common/kernel-consumer/kernel-consumer.hpp b/src/common/kernel-consumer/kernel-consumer.hpp
new file mode 100644 (file)
index 0000000..600d508
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_KCONSUMER_H
+#define _LTTNG_KCONSUMER_H
+
+#include <stdbool.h>
+#include <common/consumer/consumer.hpp>
+
+int lttng_kconsumer_take_snapshot(struct lttng_consumer_stream *stream);
+int lttng_kconsumer_sample_snapshot_positions(
+               struct lttng_consumer_stream *stream);
+int lttng_kconsumer_get_produced_snapshot(struct lttng_consumer_stream *stream,
+               unsigned long *pos);
+int lttng_kconsumer_get_consumed_snapshot(struct lttng_consumer_stream *stream,
+               unsigned long *pos);
+int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
+               int sock, struct pollfd *consumer_sockpoll);
+int lttng_kconsumer_on_recv_stream(struct lttng_consumer_stream *stream);
+int lttng_kconsumer_data_pending(struct lttng_consumer_stream *stream);
+enum sync_metadata_status lttng_kconsumer_sync_metadata(
+               struct lttng_consumer_stream *metadata);
+
+#endif /* _LTTNG_KCONSUMER_H */
diff --git a/src/common/kernel-ctl/Makefile.am b/src/common/kernel-ctl/Makefile.am
deleted file mode 100644 (file)
index 976cfdb..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libkernel-ctl.la
-
-libkernel_ctl_la_SOURCES = \
-       kernel-ctl.cpp \
-       kernel-ctl.h \
-       kernel-ioctl.h
index 4d59bdf2992dbe4237a00b8f67ec1d68dead5dab..109e65327a96cbf7e527536a34e917f6a853972a 100644 (file)
 #define __USE_LINUX_IOCTL_DEFS
 #include <sys/ioctl.h>
 #include <string.h>
-#include <common/align.h>
-#include <common/macros.h>
-#include <common/compat/errno.h>
+#include <common/align.hpp>
+#include <common/macros.hpp>
+#include <common/compat/errno.hpp>
 #include <stdarg.h>
-#include <common/time.h>
+#include <common/time.hpp>
 
-#include "kernel-ctl.h"
-#include "kernel-ioctl.h"
+#include "kernel-ctl.hpp"
+#include "kernel-ioctl.hpp"
 
 #define LTTNG_IOCTL_CHECK(fildes, request, ...)                         \
        ({                                                              \
diff --git a/src/common/kernel-ctl/kernel-ctl.h b/src/common/kernel-ctl/kernel-ctl.h
deleted file mode 100644 (file)
index e6805a9..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_KERNEL_CTL_H
-#define _LTTNG_KERNEL_CTL_H
-
-#include <stdbool.h>
-
-#include <lttng/lttng.h>
-#include <common/lttng-kernel.h>
-#include <common/lttng-kernel-old.h>
-#include <common/sessiond-comm/sessiond-comm.h>        /* for struct lttng_filter_bytecode */
-
-int kernctl_create_session(int fd);
-int kernctl_open_metadata(int fd, struct lttng_channel_attr *chops);
-int kernctl_create_channel(int fd, struct lttng_channel_attr *chops);
-int kernctl_create_stream(int fd);
-int kernctl_create_event(int fd, struct lttng_kernel_abi_event *ev);
-int kernctl_add_context(int fd, struct lttng_kernel_abi_context *ctx);
-
-int kernctl_enable(int fd);
-int kernctl_disable(int fd);
-int kernctl_start_session(int fd);
-int kernctl_stop_session(int fd);
-
-int kernctl_create_event_notifier_group(int fd);
-
-/* Apply on event notifier_group file descriptor. */
-int kernctl_create_event_notifier_group_notification_fd(int fd);
-int kernctl_create_event_notifier_group_error_counter(int fd,
-               const struct lttng_kernel_abi_counter_conf *error_counter_conf);
-int kernctl_create_event_notifier(int fd,
-               const struct lttng_kernel_abi_event_notifier *event_notifier);
-
-int kernctl_counter_get_aggregate_value(int counter_fd,
-               struct lttng_kernel_abi_counter_aggregate *value);
-int kernctl_counter_clear(int counter_fd,
-               struct lttng_kernel_abi_counter_clear *clear);
-
-/* Apply on event file descriptor. */
-int kernctl_filter(int fd, const struct lttng_bytecode *filter);
-int kernctl_add_callsite(int fd, struct lttng_kernel_abi_event_callsite *callsite);
-int kernctl_capture(int fd, const struct lttng_bytecode *capture);
-
-int kernctl_tracepoint_list(int fd);
-int kernctl_syscall_list(int fd);
-int kernctl_tracer_version(int fd, struct lttng_kernel_abi_tracer_version *v);
-int kernctl_tracer_abi_version(int fd, struct lttng_kernel_abi_tracer_abi_version *v);
-int kernctl_wait_quiescent(int fd);
-
-/*
- * kernctl_syscall_mask - Get syscall mask associated to a channel file
- * descriptor.
- *
- * The parameter @syscall_mask should initially be either NULL or point
- * to memory allocated with malloc(3) or realloc(3). When the function
- * returns, it will point to a memory area of the size required for the
- * bitmask (using realloc(3) to resize the memory).
- *
- * It returns 0 if OK, -1 on error. In all cases (error and OK),
- * @syscall_mask should be freed by the caller with free(3).
- */
-int kernctl_syscall_mask(int fd, char **syscall_mask,
-               uint32_t *nr_bits);
-
-/* Process ID tracking can be applied to session file descriptor. */
-int kernctl_track_pid(int fd, int pid);
-int kernctl_untrack_pid(int fd, int pid);
-int kernctl_list_tracker_pids(int fd);
-
-int kernctl_track_id(int fd, enum lttng_process_attr process_attr, int id);
-int kernctl_untrack_id(int fd, enum lttng_process_attr process_attr, int id);
-int kernctl_list_tracker_ids(int fd, enum lttng_process_attr process_attr);
-
-int kernctl_session_regenerate_metadata(int fd);
-int kernctl_session_regenerate_statedump(int fd);
-int kernctl_session_set_name(int fd, const char *name);
-int kernctl_session_set_creation_time(int fd, time_t time);
-
-/* Buffer operations */
-
-/* For mmap mode, readable without "get" operation */
-int kernctl_get_mmap_len(int fd, unsigned long *len);
-int kernctl_get_max_subbuf_size(int fd, unsigned long *len);
-
-/*
- * For mmap mode, operate on the current packet (between get/put or
- * get_next/put_next).
- */
-int kernctl_get_mmap_read_offset(int fd, unsigned long *len);
-int kernctl_get_subbuf_size(int fd, unsigned long *len);
-int kernctl_get_padded_subbuf_size(int fd, unsigned long *len);
-
-int kernctl_get_next_subbuf(int fd);
-int kernctl_put_next_subbuf(int fd);
-
-/* snapshot */
-int kernctl_snapshot(int fd);
-int kernctl_snapshot_sample_positions(int fd);
-int kernctl_snapshot_get_consumed(int fd, unsigned long *pos);
-int kernctl_snapshot_get_produced(int fd, unsigned long *pos);
-int kernctl_get_subbuf(int fd, unsigned long *pos);
-int kernctl_put_subbuf(int fd);
-
-int kernctl_buffer_flush(int fd);
-int kernctl_buffer_flush_empty(int fd);
-int kernctl_buffer_clear(int fd);
-int kernctl_get_metadata_version(int fd, uint64_t *version);
-int kernctl_metadata_cache_dump(int fd);
-int kernctl_get_next_subbuf_metadata_check(int fd, bool *consistent);
-
-/* index */
-int kernctl_get_timestamp_begin(int fd, uint64_t *timestamp_begin);
-int kernctl_get_timestamp_end(int fd, uint64_t *timestamp_end);
-int kernctl_get_events_discarded(int fd, uint64_t *events_discarded);
-int kernctl_get_content_size(int fd, uint64_t *content_size);
-int kernctl_get_packet_size(int fd, uint64_t *packet_size);
-int kernctl_get_stream_id(int fd, uint64_t *stream_id);
-int kernctl_get_current_timestamp(int fd, uint64_t *ts);
-int kernctl_get_sequence_number(int fd, uint64_t *seq);
-int kernctl_get_instance_id(int fd, uint64_t *seq);
-
-#endif /* _LTTNG_KERNEL_CTL_H */
diff --git a/src/common/kernel-ctl/kernel-ctl.hpp b/src/common/kernel-ctl/kernel-ctl.hpp
new file mode 100644 (file)
index 0000000..2d5899d
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_KERNEL_CTL_H
+#define _LTTNG_KERNEL_CTL_H
+
+#include <stdbool.h>
+
+#include <lttng/lttng.h>
+#include <common/lttng-kernel.hpp>
+#include <common/lttng-kernel-old.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>      /* for struct lttng_filter_bytecode */
+
+int kernctl_create_session(int fd);
+int kernctl_open_metadata(int fd, struct lttng_channel_attr *chops);
+int kernctl_create_channel(int fd, struct lttng_channel_attr *chops);
+int kernctl_create_stream(int fd);
+int kernctl_create_event(int fd, struct lttng_kernel_abi_event *ev);
+int kernctl_add_context(int fd, struct lttng_kernel_abi_context *ctx);
+
+int kernctl_enable(int fd);
+int kernctl_disable(int fd);
+int kernctl_start_session(int fd);
+int kernctl_stop_session(int fd);
+
+int kernctl_create_event_notifier_group(int fd);
+
+/* Apply on event notifier_group file descriptor. */
+int kernctl_create_event_notifier_group_notification_fd(int fd);
+int kernctl_create_event_notifier_group_error_counter(int fd,
+               const struct lttng_kernel_abi_counter_conf *error_counter_conf);
+int kernctl_create_event_notifier(int fd,
+               const struct lttng_kernel_abi_event_notifier *event_notifier);
+
+int kernctl_counter_get_aggregate_value(int counter_fd,
+               struct lttng_kernel_abi_counter_aggregate *value);
+int kernctl_counter_clear(int counter_fd,
+               struct lttng_kernel_abi_counter_clear *clear);
+
+/* Apply on event file descriptor. */
+int kernctl_filter(int fd, const struct lttng_bytecode *filter);
+int kernctl_add_callsite(int fd, struct lttng_kernel_abi_event_callsite *callsite);
+int kernctl_capture(int fd, const struct lttng_bytecode *capture);
+
+int kernctl_tracepoint_list(int fd);
+int kernctl_syscall_list(int fd);
+int kernctl_tracer_version(int fd, struct lttng_kernel_abi_tracer_version *v);
+int kernctl_tracer_abi_version(int fd, struct lttng_kernel_abi_tracer_abi_version *v);
+int kernctl_wait_quiescent(int fd);
+
+/*
+ * kernctl_syscall_mask - Get syscall mask associated to a channel file
+ * descriptor.
+ *
+ * The parameter @syscall_mask should initially be either NULL or point
+ * to memory allocated with malloc(3) or realloc(3). When the function
+ * returns, it will point to a memory area of the size required for the
+ * bitmask (using realloc(3) to resize the memory).
+ *
+ * It returns 0 if OK, -1 on error. In all cases (error and OK),
+ * @syscall_mask should be freed by the caller with free(3).
+ */
+int kernctl_syscall_mask(int fd, char **syscall_mask,
+               uint32_t *nr_bits);
+
+/* Process ID tracking can be applied to session file descriptor. */
+int kernctl_track_pid(int fd, int pid);
+int kernctl_untrack_pid(int fd, int pid);
+int kernctl_list_tracker_pids(int fd);
+
+int kernctl_track_id(int fd, enum lttng_process_attr process_attr, int id);
+int kernctl_untrack_id(int fd, enum lttng_process_attr process_attr, int id);
+int kernctl_list_tracker_ids(int fd, enum lttng_process_attr process_attr);
+
+int kernctl_session_regenerate_metadata(int fd);
+int kernctl_session_regenerate_statedump(int fd);
+int kernctl_session_set_name(int fd, const char *name);
+int kernctl_session_set_creation_time(int fd, time_t time);
+
+/* Buffer operations */
+
+/* For mmap mode, readable without "get" operation */
+int kernctl_get_mmap_len(int fd, unsigned long *len);
+int kernctl_get_max_subbuf_size(int fd, unsigned long *len);
+
+/*
+ * For mmap mode, operate on the current packet (between get/put or
+ * get_next/put_next).
+ */
+int kernctl_get_mmap_read_offset(int fd, unsigned long *len);
+int kernctl_get_subbuf_size(int fd, unsigned long *len);
+int kernctl_get_padded_subbuf_size(int fd, unsigned long *len);
+
+int kernctl_get_next_subbuf(int fd);
+int kernctl_put_next_subbuf(int fd);
+
+/* snapshot */
+int kernctl_snapshot(int fd);
+int kernctl_snapshot_sample_positions(int fd);
+int kernctl_snapshot_get_consumed(int fd, unsigned long *pos);
+int kernctl_snapshot_get_produced(int fd, unsigned long *pos);
+int kernctl_get_subbuf(int fd, unsigned long *pos);
+int kernctl_put_subbuf(int fd);
+
+int kernctl_buffer_flush(int fd);
+int kernctl_buffer_flush_empty(int fd);
+int kernctl_buffer_clear(int fd);
+int kernctl_get_metadata_version(int fd, uint64_t *version);
+int kernctl_metadata_cache_dump(int fd);
+int kernctl_get_next_subbuf_metadata_check(int fd, bool *consistent);
+
+/* index */
+int kernctl_get_timestamp_begin(int fd, uint64_t *timestamp_begin);
+int kernctl_get_timestamp_end(int fd, uint64_t *timestamp_end);
+int kernctl_get_events_discarded(int fd, uint64_t *events_discarded);
+int kernctl_get_content_size(int fd, uint64_t *content_size);
+int kernctl_get_packet_size(int fd, uint64_t *packet_size);
+int kernctl_get_stream_id(int fd, uint64_t *stream_id);
+int kernctl_get_current_timestamp(int fd, uint64_t *ts);
+int kernctl_get_sequence_number(int fd, uint64_t *seq);
+int kernctl_get_instance_id(int fd, uint64_t *seq);
+
+#endif /* _LTTNG_KERNEL_CTL_H */
diff --git a/src/common/kernel-ctl/kernel-ioctl.h b/src/common/kernel-ctl/kernel-ioctl.h
deleted file mode 100644 (file)
index b9af57a..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_KERNEL_IOCTL_H
-#define _LTT_KERNEL_IOCTL_H
-
-#define LTTNG_KERNEL_ABI_MAJOR_VERSION         2
-#define LTTNG_KERNEL_ABI_MINOR_VERSION         6
-
-/* Get a snapshot of the current ring buffer producer and consumer positions */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_SNAPSHOT                _IO(0xF6, 0x00)
-/* Get the consumer position (iteration start) */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_SNAPSHOT_GET_CONSUMED   _IOR(0xF6, 0x01, unsigned long)
-/* Get the producer position (iteration end) */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_SNAPSHOT_GET_PRODUCED   _IOR(0xF6, 0x02, unsigned long)
-/* Get exclusive read access to the specified sub-buffer position */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_SUBBUF              _IOW(0xF6, 0x03, unsigned long)
-/* Release exclusive sub-buffer access */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_PUT_SUBBUF              _IO(0xF6, 0x04)
-
-/* Get exclusive read access to the next sub-buffer that can be read. */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_NEXT_SUBBUF         _IO(0xF6, 0x05)
-/* Release exclusive sub-buffer access, move consumer forward. */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_PUT_NEXT_SUBBUF         _IO(0xF6, 0x06)
-/* returns the size of the current sub-buffer, without padding (for mmap). */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_SUBBUF_SIZE         _IOR(0xF6, 0x07, unsigned long)
-/* returns the size of the current sub-buffer, with padding (for splice). */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_PADDED_SUBBUF_SIZE  _IOR(0xF6, 0x08, unsigned long)
-/* returns the maximum size for sub-buffers. */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_MAX_SUBBUF_SIZE     _IOR(0xF6, 0x09, unsigned long)
-/* returns the length to mmap. */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_MMAP_LEN            _IOR(0xF6, 0x0A, unsigned long)
-/* returns the offset of the subbuffer belonging to the mmap reader. */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_MMAP_READ_OFFSET    _IOR(0xF6, 0x0B, unsigned long)
-/* Flush the current sub-buffer, if non-empty. */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_FLUSH                   _IO(0xF6, 0x0C)
-/* Get the current version of the metadata cache (after a get_next). */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_METADATA_VERSION    _IOR(0xF6, 0x0D, uint64_t)
-/*
- * Get a snapshot of the current ring buffer producer and consumer positions,
- * regardless of whether or not the two positions are contained within the same
- * sub-buffer.
- */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_SNAPSHOT_SAMPLE_POSITIONS _IO(0xF6, 0x0E)
-/* Flush the current sub-buffer, even if empty. */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_FLUSH_EMPTY                       _IO(0xF6, 0x0F)
-/*
- * Reset the position of what has been consumed from the metadata cache to 0
- * so it can be read again.
- */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_METADATA_CACHE_DUMP               _IO(0xF6, 0x10)
-/* Clear ring buffer content */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_CLEAR                               _IO(0xF6, 0x11)
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK _IOR(0xF6, 0x12, uint32_t)
-
-/* returns the timestamp begin of the current sub-buffer */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_TIMESTAMP_BEGIN     _IOR(0xF6, 0x20, uint64_t)
-/* returns the timestamp end of the current sub-buffer */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_TIMESTAMP_END       _IOR(0xF6, 0x21, uint64_t)
-/* returns the number of events discarded */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_EVENTS_DISCARDED    _IOR(0xF6, 0x22, uint64_t)
-/* returns the packet payload size */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_CONTENT_SIZE        _IOR(0xF6, 0x23, uint64_t)
-/* returns the actual packet size */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_PACKET_SIZE         _IOR(0xF6, 0x24, uint64_t)
-/* returns the stream id */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_STREAM_ID           _IOR(0xF6, 0x25, uint64_t)
-/* returns the current timestamp */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_CURRENT_TIMESTAMP   _IOR(0xF6, 0x26, uint64_t)
-/* returns the packet sequence number */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_SEQ_NUM             _IOR(0xF6, 0x27, uint64_t)
-/* returns the stream instance id */
-#define LTTNG_KERNEL_ABI_RING_BUFFER_INSTANCE_ID             _IOR(0xF6, 0x28, uint64_t)
-
-/* Old ABI (without support for 32/64 bits compat) */
-/* LTTng file descriptor ioctl */
-#define LTTNG_KERNEL_ABI_OLD_SESSION                _IO(0xF6, 0x40)
-#define LTTNG_KERNEL_ABI_OLD_TRACER_VERSION         \
-               _IOR(0xF6, 0x41, struct lttng_kernel_abi_old_tracer_version)
-#define LTTNG_KERNEL_ABI_OLD_TRACEPOINT_LIST        _IO(0xF6, 0x42)
-#define LTTNG_KERNEL_ABI_OLD_WAIT_QUIESCENT         _IO(0xF6, 0x43)
-
-/* Session FD ioctl */
-#define LTTNG_KERNEL_ABI_OLD_METADATA               \
-               _IOW(0xF6, 0x50, struct lttng_kernel_abi_old_channel)
-#define LTTNG_KERNEL_ABI_OLD_CHANNEL                \
-               _IOW(0xF6, 0x51, struct lttng_kernel_abi_old_channel)
-#define LTTNG_KERNEL_ABI_OLD_SESSION_START          _IO(0xF6, 0x52)
-#define LTTNG_KERNEL_ABI_OLD_SESSION_STOP           _IO(0xF6, 0x53)
-
-/* Channel FD ioctl */
-#define LTTNG_KERNEL_ABI_OLD_STREAM                 _IO(0xF6, 0x60)
-#define LTTNG_KERNEL_ABI_OLD_EVENT                  \
-               _IOW(0xF6, 0x61, struct lttng_kernel_abi_old_event)
-
-/* Event and Channel FD ioctl */
-#define LTTNG_KERNEL_ABI_OLD_CONTEXT                \
-               _IOW(0xF6, 0x70, struct lttng_kernel_abi_old_context)
-
-/* Event, Channel and Session ioctl */
-#define LTTNG_KERNEL_ABI_OLD_ENABLE                 _IO(0xF6, 0x80)
-#define LTTNG_KERNEL_ABI_OLD_DISABLE                _IO(0xF6, 0x81)
-
-
-/* Current ABI (with suport for 32/64 bits compat) */
-/* LTTng file descriptor ioctl */
-#define LTTNG_KERNEL_ABI_SESSION               _IO(0xF6, 0x45)
-#define LTTNG_KERNEL_ABI_TRACER_VERSION                \
-       _IOR(0xF6, 0x46, struct lttng_kernel_abi_tracer_version)
-#define LTTNG_KERNEL_ABI_TRACEPOINT_LIST       _IO(0xF6, 0x47)
-#define LTTNG_KERNEL_ABI_WAIT_QUIESCENT                _IO(0xF6, 0x48)
-#define LTTNG_KERNEL_ABI_SYSCALL_LIST          _IO(0xF6, 0x4A)
-#define LTTNG_KERNEL_ABI_TRACER_ABI_VERSION            \
-       _IOR(0xF6, 0x4B, struct lttng_kernel_abi_tracer_abi_version)
-#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_GROUP_CREATE \
-       _IO(0xF6, 0x4C)
-
-/* Session FD ioctl */
-#define LTTNG_KERNEL_ABI_METADATA                      \
-       _IOW(0xF6, 0x54, struct lttng_kernel_abi_channel)
-#define LTTNG_KERNEL_ABI_CHANNEL                       \
-       _IOW(0xF6, 0x55, struct lttng_kernel_abi_channel)
-#define LTTNG_KERNEL_ABI_SESSION_START         _IO(0xF6, 0x56)
-#define LTTNG_KERNEL_ABI_SESSION_STOP          _IO(0xF6, 0x57)
-#define LTTNG_KERNEL_ABI_SESSION_TRACK_PID             \
-       _IOW(0xF6, 0x58, int32_t)
-#define LTTNG_KERNEL_ABI_SESSION_UNTRACK_PID   \
-       _IOW(0xF6, 0x59, int32_t)
-/*
- * ioctl 0x58 and 0x59 are duplicated here. It works, since _IOR vs _IO
- * are generating two different ioctl numbers, but this was not done on
- * purpose. We should generally try to avoid those duplications.
- */
-#define LTTNG_KERNEL_ABI_SESSION_LIST_TRACKER_PIDS  _IO(0xF6, 0x58)
-#define LTTNG_KERNEL_ABI_SESSION_METADATA_REGEN            _IO(0xF6, 0x59)
-/* 0x5A and 0x5B are reserved for a future ABI-breaking cleanup. */
-#define LTTNG_KERNEL_ABI_SESSION_STATEDUMP         _IO(0xF6, 0x5C)
-#define LTTNG_KERNEL_ABI_SESSION_SET_NAME              \
-       _IOW(0xF6, 0x5D, struct lttng_kernel_abi_session_name)
-#define LTTNG_KERNEL_ABI_SESSION_SET_CREATION_TIME             \
-       _IOW(0xF6, 0x5E, struct lttng_kernel_abi_session_creation_time)
-
-/* Channel FD ioctl */
-#define LTTNG_KERNEL_ABI_STREAM                        _IO(0xF6, 0x62)
-#define LTTNG_KERNEL_ABI_EVENT                 \
-       _IOW(0xF6, 0x63, struct lttng_kernel_abi_event)
-#define LTTNG_KERNEL_ABI_SYSCALL_MASK          \
-       _IOWR(0xF6, 0x64, struct lttng_kernel_abi_syscall_mask)
-
-/* Event and Channel FD ioctl */
-#define LTTNG_KERNEL_ABI_CONTEXT                       \
-       _IOW(0xF6, 0x71, struct lttng_kernel_abi_context)
-
-/* Event, event notifier, Channel and Session ioctl */
-#define LTTNG_KERNEL_ABI_ENABLE                        _IO(0xF6, 0x82)
-#define LTTNG_KERNEL_ABI_DISABLE               _IO(0xF6, 0x83)
-
-/* Event notifier group ioctl */
-#define LTTNG_KERNEL_ABI_COUNTER                       \
-       _IOW(0xF6, 0x84, struct lttng_kernel_abi_counter_conf)
-
-/* Event and event notifier FD ioctl */
-#define LTTNG_KERNEL_ABI_FILTER                        _IO(0xF6, 0x90)
-#define LTTNG_KERNEL_ABI_ADD_CALLSITE          _IO(0xF6, 0x91)
-
-/* Session FD ioctl (continued) */
-#define LTTNG_KERNEL_ABI_SESSION_LIST_TRACKER_IDS      \
-       _IOW(0xF6, 0xA0, struct lttng_kernel_abi_tracker_args)
-#define LTTNG_KERNEL_ABI_SESSION_TRACK_ID              \
-       _IOW(0xF6, 0xA1, struct lttng_kernel_abi_tracker_args)
-#define LTTNG_KERNEL_ABI_SESSION_UNTRACK_ID            \
-       _IOW(0xF6, 0xA2, struct lttng_kernel_abi_tracker_args)
-
-/* Event notifier group file descriptor ioctl */
-#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_CREATE                 \
-       _IOW(0xF6, 0xB0, struct lttng_kernel_abi_event_notifier)
-#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_GROUP_NOTIFICATION_FD  \
-       _IO(0xF6, 0xB1)
-
-/* Event notifier file descriptor ioctl */
-#define LTTNG_KERNEL_ABI_CAPTURE               _IO(0xF6, 0xB8)
-
-/* Counter file descriptor ioctl */
-#define LTTNG_KERNEL_ABI_COUNTER_READ          \
-       IOWR(0xF6, 0xC0, struct lttng_kernel_abi_counter_read)
-#define LTTNG_KERNEL_ABI_COUNTER_AGGREGATE             \
-       _IOWR(0xF6, 0xC1, struct lttng_kernel_abi_counter_aggregate)
-#define LTTNG_KERNEL_ABI_COUNTER_CLEAR         \
-       _IOW(0xF6, 0xC2, struct lttng_kernel_abi_counter_clear)
-
-/*
-  * Those ioctl numbers use the wrong direction, but are kept for ABI backward
-  * compatibility.
-  */
- #define LTTNG_KERNEL_ABI_OLD_SESSION_SET_NAME        \
-     _IOR(0xF6, 0x5D, struct lttng_kernel_abi_session_name)
- #define LTTNG_KERNEL_ABI_OLD_SESSION_SET_CREATION_TIME    \
-     _IOR(0xF6, 0x5E, struct lttng_kernel_abi_session_creation_time)
- #define LTTNG_KERNEL_ABI_OLD_SESSION_TRACK_PID        \
-     _IOW(0xF6, 0x58, int32_t)
- #define LTTNG_KERNEL_ABI_OLD_SESSION_UNTRACK_PID    \
-     _IOW(0xF6, 0x59, int32_t)
- #define LTTNG_KERNEL_ABI_OLD_SESSION_LIST_TRACKER_IDS    \
-     _IOR(0xF6, 0xA0, struct lttng_kernel_abi_tracker_args)
- #define LTTNG_KERNEL_ABI_OLD_SESSION_TRACK_ID        \
-     _IOR(0xF6, 0xA1, struct lttng_kernel_abi_tracker_args)
- #define LTTNG_KERNEL_ABI_OLD_SESSION_UNTRACK_ID        \
-     _IOR(0xF6, 0xA2, struct lttng_kernel_abi_tracker_args)
-
-#endif /* _LTT_KERNEL_IOCTL_H */
diff --git a/src/common/kernel-ctl/kernel-ioctl.hpp b/src/common/kernel-ctl/kernel-ioctl.hpp
new file mode 100644 (file)
index 0000000..b9af57a
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_KERNEL_IOCTL_H
+#define _LTT_KERNEL_IOCTL_H
+
+#define LTTNG_KERNEL_ABI_MAJOR_VERSION         2
+#define LTTNG_KERNEL_ABI_MINOR_VERSION         6
+
+/* Get a snapshot of the current ring buffer producer and consumer positions */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_SNAPSHOT                _IO(0xF6, 0x00)
+/* Get the consumer position (iteration start) */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_SNAPSHOT_GET_CONSUMED   _IOR(0xF6, 0x01, unsigned long)
+/* Get the producer position (iteration end) */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_SNAPSHOT_GET_PRODUCED   _IOR(0xF6, 0x02, unsigned long)
+/* Get exclusive read access to the specified sub-buffer position */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_SUBBUF              _IOW(0xF6, 0x03, unsigned long)
+/* Release exclusive sub-buffer access */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_PUT_SUBBUF              _IO(0xF6, 0x04)
+
+/* Get exclusive read access to the next sub-buffer that can be read. */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_NEXT_SUBBUF         _IO(0xF6, 0x05)
+/* Release exclusive sub-buffer access, move consumer forward. */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_PUT_NEXT_SUBBUF         _IO(0xF6, 0x06)
+/* returns the size of the current sub-buffer, without padding (for mmap). */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_SUBBUF_SIZE         _IOR(0xF6, 0x07, unsigned long)
+/* returns the size of the current sub-buffer, with padding (for splice). */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_PADDED_SUBBUF_SIZE  _IOR(0xF6, 0x08, unsigned long)
+/* returns the maximum size for sub-buffers. */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_MAX_SUBBUF_SIZE     _IOR(0xF6, 0x09, unsigned long)
+/* returns the length to mmap. */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_MMAP_LEN            _IOR(0xF6, 0x0A, unsigned long)
+/* returns the offset of the subbuffer belonging to the mmap reader. */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_MMAP_READ_OFFSET    _IOR(0xF6, 0x0B, unsigned long)
+/* Flush the current sub-buffer, if non-empty. */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_FLUSH                   _IO(0xF6, 0x0C)
+/* Get the current version of the metadata cache (after a get_next). */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_METADATA_VERSION    _IOR(0xF6, 0x0D, uint64_t)
+/*
+ * Get a snapshot of the current ring buffer producer and consumer positions,
+ * regardless of whether or not the two positions are contained within the same
+ * sub-buffer.
+ */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_SNAPSHOT_SAMPLE_POSITIONS _IO(0xF6, 0x0E)
+/* Flush the current sub-buffer, even if empty. */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_FLUSH_EMPTY                       _IO(0xF6, 0x0F)
+/*
+ * Reset the position of what has been consumed from the metadata cache to 0
+ * so it can be read again.
+ */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_METADATA_CACHE_DUMP               _IO(0xF6, 0x10)
+/* Clear ring buffer content */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_CLEAR                               _IO(0xF6, 0x11)
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_NEXT_SUBBUF_METADATA_CHECK _IOR(0xF6, 0x12, uint32_t)
+
+/* returns the timestamp begin of the current sub-buffer */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_TIMESTAMP_BEGIN     _IOR(0xF6, 0x20, uint64_t)
+/* returns the timestamp end of the current sub-buffer */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_TIMESTAMP_END       _IOR(0xF6, 0x21, uint64_t)
+/* returns the number of events discarded */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_EVENTS_DISCARDED    _IOR(0xF6, 0x22, uint64_t)
+/* returns the packet payload size */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_CONTENT_SIZE        _IOR(0xF6, 0x23, uint64_t)
+/* returns the actual packet size */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_PACKET_SIZE         _IOR(0xF6, 0x24, uint64_t)
+/* returns the stream id */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_STREAM_ID           _IOR(0xF6, 0x25, uint64_t)
+/* returns the current timestamp */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_CURRENT_TIMESTAMP   _IOR(0xF6, 0x26, uint64_t)
+/* returns the packet sequence number */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_GET_SEQ_NUM             _IOR(0xF6, 0x27, uint64_t)
+/* returns the stream instance id */
+#define LTTNG_KERNEL_ABI_RING_BUFFER_INSTANCE_ID             _IOR(0xF6, 0x28, uint64_t)
+
+/* Old ABI (without support for 32/64 bits compat) */
+/* LTTng file descriptor ioctl */
+#define LTTNG_KERNEL_ABI_OLD_SESSION                _IO(0xF6, 0x40)
+#define LTTNG_KERNEL_ABI_OLD_TRACER_VERSION         \
+               _IOR(0xF6, 0x41, struct lttng_kernel_abi_old_tracer_version)
+#define LTTNG_KERNEL_ABI_OLD_TRACEPOINT_LIST        _IO(0xF6, 0x42)
+#define LTTNG_KERNEL_ABI_OLD_WAIT_QUIESCENT         _IO(0xF6, 0x43)
+
+/* Session FD ioctl */
+#define LTTNG_KERNEL_ABI_OLD_METADATA               \
+               _IOW(0xF6, 0x50, struct lttng_kernel_abi_old_channel)
+#define LTTNG_KERNEL_ABI_OLD_CHANNEL                \
+               _IOW(0xF6, 0x51, struct lttng_kernel_abi_old_channel)
+#define LTTNG_KERNEL_ABI_OLD_SESSION_START          _IO(0xF6, 0x52)
+#define LTTNG_KERNEL_ABI_OLD_SESSION_STOP           _IO(0xF6, 0x53)
+
+/* Channel FD ioctl */
+#define LTTNG_KERNEL_ABI_OLD_STREAM                 _IO(0xF6, 0x60)
+#define LTTNG_KERNEL_ABI_OLD_EVENT                  \
+               _IOW(0xF6, 0x61, struct lttng_kernel_abi_old_event)
+
+/* Event and Channel FD ioctl */
+#define LTTNG_KERNEL_ABI_OLD_CONTEXT                \
+               _IOW(0xF6, 0x70, struct lttng_kernel_abi_old_context)
+
+/* Event, Channel and Session ioctl */
+#define LTTNG_KERNEL_ABI_OLD_ENABLE                 _IO(0xF6, 0x80)
+#define LTTNG_KERNEL_ABI_OLD_DISABLE                _IO(0xF6, 0x81)
+
+
+/* Current ABI (with suport for 32/64 bits compat) */
+/* LTTng file descriptor ioctl */
+#define LTTNG_KERNEL_ABI_SESSION               _IO(0xF6, 0x45)
+#define LTTNG_KERNEL_ABI_TRACER_VERSION                \
+       _IOR(0xF6, 0x46, struct lttng_kernel_abi_tracer_version)
+#define LTTNG_KERNEL_ABI_TRACEPOINT_LIST       _IO(0xF6, 0x47)
+#define LTTNG_KERNEL_ABI_WAIT_QUIESCENT                _IO(0xF6, 0x48)
+#define LTTNG_KERNEL_ABI_SYSCALL_LIST          _IO(0xF6, 0x4A)
+#define LTTNG_KERNEL_ABI_TRACER_ABI_VERSION            \
+       _IOR(0xF6, 0x4B, struct lttng_kernel_abi_tracer_abi_version)
+#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_GROUP_CREATE \
+       _IO(0xF6, 0x4C)
+
+/* Session FD ioctl */
+#define LTTNG_KERNEL_ABI_METADATA                      \
+       _IOW(0xF6, 0x54, struct lttng_kernel_abi_channel)
+#define LTTNG_KERNEL_ABI_CHANNEL                       \
+       _IOW(0xF6, 0x55, struct lttng_kernel_abi_channel)
+#define LTTNG_KERNEL_ABI_SESSION_START         _IO(0xF6, 0x56)
+#define LTTNG_KERNEL_ABI_SESSION_STOP          _IO(0xF6, 0x57)
+#define LTTNG_KERNEL_ABI_SESSION_TRACK_PID             \
+       _IOW(0xF6, 0x58, int32_t)
+#define LTTNG_KERNEL_ABI_SESSION_UNTRACK_PID   \
+       _IOW(0xF6, 0x59, int32_t)
+/*
+ * ioctl 0x58 and 0x59 are duplicated here. It works, since _IOR vs _IO
+ * are generating two different ioctl numbers, but this was not done on
+ * purpose. We should generally try to avoid those duplications.
+ */
+#define LTTNG_KERNEL_ABI_SESSION_LIST_TRACKER_PIDS  _IO(0xF6, 0x58)
+#define LTTNG_KERNEL_ABI_SESSION_METADATA_REGEN            _IO(0xF6, 0x59)
+/* 0x5A and 0x5B are reserved for a future ABI-breaking cleanup. */
+#define LTTNG_KERNEL_ABI_SESSION_STATEDUMP         _IO(0xF6, 0x5C)
+#define LTTNG_KERNEL_ABI_SESSION_SET_NAME              \
+       _IOW(0xF6, 0x5D, struct lttng_kernel_abi_session_name)
+#define LTTNG_KERNEL_ABI_SESSION_SET_CREATION_TIME             \
+       _IOW(0xF6, 0x5E, struct lttng_kernel_abi_session_creation_time)
+
+/* Channel FD ioctl */
+#define LTTNG_KERNEL_ABI_STREAM                        _IO(0xF6, 0x62)
+#define LTTNG_KERNEL_ABI_EVENT                 \
+       _IOW(0xF6, 0x63, struct lttng_kernel_abi_event)
+#define LTTNG_KERNEL_ABI_SYSCALL_MASK          \
+       _IOWR(0xF6, 0x64, struct lttng_kernel_abi_syscall_mask)
+
+/* Event and Channel FD ioctl */
+#define LTTNG_KERNEL_ABI_CONTEXT                       \
+       _IOW(0xF6, 0x71, struct lttng_kernel_abi_context)
+
+/* Event, event notifier, Channel and Session ioctl */
+#define LTTNG_KERNEL_ABI_ENABLE                        _IO(0xF6, 0x82)
+#define LTTNG_KERNEL_ABI_DISABLE               _IO(0xF6, 0x83)
+
+/* Event notifier group ioctl */
+#define LTTNG_KERNEL_ABI_COUNTER                       \
+       _IOW(0xF6, 0x84, struct lttng_kernel_abi_counter_conf)
+
+/* Event and event notifier FD ioctl */
+#define LTTNG_KERNEL_ABI_FILTER                        _IO(0xF6, 0x90)
+#define LTTNG_KERNEL_ABI_ADD_CALLSITE          _IO(0xF6, 0x91)
+
+/* Session FD ioctl (continued) */
+#define LTTNG_KERNEL_ABI_SESSION_LIST_TRACKER_IDS      \
+       _IOW(0xF6, 0xA0, struct lttng_kernel_abi_tracker_args)
+#define LTTNG_KERNEL_ABI_SESSION_TRACK_ID              \
+       _IOW(0xF6, 0xA1, struct lttng_kernel_abi_tracker_args)
+#define LTTNG_KERNEL_ABI_SESSION_UNTRACK_ID            \
+       _IOW(0xF6, 0xA2, struct lttng_kernel_abi_tracker_args)
+
+/* Event notifier group file descriptor ioctl */
+#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_CREATE                 \
+       _IOW(0xF6, 0xB0, struct lttng_kernel_abi_event_notifier)
+#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_GROUP_NOTIFICATION_FD  \
+       _IO(0xF6, 0xB1)
+
+/* Event notifier file descriptor ioctl */
+#define LTTNG_KERNEL_ABI_CAPTURE               _IO(0xF6, 0xB8)
+
+/* Counter file descriptor ioctl */
+#define LTTNG_KERNEL_ABI_COUNTER_READ          \
+       IOWR(0xF6, 0xC0, struct lttng_kernel_abi_counter_read)
+#define LTTNG_KERNEL_ABI_COUNTER_AGGREGATE             \
+       _IOWR(0xF6, 0xC1, struct lttng_kernel_abi_counter_aggregate)
+#define LTTNG_KERNEL_ABI_COUNTER_CLEAR         \
+       _IOW(0xF6, 0xC2, struct lttng_kernel_abi_counter_clear)
+
+/*
+  * Those ioctl numbers use the wrong direction, but are kept for ABI backward
+  * compatibility.
+  */
+ #define LTTNG_KERNEL_ABI_OLD_SESSION_SET_NAME        \
+     _IOR(0xF6, 0x5D, struct lttng_kernel_abi_session_name)
+ #define LTTNG_KERNEL_ABI_OLD_SESSION_SET_CREATION_TIME    \
+     _IOR(0xF6, 0x5E, struct lttng_kernel_abi_session_creation_time)
+ #define LTTNG_KERNEL_ABI_OLD_SESSION_TRACK_PID        \
+     _IOW(0xF6, 0x58, int32_t)
+ #define LTTNG_KERNEL_ABI_OLD_SESSION_UNTRACK_PID    \
+     _IOW(0xF6, 0x59, int32_t)
+ #define LTTNG_KERNEL_ABI_OLD_SESSION_LIST_TRACKER_IDS    \
+     _IOR(0xF6, 0xA0, struct lttng_kernel_abi_tracker_args)
+ #define LTTNG_KERNEL_ABI_OLD_SESSION_TRACK_ID        \
+     _IOR(0xF6, 0xA1, struct lttng_kernel_abi_tracker_args)
+ #define LTTNG_KERNEL_ABI_OLD_SESSION_UNTRACK_ID        \
+     _IOR(0xF6, 0xA2, struct lttng_kernel_abi_tracker_args)
+
+#endif /* _LTT_KERNEL_IOCTL_H */
index a05b451c38dc406a68b4c5631841aaf649db96c8..979ca73111dc161b82cc4e6b8872ea5f9f34853c 100644 (file)
@@ -6,16 +6,16 @@
  */
 
 #include "lttng/lttng-error.h"
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
 #include <fcntl.h>
 #include <lttng/constant.h>
-#include <lttng/kernel-probe-internal.h>
+#include <lttng/kernel-probe-internal.hpp>
 #include <lttng/kernel-probe.h>
 #include <sys/stat.h>
 #include <sys/types.h>
index 80c4b4d554dff7fb1f354497040c2c20f40d1259..7e6ea79b0aac8baa6082ff5f06869e7771bac670 100644 (file)
@@ -5,10 +5,10 @@
  *
  */
 
-#include <lttng/location-internal.h>
-#include <common/macros.h>
+#include <lttng/location-internal.hpp>
+#include <common/macros.hpp>
 #include <stdlib.h>
-#include <common/error.h>
+#include <common/error.hpp>
 
 static
 struct lttng_trace_archive_location *lttng_trace_archive_location_create(
index e891222e0136842b6a1e86c8b922e20568067902..766e8b25becb60296b7afb750108c48098dfbda1 100644 (file)
@@ -5,13 +5,13 @@
  *
  */
 
-#include <common/dynamic-buffer.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <lttng/log-level-rule-internal.h>
+#include <common/dynamic-buffer.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <lttng/log-level-rule-internal.hpp>
 #include <lttng/log-level-rule.h>
 #include <stdbool.h>
 #include <stdlib.h>
index 992410a883d8d4ffa96636f2db612c3f818e9716..60cc4e248786d2acf03c10d25d39f3a96555bdd1 100644 (file)
@@ -8,11 +8,11 @@
  */
 
 #include <algorithm>
-#include <common/compat/endian.h>
-#include <common/error.h>
-#include <common/lttng-elf.h>
-#include <common/macros.h>
-#include <common/readwrite.h>
+#include <common/compat/endian.hpp>
+#include <common/error.hpp>
+#include <common/lttng-elf.hpp>
+#include <common/macros.hpp>
+#include <common/readwrite.hpp>
 #include <fcntl.h>
 #include <stdbool.h>
 #include <stdint.h>
diff --git a/src/common/lttng-elf.h b/src/common/lttng-elf.h
deleted file mode 100644 (file)
index 41dd496..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _LTTNG_ELF_H
-#define _LTTNG_ELF_H
-/*
- * Copyright (C) 2017 Francis Deslauriers <francis.deslauriers@efficios.com>
- * Copyright (C) 2017 Erica Bugden <erica.bugden@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-or-later
- *
- */
-
-#include <lttng/lttng-export.h>
-
-extern "C" LTTNG_EXPORT
-int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset);
-
-extern "C" LTTNG_EXPORT
-int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name,
-               const char *probe_name, uint64_t **offsets, uint32_t *nb_probe);
-
-#endif /* _LTTNG_ELF_H */
diff --git a/src/common/lttng-elf.hpp b/src/common/lttng-elf.hpp
new file mode 100644 (file)
index 0000000..41dd496
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _LTTNG_ELF_H
+#define _LTTNG_ELF_H
+/*
+ * Copyright (C) 2017 Francis Deslauriers <francis.deslauriers@efficios.com>
+ * Copyright (C) 2017 Erica Bugden <erica.bugden@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ */
+
+#include <lttng/lttng-export.h>
+
+extern "C" LTTNG_EXPORT
+int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset);
+
+extern "C" LTTNG_EXPORT
+int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name,
+               const char *probe_name, uint64_t **offsets, uint32_t *nb_probe);
+
+#endif /* _LTTNG_ELF_H */
diff --git a/src/common/lttng-kernel-old.h b/src/common/lttng-kernel-old.h
deleted file mode 100644 (file)
index 14f9cb4..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_KERNEL_OLD_H
-#define _LTTNG_KERNEL_OLD_H
-
-#include <stdint.h>
-#include <common/lttng-kernel.h>
-
-/*
- * LTTng DebugFS ABI structures.
- *
- * This is the kernel ABI copied from lttng-modules tree.
- */
-
-/* Perf counter attributes */
-struct lttng_kernel_abi_old_perf_counter_ctx {
-       uint32_t type;
-       uint64_t config;
-       char name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-};
-
-/* Event/Channel context */
-#define LTTNG_KERNEL_ABI_OLD_CONTEXT_PADDING1  16
-#define LTTNG_KERNEL_ABI_OLD_CONTEXT_PADDING2  LTTNG_KERNEL_ABI_SYM_NAME_LEN + 32
-struct lttng_kernel_abi_old_context {
-       enum lttng_kernel_abi_context_type ctx;
-       char padding[LTTNG_KERNEL_ABI_OLD_CONTEXT_PADDING1];
-
-       union {
-               struct lttng_kernel_abi_old_perf_counter_ctx perf_counter;
-               char padding[LTTNG_KERNEL_ABI_OLD_CONTEXT_PADDING2];
-       } u;
-};
-
-struct lttng_kernel_abi_old_kretprobe {
-       uint64_t addr;
-
-       uint64_t offset;
-       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-};
-
-/*
- * Either addr is used, or symbol_name and offset.
- */
-struct lttng_kernel_abi_old_kprobe {
-       uint64_t addr;
-
-       uint64_t offset;
-       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-};
-
-/* Function tracer */
-struct lttng_kernel_abi_old_function {
-       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-};
-
-#define LTTNG_KERNEL_ABI_OLD_EVENT_PADDING1    16
-#define LTTNG_KERNEL_ABI_OLD_EVENT_PADDING2    LTTNG_KERNEL_ABI_SYM_NAME_LEN + 32
-struct lttng_kernel_abi_old_event {
-       char name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-       enum lttng_kernel_abi_instrumentation instrumentation;
-       char padding[LTTNG_KERNEL_ABI_OLD_EVENT_PADDING1];
-
-       /* Per instrumentation type configuration */
-       union {
-               struct lttng_kernel_abi_old_kretprobe kretprobe;
-               struct lttng_kernel_abi_old_kprobe kprobe;
-               struct lttng_kernel_abi_old_function ftrace;
-               char padding[LTTNG_KERNEL_ABI_OLD_EVENT_PADDING2];
-       } u;
-};
-
-struct lttng_kernel_abi_old_tracer_version {
-       uint32_t major;
-       uint32_t minor;
-       uint32_t patchlevel;
-};
-
-/*
- * kernel channel
- */
-#define LTTNG_KERNEL_ABI_OLD_CHANNEL_PADDING1 LTTNG_SYMBOL_NAME_LEN + 32
-struct lttng_kernel_abi_old_channel {
-       int overwrite;                      /* 1: overwrite, 0: discard */
-       uint64_t subbuf_size;               /* bytes */
-       uint64_t num_subbuf;                /* power of 2 */
-       unsigned int switch_timer_interval; /* usec */
-       unsigned int read_timer_interval;   /* usec */
-       enum lttng_event_output output;     /* splice, mmap */
-
-       char padding[LTTNG_KERNEL_ABI_OLD_CHANNEL_PADDING1];
-};
-
-#endif /* _LTTNG_KERNEL_OLD_H */
diff --git a/src/common/lttng-kernel-old.hpp b/src/common/lttng-kernel-old.hpp
new file mode 100644 (file)
index 0000000..d16ae5d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_KERNEL_OLD_H
+#define _LTTNG_KERNEL_OLD_H
+
+#include <stdint.h>
+#include <common/lttng-kernel.hpp>
+
+/*
+ * LTTng DebugFS ABI structures.
+ *
+ * This is the kernel ABI copied from lttng-modules tree.
+ */
+
+/* Perf counter attributes */
+struct lttng_kernel_abi_old_perf_counter_ctx {
+       uint32_t type;
+       uint64_t config;
+       char name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+};
+
+/* Event/Channel context */
+#define LTTNG_KERNEL_ABI_OLD_CONTEXT_PADDING1  16
+#define LTTNG_KERNEL_ABI_OLD_CONTEXT_PADDING2  LTTNG_KERNEL_ABI_SYM_NAME_LEN + 32
+struct lttng_kernel_abi_old_context {
+       enum lttng_kernel_abi_context_type ctx;
+       char padding[LTTNG_KERNEL_ABI_OLD_CONTEXT_PADDING1];
+
+       union {
+               struct lttng_kernel_abi_old_perf_counter_ctx perf_counter;
+               char padding[LTTNG_KERNEL_ABI_OLD_CONTEXT_PADDING2];
+       } u;
+};
+
+struct lttng_kernel_abi_old_kretprobe {
+       uint64_t addr;
+
+       uint64_t offset;
+       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+};
+
+/*
+ * Either addr is used, or symbol_name and offset.
+ */
+struct lttng_kernel_abi_old_kprobe {
+       uint64_t addr;
+
+       uint64_t offset;
+       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+};
+
+/* Function tracer */
+struct lttng_kernel_abi_old_function {
+       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+};
+
+#define LTTNG_KERNEL_ABI_OLD_EVENT_PADDING1    16
+#define LTTNG_KERNEL_ABI_OLD_EVENT_PADDING2    LTTNG_KERNEL_ABI_SYM_NAME_LEN + 32
+struct lttng_kernel_abi_old_event {
+       char name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+       enum lttng_kernel_abi_instrumentation instrumentation;
+       char padding[LTTNG_KERNEL_ABI_OLD_EVENT_PADDING1];
+
+       /* Per instrumentation type configuration */
+       union {
+               struct lttng_kernel_abi_old_kretprobe kretprobe;
+               struct lttng_kernel_abi_old_kprobe kprobe;
+               struct lttng_kernel_abi_old_function ftrace;
+               char padding[LTTNG_KERNEL_ABI_OLD_EVENT_PADDING2];
+       } u;
+};
+
+struct lttng_kernel_abi_old_tracer_version {
+       uint32_t major;
+       uint32_t minor;
+       uint32_t patchlevel;
+};
+
+/*
+ * kernel channel
+ */
+#define LTTNG_KERNEL_ABI_OLD_CHANNEL_PADDING1 LTTNG_SYMBOL_NAME_LEN + 32
+struct lttng_kernel_abi_old_channel {
+       int overwrite;                      /* 1: overwrite, 0: discard */
+       uint64_t subbuf_size;               /* bytes */
+       uint64_t num_subbuf;                /* power of 2 */
+       unsigned int switch_timer_interval; /* usec */
+       unsigned int read_timer_interval;   /* usec */
+       enum lttng_event_output output;     /* splice, mmap */
+
+       char padding[LTTNG_KERNEL_ABI_OLD_CHANNEL_PADDING1];
+};
+
+#endif /* _LTTNG_KERNEL_OLD_H */
diff --git a/src/common/lttng-kernel.h b/src/common/lttng-kernel.h
deleted file mode 100644 (file)
index 82f242b..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_KERNEL_H
-#define _LTTNG_KERNEL_H
-
-#include <stdint.h>
-#include <common/macros.h>
-#include <lttng/constant.h>
-#include <lttng/event.h>
-
-#define LTTNG_KERNEL_ABI_SYM_NAME_LEN  256
-#define LTTNG_KERNEL_ABI_MAX_UPROBE_NUM  32
-#define LTTNG_KERNEL_ABI_SESSION_NAME_LEN      256
-#define LTTNG_KERNEL_ABI_SESSION_CREATION_TIME_ISO8601_LEN     26
-
-/*
- * LTTng DebugFS ABI structures.
- *
- * This is the kernel ABI copied from lttng-modules tree.
- */
-
-enum lttng_kernel_abi_instrumentation {
-       LTTNG_KERNEL_ABI_ALL           = -1,   /* Used within lttng-tools */
-       LTTNG_KERNEL_ABI_TRACEPOINT    = 0,
-       LTTNG_KERNEL_ABI_KPROBE        = 1,
-       LTTNG_KERNEL_ABI_FUNCTION      = 2,
-       LTTNG_KERNEL_ABI_KRETPROBE     = 3,
-       LTTNG_KERNEL_ABI_NOOP          = 4,    /* not hooked */
-       LTTNG_KERNEL_ABI_SYSCALL       = 5,
-       LTTNG_KERNEL_ABI_UPROBE        = 6,
-};
-
-enum lttng_kernel_abi_context_type {
-       LTTNG_KERNEL_ABI_CONTEXT_PID            = 0,
-       LTTNG_KERNEL_ABI_CONTEXT_PERF_CPU_COUNTER = 1,
-       LTTNG_KERNEL_ABI_CONTEXT_PROCNAME       = 2,
-       LTTNG_KERNEL_ABI_CONTEXT_PRIO           = 3,
-       LTTNG_KERNEL_ABI_CONTEXT_NICE           = 4,
-       LTTNG_KERNEL_ABI_CONTEXT_VPID           = 5,
-       LTTNG_KERNEL_ABI_CONTEXT_TID            = 6,
-       LTTNG_KERNEL_ABI_CONTEXT_VTID           = 7,
-       LTTNG_KERNEL_ABI_CONTEXT_PPID           = 8,
-       LTTNG_KERNEL_ABI_CONTEXT_VPPID          = 9,
-       LTTNG_KERNEL_ABI_CONTEXT_HOSTNAME       = 10,
-       LTTNG_KERNEL_ABI_CONTEXT_CPU_ID         = 11,
-       LTTNG_KERNEL_ABI_CONTEXT_INTERRUPTIBLE  = 12,
-       LTTNG_KERNEL_ABI_CONTEXT_PREEMPTIBLE    = 13,
-       LTTNG_KERNEL_ABI_CONTEXT_NEED_RESCHEDULE = 14,
-       LTTNG_KERNEL_ABI_CONTEXT_MIGRATABLE     = 15,
-       LTTNG_KERNEL_ABI_CONTEXT_CALLSTACK_KERNEL = 16,
-       LTTNG_KERNEL_ABI_CONTEXT_CALLSTACK_USER   = 17,
-       LTTNG_KERNEL_ABI_CONTEXT_CGROUP_NS      = 18,
-       LTTNG_KERNEL_ABI_CONTEXT_IPC_NS         = 19,
-       LTTNG_KERNEL_ABI_CONTEXT_MNT_NS         = 20,
-       LTTNG_KERNEL_ABI_CONTEXT_NET_NS         = 21,
-       LTTNG_KERNEL_ABI_CONTEXT_PID_NS         = 22,
-       LTTNG_KERNEL_ABI_CONTEXT_USER_NS        = 23,
-       LTTNG_KERNEL_ABI_CONTEXT_UTS_NS         = 24,
-       LTTNG_KERNEL_ABI_CONTEXT_UID            = 25,
-       LTTNG_KERNEL_ABI_CONTEXT_EUID           = 26,
-       LTTNG_KERNEL_ABI_CONTEXT_SUID           = 27,
-       LTTNG_KERNEL_ABI_CONTEXT_GID            = 28,
-       LTTNG_KERNEL_ABI_CONTEXT_EGID           = 29,
-       LTTNG_KERNEL_ABI_CONTEXT_SGID           = 30,
-       LTTNG_KERNEL_ABI_CONTEXT_VUID           = 31,
-       LTTNG_KERNEL_ABI_CONTEXT_VEUID          = 32,
-       LTTNG_KERNEL_ABI_CONTEXT_VSUID          = 33,
-       LTTNG_KERNEL_ABI_CONTEXT_VGID           = 34,
-       LTTNG_KERNEL_ABI_CONTEXT_VEGID          = 35,
-       LTTNG_KERNEL_ABI_CONTEXT_VSGID          = 36,
-       LTTNG_KERNEL_ABI_CONTEXT_TIME_NS        = 37,
-};
-
-/* Perf counter attributes */
-struct lttng_kernel_abi_perf_counter_ctx {
-       uint32_t type;
-       uint64_t config;
-       char name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-} LTTNG_PACKED;
-
-/* Event/Channel context */
-#define LTTNG_KERNEL_ABI_CONTEXT_PADDING1  16
-#define LTTNG_KERNEL_ABI_CONTEXT_PADDING2  LTTNG_KERNEL_ABI_SYM_NAME_LEN + 32
-struct lttng_kernel_abi_context {
-       enum lttng_kernel_abi_context_type ctx;
-       char padding[LTTNG_KERNEL_ABI_CONTEXT_PADDING1];
-
-       union {
-               struct lttng_kernel_abi_perf_counter_ctx perf_counter;
-               char padding[LTTNG_KERNEL_ABI_CONTEXT_PADDING2];
-       } u;
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_kretprobe {
-       uint64_t addr;
-
-       uint64_t offset;
-       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-} LTTNG_PACKED;
-
-/*
- * Either addr is used, or symbol_name and offset.
- */
-struct lttng_kernel_abi_kprobe {
-       uint64_t addr;
-
-       uint64_t offset;
-       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_uprobe {
-       int fd;
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_event_callsite_uprobe {
-       uint64_t offset;
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_event_callsite {
-       union {
-               struct lttng_kernel_abi_event_callsite_uprobe uprobe;
-       } u;
-} LTTNG_PACKED;
-
-enum lttng_kernel_abi_syscall_entryexit {
-       LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT      = 0,
-       LTTNG_KERNEL_ABI_SYSCALL_ENTRY  = 1,
-       LTTNG_KERNEL_ABI_SYSCALL_EXIT   = 2,
-};
-
-enum lttng_kernel_abi_syscall_abi {
-       LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL        = 0,
-       LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE = 1,
-       LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT = 2,
-};
-
-enum lttng_kernel_abi_syscall_match {
-       LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME = 0,
-       LTTNG_KERNEL_ABI_SYSCALL_MATCH_NR       = 1,
-};
-
-struct lttng_kernel_abi_syscall {
-       uint8_t entryexit;      /* enum lttng_kernel_abi_syscall_entryexit */
-       uint8_t abi;            /* enum lttng_kernel_abi_syscall_abi */
-       uint8_t match;          /* enum lttng_kernel_abi_syscall_match */
-       uint8_t padding;
-       uint32_t nr;            /* For LTTNG_SYSCALL_MATCH_NR */
-} LTTNG_PACKED;
-
-/* Function tracer */
-struct lttng_kernel_abi_function {
-       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_EVENT_PADDING1    8
-#define LTTNG_KERNEL_ABI_EVENT_PADDING2    LTTNG_KERNEL_ABI_SYM_NAME_LEN + 32
-struct lttng_kernel_abi_event {
-       char name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
-       enum lttng_kernel_abi_instrumentation instrumentation;
-       uint64_t token;
-       char padding[LTTNG_KERNEL_ABI_EVENT_PADDING1];
-
-       /* Per instrumentation type configuration */
-       union {
-               struct lttng_kernel_abi_kretprobe kretprobe;
-               struct lttng_kernel_abi_kprobe kprobe;
-               struct lttng_kernel_abi_function ftrace;
-               struct lttng_kernel_abi_uprobe uprobe;
-               struct lttng_kernel_abi_syscall syscall;
-               char padding[LTTNG_KERNEL_ABI_EVENT_PADDING2];
-       } u;
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_PADDING        32
-struct lttng_kernel_abi_event_notifier {
-       struct lttng_kernel_abi_event event;
-       uint64_t error_counter_idx;
-
-       char padding[LTTNG_KERNEL_ABI_EVENT_NOTIFIER_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX      4
-
-enum lttng_kernel_abi_counter_arithmetic {
-       LTTNG_KERNEL_ABI_COUNTER_ARITHMETIC_MODULAR = 0,
-};
-
-enum lttng_kernel_abi_counter_bitness {
-       LTTNG_KERNEL_ABI_COUNTER_BITNESS_32 = 0,
-       LTTNG_KERNEL_ABI_COUNTER_BITNESS_64 = 1,
-};
-
-struct lttng_kernel_abi_counter_dimension {
-       uint64_t size;
-       uint64_t underflow_index;
-       uint64_t overflow_index;
-       uint8_t has_underflow;
-       uint8_t has_overflow;
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_COUNTER_CONF_PADDING1      67
-struct lttng_kernel_abi_counter_conf {
-       uint32_t arithmetic;    /* enum lttng_kernel_abi_counter_arithmetic */
-       uint32_t bitness;       /* enum lttng_kernel_abi_counter_bitness */
-       uint32_t number_dimensions;
-       int64_t global_sum_step;
-       struct lttng_kernel_abi_counter_dimension dimensions[LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX];
-       uint8_t coalesce_hits;
-       char padding[LTTNG_KERNEL_ABI_COUNTER_CONF_PADDING1];
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_counter_index {
-       uint32_t number_dimensions;
-       uint64_t dimension_indexes[LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX];
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_counter_value {
-       int64_t value;
-       uint8_t underflow;
-       uint8_t overflow;
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_COUNTER_READ_PADDING 32
-struct lttng_kernel_abi_counter_read {
-       struct lttng_kernel_abi_counter_index index;
-       int32_t cpu;    /* -1 for global counter, >= 0 for specific cpu. */
-       struct lttng_kernel_abi_counter_value value;    /* output */
-       char padding[LTTNG_KERNEL_ABI_COUNTER_READ_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_COUNTER_AGGREGATE_PADDING 32
-struct lttng_kernel_abi_counter_aggregate {
-       struct lttng_kernel_abi_counter_index index;
-       struct lttng_kernel_abi_counter_value value;    /* output */
-       char padding[LTTNG_KERNEL_ABI_COUNTER_AGGREGATE_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_COUNTER_CLEAR_PADDING 32
-struct lttng_kernel_abi_counter_clear {
-       struct lttng_kernel_abi_counter_index index;
-       char padding[LTTNG_KERNEL_ABI_COUNTER_CLEAR_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING 32
-struct lttng_kernel_abi_event_notifier_notification {
-       uint64_t token;
-       uint16_t capture_buf_size;
-       char padding[LTTNG_KERNEL_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING];
-} LTTNG_PACKED;
-
-#define LTTNG_KERNEL_ABI_CAPTURE_BYTECODE_MAX_LEN              65536
-struct lttng_kernel_abi_capture_bytecode {
-       uint32_t len;
-       uint32_t reloc_offset;
-       uint64_t seqnum;
-       char data[0];
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_tracer_version {
-       uint32_t major;
-       uint32_t minor;
-       uint32_t patchlevel;
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_tracer_abi_version {
-       uint32_t major;
-       uint32_t minor;
-} LTTNG_PACKED;
-
-struct lttng_kernel_abi_syscall_mask {
-       uint32_t len;   /* in bits */
-       char mask[];
-} LTTNG_PACKED;
-
-/*
- * kernel channel
- */
-#define LTTNG_KERNEL_ABI_CHANNEL_PADDING1 LTTNG_SYMBOL_NAME_LEN + 32
-struct lttng_kernel_abi_channel {
-       uint64_t subbuf_size;               /* bytes */
-       uint64_t num_subbuf;                /* power of 2 */
-       unsigned int switch_timer_interval; /* usec */
-       unsigned int read_timer_interval;   /* usec */
-       enum lttng_event_output output;     /* splice, mmap */
-
-       int overwrite;                      /* 1: overwrite, 0: discard */
-       char padding[LTTNG_KERNEL_ABI_CHANNEL_PADDING1];
-} LTTNG_PACKED;
-
-#define KERNEL_FILTER_BYTECODE_MAX_LEN         65536
-struct lttng_kernel_abi_filter_bytecode {
-       uint32_t len;
-       uint32_t reloc_offset;
-       uint64_t seqnum;
-       char data[0];
-} LTTNG_PACKED;
-
-/*
- * kernel session name
- */
-struct lttng_kernel_abi_session_name {
-       char name[LTTNG_KERNEL_ABI_SESSION_NAME_LEN];
-} LTTNG_PACKED;
-
-/*
- * kernel session creation datetime
- */
-struct lttng_kernel_abi_session_creation_time {
-       char iso8601[LTTNG_KERNEL_ABI_SESSION_CREATION_TIME_ISO8601_LEN];
-} LTTNG_PACKED;
-
-enum lttng_kernel_abi_tracker_type {
-       LTTNG_KERNEL_ABI_TRACKER_UNKNOWN                = -1,
-
-       LTTNG_KERNEL_ABI_TRACKER_PID            = 0,
-       LTTNG_KERNEL_ABI_TRACKER_VPID           = 1,
-       LTTNG_KERNEL_ABI_TRACKER_UID            = 2,
-       LTTNG_KERNEL_ABI_TRACKER_VUID           = 3,
-       LTTNG_KERNEL_ABI_TRACKER_GID            = 4,
-       LTTNG_KERNEL_ABI_TRACKER_VGID           = 5,
-};
-
-struct lttng_kernel_abi_tracker_args {
-       enum lttng_kernel_abi_tracker_type type;
-       int32_t id;
-};
-
-#endif /* _LTTNG_KERNEL_H */
diff --git a/src/common/lttng-kernel.hpp b/src/common/lttng-kernel.hpp
new file mode 100644 (file)
index 0000000..4284142
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_KERNEL_H
+#define _LTTNG_KERNEL_H
+
+#include <stdint.h>
+#include <common/macros.hpp>
+#include <lttng/constant.h>
+#include <lttng/event.h>
+
+#define LTTNG_KERNEL_ABI_SYM_NAME_LEN  256
+#define LTTNG_KERNEL_ABI_MAX_UPROBE_NUM  32
+#define LTTNG_KERNEL_ABI_SESSION_NAME_LEN      256
+#define LTTNG_KERNEL_ABI_SESSION_CREATION_TIME_ISO8601_LEN     26
+
+/*
+ * LTTng DebugFS ABI structures.
+ *
+ * This is the kernel ABI copied from lttng-modules tree.
+ */
+
+enum lttng_kernel_abi_instrumentation {
+       LTTNG_KERNEL_ABI_ALL           = -1,   /* Used within lttng-tools */
+       LTTNG_KERNEL_ABI_TRACEPOINT    = 0,
+       LTTNG_KERNEL_ABI_KPROBE        = 1,
+       LTTNG_KERNEL_ABI_FUNCTION      = 2,
+       LTTNG_KERNEL_ABI_KRETPROBE     = 3,
+       LTTNG_KERNEL_ABI_NOOP          = 4,    /* not hooked */
+       LTTNG_KERNEL_ABI_SYSCALL       = 5,
+       LTTNG_KERNEL_ABI_UPROBE        = 6,
+};
+
+enum lttng_kernel_abi_context_type {
+       LTTNG_KERNEL_ABI_CONTEXT_PID            = 0,
+       LTTNG_KERNEL_ABI_CONTEXT_PERF_CPU_COUNTER = 1,
+       LTTNG_KERNEL_ABI_CONTEXT_PROCNAME       = 2,
+       LTTNG_KERNEL_ABI_CONTEXT_PRIO           = 3,
+       LTTNG_KERNEL_ABI_CONTEXT_NICE           = 4,
+       LTTNG_KERNEL_ABI_CONTEXT_VPID           = 5,
+       LTTNG_KERNEL_ABI_CONTEXT_TID            = 6,
+       LTTNG_KERNEL_ABI_CONTEXT_VTID           = 7,
+       LTTNG_KERNEL_ABI_CONTEXT_PPID           = 8,
+       LTTNG_KERNEL_ABI_CONTEXT_VPPID          = 9,
+       LTTNG_KERNEL_ABI_CONTEXT_HOSTNAME       = 10,
+       LTTNG_KERNEL_ABI_CONTEXT_CPU_ID         = 11,
+       LTTNG_KERNEL_ABI_CONTEXT_INTERRUPTIBLE  = 12,
+       LTTNG_KERNEL_ABI_CONTEXT_PREEMPTIBLE    = 13,
+       LTTNG_KERNEL_ABI_CONTEXT_NEED_RESCHEDULE = 14,
+       LTTNG_KERNEL_ABI_CONTEXT_MIGRATABLE     = 15,
+       LTTNG_KERNEL_ABI_CONTEXT_CALLSTACK_KERNEL = 16,
+       LTTNG_KERNEL_ABI_CONTEXT_CALLSTACK_USER   = 17,
+       LTTNG_KERNEL_ABI_CONTEXT_CGROUP_NS      = 18,
+       LTTNG_KERNEL_ABI_CONTEXT_IPC_NS         = 19,
+       LTTNG_KERNEL_ABI_CONTEXT_MNT_NS         = 20,
+       LTTNG_KERNEL_ABI_CONTEXT_NET_NS         = 21,
+       LTTNG_KERNEL_ABI_CONTEXT_PID_NS         = 22,
+       LTTNG_KERNEL_ABI_CONTEXT_USER_NS        = 23,
+       LTTNG_KERNEL_ABI_CONTEXT_UTS_NS         = 24,
+       LTTNG_KERNEL_ABI_CONTEXT_UID            = 25,
+       LTTNG_KERNEL_ABI_CONTEXT_EUID           = 26,
+       LTTNG_KERNEL_ABI_CONTEXT_SUID           = 27,
+       LTTNG_KERNEL_ABI_CONTEXT_GID            = 28,
+       LTTNG_KERNEL_ABI_CONTEXT_EGID           = 29,
+       LTTNG_KERNEL_ABI_CONTEXT_SGID           = 30,
+       LTTNG_KERNEL_ABI_CONTEXT_VUID           = 31,
+       LTTNG_KERNEL_ABI_CONTEXT_VEUID          = 32,
+       LTTNG_KERNEL_ABI_CONTEXT_VSUID          = 33,
+       LTTNG_KERNEL_ABI_CONTEXT_VGID           = 34,
+       LTTNG_KERNEL_ABI_CONTEXT_VEGID          = 35,
+       LTTNG_KERNEL_ABI_CONTEXT_VSGID          = 36,
+       LTTNG_KERNEL_ABI_CONTEXT_TIME_NS        = 37,
+};
+
+/* Perf counter attributes */
+struct lttng_kernel_abi_perf_counter_ctx {
+       uint32_t type;
+       uint64_t config;
+       char name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+} LTTNG_PACKED;
+
+/* Event/Channel context */
+#define LTTNG_KERNEL_ABI_CONTEXT_PADDING1  16
+#define LTTNG_KERNEL_ABI_CONTEXT_PADDING2  LTTNG_KERNEL_ABI_SYM_NAME_LEN + 32
+struct lttng_kernel_abi_context {
+       enum lttng_kernel_abi_context_type ctx;
+       char padding[LTTNG_KERNEL_ABI_CONTEXT_PADDING1];
+
+       union {
+               struct lttng_kernel_abi_perf_counter_ctx perf_counter;
+               char padding[LTTNG_KERNEL_ABI_CONTEXT_PADDING2];
+       } u;
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_kretprobe {
+       uint64_t addr;
+
+       uint64_t offset;
+       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+} LTTNG_PACKED;
+
+/*
+ * Either addr is used, or symbol_name and offset.
+ */
+struct lttng_kernel_abi_kprobe {
+       uint64_t addr;
+
+       uint64_t offset;
+       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_uprobe {
+       int fd;
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_event_callsite_uprobe {
+       uint64_t offset;
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_event_callsite {
+       union {
+               struct lttng_kernel_abi_event_callsite_uprobe uprobe;
+       } u;
+} LTTNG_PACKED;
+
+enum lttng_kernel_abi_syscall_entryexit {
+       LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT      = 0,
+       LTTNG_KERNEL_ABI_SYSCALL_ENTRY  = 1,
+       LTTNG_KERNEL_ABI_SYSCALL_EXIT   = 2,
+};
+
+enum lttng_kernel_abi_syscall_abi {
+       LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL        = 0,
+       LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE = 1,
+       LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT = 2,
+};
+
+enum lttng_kernel_abi_syscall_match {
+       LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME = 0,
+       LTTNG_KERNEL_ABI_SYSCALL_MATCH_NR       = 1,
+};
+
+struct lttng_kernel_abi_syscall {
+       uint8_t entryexit;      /* enum lttng_kernel_abi_syscall_entryexit */
+       uint8_t abi;            /* enum lttng_kernel_abi_syscall_abi */
+       uint8_t match;          /* enum lttng_kernel_abi_syscall_match */
+       uint8_t padding;
+       uint32_t nr;            /* For LTTNG_SYSCALL_MATCH_NR */
+} LTTNG_PACKED;
+
+/* Function tracer */
+struct lttng_kernel_abi_function {
+       char symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_EVENT_PADDING1    8
+#define LTTNG_KERNEL_ABI_EVENT_PADDING2    LTTNG_KERNEL_ABI_SYM_NAME_LEN + 32
+struct lttng_kernel_abi_event {
+       char name[LTTNG_KERNEL_ABI_SYM_NAME_LEN];
+       enum lttng_kernel_abi_instrumentation instrumentation;
+       uint64_t token;
+       char padding[LTTNG_KERNEL_ABI_EVENT_PADDING1];
+
+       /* Per instrumentation type configuration */
+       union {
+               struct lttng_kernel_abi_kretprobe kretprobe;
+               struct lttng_kernel_abi_kprobe kprobe;
+               struct lttng_kernel_abi_function ftrace;
+               struct lttng_kernel_abi_uprobe uprobe;
+               struct lttng_kernel_abi_syscall syscall;
+               char padding[LTTNG_KERNEL_ABI_EVENT_PADDING2];
+       } u;
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_PADDING        32
+struct lttng_kernel_abi_event_notifier {
+       struct lttng_kernel_abi_event event;
+       uint64_t error_counter_idx;
+
+       char padding[LTTNG_KERNEL_ABI_EVENT_NOTIFIER_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX      4
+
+enum lttng_kernel_abi_counter_arithmetic {
+       LTTNG_KERNEL_ABI_COUNTER_ARITHMETIC_MODULAR = 0,
+};
+
+enum lttng_kernel_abi_counter_bitness {
+       LTTNG_KERNEL_ABI_COUNTER_BITNESS_32 = 0,
+       LTTNG_KERNEL_ABI_COUNTER_BITNESS_64 = 1,
+};
+
+struct lttng_kernel_abi_counter_dimension {
+       uint64_t size;
+       uint64_t underflow_index;
+       uint64_t overflow_index;
+       uint8_t has_underflow;
+       uint8_t has_overflow;
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_COUNTER_CONF_PADDING1      67
+struct lttng_kernel_abi_counter_conf {
+       uint32_t arithmetic;    /* enum lttng_kernel_abi_counter_arithmetic */
+       uint32_t bitness;       /* enum lttng_kernel_abi_counter_bitness */
+       uint32_t number_dimensions;
+       int64_t global_sum_step;
+       struct lttng_kernel_abi_counter_dimension dimensions[LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX];
+       uint8_t coalesce_hits;
+       char padding[LTTNG_KERNEL_ABI_COUNTER_CONF_PADDING1];
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_counter_index {
+       uint32_t number_dimensions;
+       uint64_t dimension_indexes[LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX];
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_counter_value {
+       int64_t value;
+       uint8_t underflow;
+       uint8_t overflow;
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_COUNTER_READ_PADDING 32
+struct lttng_kernel_abi_counter_read {
+       struct lttng_kernel_abi_counter_index index;
+       int32_t cpu;    /* -1 for global counter, >= 0 for specific cpu. */
+       struct lttng_kernel_abi_counter_value value;    /* output */
+       char padding[LTTNG_KERNEL_ABI_COUNTER_READ_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_COUNTER_AGGREGATE_PADDING 32
+struct lttng_kernel_abi_counter_aggregate {
+       struct lttng_kernel_abi_counter_index index;
+       struct lttng_kernel_abi_counter_value value;    /* output */
+       char padding[LTTNG_KERNEL_ABI_COUNTER_AGGREGATE_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_COUNTER_CLEAR_PADDING 32
+struct lttng_kernel_abi_counter_clear {
+       struct lttng_kernel_abi_counter_index index;
+       char padding[LTTNG_KERNEL_ABI_COUNTER_CLEAR_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING 32
+struct lttng_kernel_abi_event_notifier_notification {
+       uint64_t token;
+       uint16_t capture_buf_size;
+       char padding[LTTNG_KERNEL_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING];
+} LTTNG_PACKED;
+
+#define LTTNG_KERNEL_ABI_CAPTURE_BYTECODE_MAX_LEN              65536
+struct lttng_kernel_abi_capture_bytecode {
+       uint32_t len;
+       uint32_t reloc_offset;
+       uint64_t seqnum;
+       char data[0];
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_tracer_version {
+       uint32_t major;
+       uint32_t minor;
+       uint32_t patchlevel;
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_tracer_abi_version {
+       uint32_t major;
+       uint32_t minor;
+} LTTNG_PACKED;
+
+struct lttng_kernel_abi_syscall_mask {
+       uint32_t len;   /* in bits */
+       char mask[];
+} LTTNG_PACKED;
+
+/*
+ * kernel channel
+ */
+#define LTTNG_KERNEL_ABI_CHANNEL_PADDING1 LTTNG_SYMBOL_NAME_LEN + 32
+struct lttng_kernel_abi_channel {
+       uint64_t subbuf_size;               /* bytes */
+       uint64_t num_subbuf;                /* power of 2 */
+       unsigned int switch_timer_interval; /* usec */
+       unsigned int read_timer_interval;   /* usec */
+       enum lttng_event_output output;     /* splice, mmap */
+
+       int overwrite;                      /* 1: overwrite, 0: discard */
+       char padding[LTTNG_KERNEL_ABI_CHANNEL_PADDING1];
+} LTTNG_PACKED;
+
+#define KERNEL_FILTER_BYTECODE_MAX_LEN         65536
+struct lttng_kernel_abi_filter_bytecode {
+       uint32_t len;
+       uint32_t reloc_offset;
+       uint64_t seqnum;
+       char data[0];
+} LTTNG_PACKED;
+
+/*
+ * kernel session name
+ */
+struct lttng_kernel_abi_session_name {
+       char name[LTTNG_KERNEL_ABI_SESSION_NAME_LEN];
+} LTTNG_PACKED;
+
+/*
+ * kernel session creation datetime
+ */
+struct lttng_kernel_abi_session_creation_time {
+       char iso8601[LTTNG_KERNEL_ABI_SESSION_CREATION_TIME_ISO8601_LEN];
+} LTTNG_PACKED;
+
+enum lttng_kernel_abi_tracker_type {
+       LTTNG_KERNEL_ABI_TRACKER_UNKNOWN                = -1,
+
+       LTTNG_KERNEL_ABI_TRACKER_PID            = 0,
+       LTTNG_KERNEL_ABI_TRACKER_VPID           = 1,
+       LTTNG_KERNEL_ABI_TRACKER_UID            = 2,
+       LTTNG_KERNEL_ABI_TRACKER_VUID           = 3,
+       LTTNG_KERNEL_ABI_TRACKER_GID            = 4,
+       LTTNG_KERNEL_ABI_TRACKER_VGID           = 5,
+};
+
+struct lttng_kernel_abi_tracker_args {
+       enum lttng_kernel_abi_tracker_type type;
+       int32_t id;
+};
+
+#endif /* _LTTNG_KERNEL_H */
diff --git a/src/common/macros.h b/src/common/macros.h
deleted file mode 100644 (file)
index 6ac24fa..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _MACROS_H
-#define _MACROS_H
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <common/compat/string.h>
-
-/*
- * Takes a pointer x and transform it so we can use it to access members
- * without a function call. Here an example:
- *
- *    #define GET_SIZE(x) LTTNG_REF(x)->size
- *
- *    struct { int size; } s;
- *
- *    printf("size : %d\n", GET_SIZE(&s));
- *
- * For this example we can't use something like this for compatibility purpose
- * since this will fail:
- *
- *    #define GET_SIZE(x) x->size;
- *
- * This is mostly use for the compatibility layer of lttng-tools. See
- * poll/epoll for a good example. Since x can be on the stack or allocated
- * memory using malloc(), we must use generic accessors for compat in order to
- * *not* use a function to access members and not the variable name.
- */
-#define LTTNG_REF(x) ((typeof(*x) *)(x))
-
-/*
- * Memory allocation zeroed
- */
-static inline
-void *zmalloc(size_t len)
-{
-       return calloc(1, len);
-}
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(array)   (sizeof(array) / (sizeof((array)[0])))
-#endif
-
-#ifndef container_of
-#define container_of(ptr, type, member)                                        \
-       ({                                                              \
-               const typeof(((type *)NULL)->member) * __ptr = (ptr);   \
-               (type *)((char *)__ptr - offsetof(type, member));       \
-       })
-#endif
-
-#ifndef LTTNG_PACKED
-#define LTTNG_PACKED __attribute__((__packed__))
-#endif
-
-#ifndef LTTNG_NO_SANITIZE_ADDRESS
-#if defined(__clang__) || defined (__GNUC__)
-#define LTTNG_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
-#else
-#define LTTNG_NO_SANITIZE_ADDRESS
-#endif
-#endif
-
-#define is_signed(type) (((type) -1) < (type) 1)
-
-#define member_sizeof(type, field)     sizeof(((type *) 0)->field)
-
-#define ASSERT_LOCKED(lock) LTTNG_ASSERT(pthread_mutex_trylock(&lock))
-
-/* Attribute suitable to tag functions as having printf()-like arguments. */
-#define ATTR_FORMAT_PRINTF(_string_index, _first_to_check) \
-       __attribute__((format(printf, _string_index, _first_to_check)))
-
-/* Attribute suitable to tag functions as having strftime()-like arguments. */
-#define ATTR_FORMAT_STRFTIME(_string_index) \
-       __attribute__((format(strftime, _string_index, 0)))
-
-/* Macros used to ignore specific compiler diagnostics. */
-
-#define DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
-#define DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
-
-#if defined(__clang__)
-  /* Clang */
-# define DIAGNOSTIC_IGNORE_SUGGEST_ATTRIBUTE_FORMAT
-# define DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL \
-       _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
-#else
-  /* GCC */
-# define DIAGNOSTIC_IGNORE_SUGGEST_ATTRIBUTE_FORMAT \
-       _Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=format\"")
-# define DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL \
-       _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
-#endif
-
-/* Used to make specific C++ functions to C code. */
-#ifdef __cplusplus
-#define C_LINKAGE extern "C"
-#else
-#define C_LINKAGE
-#endif
-
-/*
- * lttng_strncpy returns 0 on success, or nonzero on failure.
- * It checks that the @src string fits into @dst_len before performing
- * the copy. On failure, no copy has been performed.
- *
- * dst_len includes the string's trailing NULL.
- */
-static inline
-int lttng_strncpy(char *dst, const char *src, size_t dst_len)
-{
-       if (lttng_strnlen(src, dst_len) >= dst_len) {
-               /* Fail since copying would result in truncation. */
-               return -1;
-       }
-       strcpy(dst, src);
-       return 0;
-}
-
-#ifdef NDEBUG
-/*
-* Force usage of the assertion condition to prevent unused variable warnings
-* when `assert()` are disabled by the `NDEBUG` definition.
-*/
-# define LTTNG_ASSERT(_cond) ((void) sizeof((void) (_cond), 0))
-#else
-# include <assert.h>
-# define LTTNG_ASSERT(_cond) assert(_cond)
-#endif
-
-#endif /* _MACROS_H */
diff --git a/src/common/macros.hpp b/src/common/macros.hpp
new file mode 100644 (file)
index 0000000..d13f9bd
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _MACROS_H
+#define _MACROS_H
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <common/compat/string.hpp>
+
+/*
+ * Takes a pointer x and transform it so we can use it to access members
+ * without a function call. Here an example:
+ *
+ *    #define GET_SIZE(x) LTTNG_REF(x)->size
+ *
+ *    struct { int size; } s;
+ *
+ *    printf("size : %d\n", GET_SIZE(&s));
+ *
+ * For this example we can't use something like this for compatibility purpose
+ * since this will fail:
+ *
+ *    #define GET_SIZE(x) x->size;
+ *
+ * This is mostly use for the compatibility layer of lttng-tools. See
+ * poll/epoll for a good example. Since x can be on the stack or allocated
+ * memory using malloc(), we must use generic accessors for compat in order to
+ * *not* use a function to access members and not the variable name.
+ */
+#define LTTNG_REF(x) ((typeof(*x) *)(x))
+
+/*
+ * Memory allocation zeroed
+ */
+static inline
+void *zmalloc(size_t len)
+{
+       return calloc(1, len);
+}
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array)   (sizeof(array) / (sizeof((array)[0])))
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member)                                        \
+       ({                                                              \
+               const typeof(((type *)NULL)->member) * __ptr = (ptr);   \
+               (type *)((char *)__ptr - offsetof(type, member));       \
+       })
+#endif
+
+#ifndef LTTNG_PACKED
+#define LTTNG_PACKED __attribute__((__packed__))
+#endif
+
+#ifndef LTTNG_NO_SANITIZE_ADDRESS
+#if defined(__clang__) || defined (__GNUC__)
+#define LTTNG_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+#else
+#define LTTNG_NO_SANITIZE_ADDRESS
+#endif
+#endif
+
+#define member_sizeof(type, field)     sizeof(((type *) 0)->field)
+
+#define ASSERT_LOCKED(lock) LTTNG_ASSERT(pthread_mutex_trylock(&lock))
+
+/* Attribute suitable to tag functions as having printf()-like arguments. */
+#define ATTR_FORMAT_PRINTF(_string_index, _first_to_check) \
+       __attribute__((format(printf, _string_index, _first_to_check)))
+
+/* Attribute suitable to tag functions as having strftime()-like arguments. */
+#define ATTR_FORMAT_STRFTIME(_string_index) \
+       __attribute__((format(strftime, _string_index, 0)))
+
+/* Macros used to ignore specific compiler diagnostics. */
+
+#define DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
+#define DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
+
+#if defined(__clang__)
+  /* Clang */
+# define DIAGNOSTIC_IGNORE_SUGGEST_ATTRIBUTE_FORMAT
+# define DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL \
+       _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
+#else
+  /* GCC */
+# define DIAGNOSTIC_IGNORE_SUGGEST_ATTRIBUTE_FORMAT \
+       _Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=format\"")
+# define DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL \
+       _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
+#endif
+
+/* Used to make specific C++ functions to C code. */
+#ifdef __cplusplus
+#define C_LINKAGE extern "C"
+#else
+#define C_LINKAGE
+#endif
+
+/*
+ * lttng_strncpy returns 0 on success, or nonzero on failure.
+ * It checks that the @src string fits into @dst_len before performing
+ * the copy. On failure, no copy has been performed.
+ *
+ * dst_len includes the string's trailing NULL.
+ */
+static inline
+int lttng_strncpy(char *dst, const char *src, size_t dst_len)
+{
+       if (lttng_strnlen(src, dst_len) >= dst_len) {
+               /* Fail since copying would result in truncation. */
+               return -1;
+       }
+       strcpy(dst, src);
+       return 0;
+}
+
+#ifdef NDEBUG
+/*
+* Force usage of the assertion condition to prevent unused variable warnings
+* when `assert()` are disabled by the `NDEBUG` definition.
+*/
+# define LTTNG_ASSERT(_cond) ((void) sizeof((void) (_cond), 0))
+#else
+# include <assert.h>
+# define LTTNG_ASSERT(_cond) assert(_cond)
+#endif
+
+#define DISABLE_COPY_AND_ASSIGN(name) \
+       name (const name &) = delete; \
+       name &operator=(const name &) = delete
+
+#endif /* _MACROS_H */
index d41a3cadc7e2e1d05f11bc9f773ac2308f420f09..e07dfc8d42a31995411060bc425eab53c5d85c28 100644 (file)
@@ -9,12 +9,12 @@
 
 #include "lttng/tracker.h"
 #define _LGPL_SOURCE
-#include "mi-lttng.h"
-#include <common/config/session-config.h>
-#include <common/defaults.h>
-#include <common/tracker.h>
+#include "mi-lttng.hpp"
+#include <common/config/session-config.hpp>
+#include <common/defaults.hpp>
+#include <common/tracker.hpp>
 #include <lttng/channel.h>
-#include <lttng/snapshot-internal.h>
+#include <lttng/snapshot-internal.hpp>
 
 
 #define MI_SCHEMA_MAJOR_VERSION 4
diff --git a/src/common/mi-lttng.h b/src/common/mi-lttng.h
deleted file mode 100644 (file)
index a9c59a6..0000000
+++ /dev/null
@@ -1,1120 +0,0 @@
-/*
- * Copyright (C) 2014 Jonathan Rajotte <jonathan.r.julien@gmail.com>
- * Copyright (C) 2014 Olivier Cotte <olivier.cotte@polymtl.ca>
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _MI_LTTNG_H
-#define _MI_LTTNG_H
-
-#include <stdint.h>
-
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/config/session-config.h>
-#include <lttng/lttng.h>
-
-/* Don't want to reference snapshot-internal.h here */
-struct lttng_snapshot_output;
-
-/* Instance of a machine interface writer. */
-struct mi_writer {
-       struct config_writer *writer;
-       enum lttng_mi_output_type type;
-};
-
-/*
- * Version information for the machine interface.
- */
-struct mi_lttng_version_data {
-       char version[LTTNG_NAME_MAX]; /* Version number of package */
-       uint32_t version_major; /* LTTng-Tools major version number */
-       uint32_t version_minor; /* LTTng-Tools minor version number */
-       uint32_t version_patchlevel; /* LTTng-Tools patchlevel version number */
-       char version_commit[LTTNG_NAME_MAX]; /* Commit hash of the current version */
-       char version_name[LTTNG_NAME_MAX];
-       char package_url[LTTNG_NAME_MAX]; /* Define to the home page for this package. */
-};
-
-/* Error query callbacks. */
-typedef enum lttng_error_code (*mi_lttng_error_query_trigger_cb)(
-               const struct lttng_trigger *trigger,
-               struct lttng_error_query_results **results);
-typedef enum lttng_error_code (*mi_lttng_error_query_condition_cb)(
-               const struct lttng_trigger *trigger,
-               struct lttng_error_query_results **results);
-typedef enum lttng_error_code (*mi_lttng_error_query_action_cb)(
-               const struct lttng_trigger *trigger,
-               const struct lttng_action_path *action_path,
-               struct lttng_error_query_results **results);
-
-struct mi_lttng_error_query_callbacks {
-       mi_lttng_error_query_trigger_cb trigger_cb;
-       mi_lttng_error_query_condition_cb condition_cb;
-       mi_lttng_error_query_action_cb action_cb;
-};
-
-/* Strings related to command */
-LTTNG_EXPORT extern const char * const mi_lttng_element_command;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_action;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_add_context;
-extern const char * const mi_lttng_element_command_add_trigger;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_create;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_destroy;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_disable_channel;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_disable_event;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_enable_channels;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_enable_event;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_list;
-extern const char * const mi_lttng_element_command_list_trigger;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_load;
-extern const char * const mi_lttng_element_command_metadata;
-extern const char * const mi_lttng_element_command_metadata_action;
-extern const char * const mi_lttng_element_command_regenerate;
-extern const char * const mi_lttng_element_command_regenerate_action;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_name;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_output;
-extern const char * const mi_lttng_element_command_remove_trigger;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_save;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_set_session;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_add;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_del;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_list;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_record;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_start;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_stop;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_success;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_track;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_untrack;
-LTTNG_EXPORT extern const char * const mi_lttng_element_command_version;
-extern const char * const mi_lttng_element_command_rotate;
-extern const char * const mi_lttng_element_command_enable_rotation;
-extern const char * const mi_lttng_element_command_disable_rotation;
-extern const char * const mi_lttng_element_command_clear;
-
-/* Strings related to version command */
-LTTNG_EXPORT extern const char * const mi_lttng_element_version;
-LTTNG_EXPORT extern const char * const mi_lttng_element_version_commit;
-LTTNG_EXPORT extern const char * const mi_lttng_element_version_description;
-LTTNG_EXPORT extern const char * const mi_lttng_element_version_license;
-LTTNG_EXPORT extern const char * const mi_lttng_element_version_major;
-LTTNG_EXPORT extern const char * const mi_lttng_element_version_minor;
-LTTNG_EXPORT extern const char * const mi_lttng_element_version_patch_level;
-LTTNG_EXPORT extern const char * const mi_lttng_element_version_str;
-LTTNG_EXPORT extern const char * const mi_lttng_element_version_web;
-
-/* String related to a lttng_event_field */
-LTTNG_EXPORT extern const char * const mi_lttng_element_event_field;
-LTTNG_EXPORT extern const char * const mi_lttng_element_event_fields;
-
-/* String related to lttng_event_perf_counter_ctx */
-LTTNG_EXPORT extern const char * const mi_lttng_element_perf_counter_context;
-
-/* Strings related to pid */
-LTTNG_EXPORT extern const char * const mi_lttng_element_pid_id;
-
-/* Strings related to save command */
-LTTNG_EXPORT extern const char * const mi_lttng_element_save;
-
-/* Strings related to load command */
-LTTNG_EXPORT extern const char * const mi_lttng_element_load;
-extern const char * const mi_lttng_element_load_overrides;
-extern const char * const mi_lttng_element_load_override_url;
-
-/* General element of mi_lttng */
-LTTNG_EXPORT extern const char * const mi_lttng_element_empty;
-LTTNG_EXPORT extern const char * const mi_lttng_element_id;
-LTTNG_EXPORT extern const char * const mi_lttng_element_nowrite;
-LTTNG_EXPORT extern const char * const mi_lttng_element_success;
-LTTNG_EXPORT extern const char * const mi_lttng_element_type_enum;
-LTTNG_EXPORT extern const char * const mi_lttng_element_type_float;
-LTTNG_EXPORT extern const char * const mi_lttng_element_type_integer;
-LTTNG_EXPORT extern const char * const mi_lttng_element_type_other;
-LTTNG_EXPORT extern const char * const mi_lttng_element_type_string;
-
-/* String related to loglevel */
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_alert;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_crit;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_function;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_line;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_module;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_process;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_program;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_system;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_unit;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_emerg;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_err;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_info;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_notice;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_unknown;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_warning;
-
-/* String related to loglevel JUL */
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_all;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_config;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_fine;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_finer;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_finest;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_info;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_off;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_severe;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_warning;
-
-/* String related to loglevel Log4j */
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_off;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_fatal;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_error;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_warn;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_info;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_debug;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_trace;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_all;
-
-/* String related to loglevel Python */
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_critical;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_error;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_warning;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_info;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_debug;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_notset;
-
-/* String related to loglevel type */
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_all;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_range;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_single;
-LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_unknown;
-
-/* String related to a lttng_snapshot */
-LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_ctrl_url;
-LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_data_url;
-LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_max_size;
-LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_n_ptr;
-LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_session_name;
-LTTNG_EXPORT extern const char * const mi_lttng_element_snapshots;
-
-/* String related to track/untrack command */
-LTTNG_EXPORT extern const char * const mi_lttng_element_track_untrack_all_wildcard;
-
-extern const char * const mi_lttng_element_session_name;
-
-/* String related to rotate command */
-extern const char * const mi_lttng_element_rotation;
-extern const char * const mi_lttng_element_rotate_status;
-extern const char * const mi_lttng_element_rotation_schedule;
-extern const char * const mi_lttng_element_rotation_schedules;
-extern const char * const mi_lttng_element_rotation_schedule_periodic;
-extern const char * const mi_lttng_element_rotation_schedule_periodic_time_us;
-extern const char * const mi_lttng_element_rotation_schedule_size_threshold;
-extern const char * const mi_lttng_element_rotation_schedule_size_threshold_bytes;
-extern const char * const mi_lttng_element_rotation_schedule_result;
-extern const char * const mi_lttng_element_rotation_schedule_results;
-extern const char * const mi_lttng_element_rotation_state;
-extern const char * const mi_lttng_element_rotation_location;
-extern const char * const mi_lttng_element_rotation_location_local;
-extern const char * const mi_lttng_element_rotation_location_local_absolute_path;
-extern const char * const mi_lttng_element_rotation_location_relay;
-extern const char * const mi_lttng_element_rotation_location_relay_host;
-extern const char * const mi_lttng_element_rotation_location_relay_control_port;
-extern const char * const mi_lttng_element_rotation_location_relay_data_port;
-extern const char * const mi_lttng_element_rotation_location_relay_protocol;
-extern const char * const mi_lttng_element_rotation_location_relay_relative_path;
-
-/* String related to enum lttng_rotation_state */
-extern const char * const mi_lttng_rotation_state_str_ongoing;
-extern const char * const mi_lttng_rotation_state_str_completed;
-extern const char * const mi_lttng_rotation_state_str_expired;
-extern const char * const mi_lttng_rotation_state_str_error;
-
-/* String related to enum lttng_trace_archive_location_relay_protocol_type */
-extern const char * const mi_lttng_rotation_location_relay_protocol_str_tcp;
-
-/* String related to rate_policy elements */
-extern const char *const mi_lttng_element_rate_policy;
-extern const char *const mi_lttng_element_rate_policy_every_n;
-extern const char *const mi_lttng_element_rate_policy_once_after_n;
-
-extern const char
-               *const mi_lttng_element_rate_policy_every_n_interval;
-extern const char
-               *const mi_lttng_element_rate_policy_once_after_n_threshold;
-
-/* String related to action elements */
-extern const char *const mi_lttng_element_action;
-extern const char *const mi_lttng_element_action_list;
-extern const char *const mi_lttng_element_action_notify;
-extern const char *const mi_lttng_element_action_start_session;
-extern const char *const mi_lttng_element_action_stop_session;
-extern const char *const mi_lttng_element_action_rotate_session;
-extern const char *const mi_lttng_element_action_snapshot_session;
-extern const char
-               *const mi_lttng_element_action_snapshot_session_output;
-
-/* String related to condition */
-extern const char *const mi_lttng_element_condition;
-extern const char
-               *const mi_lttng_element_condition_buffer_usage_high;
-extern const char
-               *const mi_lttng_element_condition_buffer_usage_low;
-extern const char
-               *const mi_lttng_element_condition_event_rule_matches;
-extern const char
-               *const mi_lttng_element_condition_session_consumed_size;
-extern const char
-               *const mi_lttng_element_condition_session_rotation;
-extern const char
-               *const mi_lttng_element_condition_session_rotation_completed;
-extern const char
-               *const mi_lttng_element_condition_session_rotation_ongoing;
-extern const char *const mi_lttng_element_condition_channel_name;
-extern const char *const mi_lttng_element_condition_threshold_ratio;
-extern const char *const mi_lttng_element_condition_threshold_bytes;
-
-/* String related to capture descriptor */
-extern const char *const mi_lttng_element_capture_descriptor;
-extern const char *const mi_lttng_element_capture_descriptors;
-
-/* String related to event expression */
-extern const char *const mi_lttng_element_event_expr;
-extern const char *const mi_lttng_element_event_expr_payload_field;
-extern const char
-               *const mi_lttng_element_event_expr_channel_context_field;
-extern const char
-               *const mi_lttng_element_event_expr_app_specific_context_field;
-extern const char
-               *const mi_lttng_element_event_expr_array_field_element;
-
-extern const char *const mi_lttng_element_event_expr_provider_name;
-extern const char *const mi_lttng_element_event_expr_type_name;
-extern const char *const mi_lttng_element_event_expr_index;
-
-/* String related to event rule */
-extern const char *const mi_lttng_element_event_rule;
-
-/* String related to lttng_event_rule */
-extern const char *const mi_lttng_element_event_rule_event_name;
-extern const char *const mi_lttng_element_event_rule_name_pattern;
-extern const char
-               *const mi_lttng_element_event_rule_filter_expression;
-extern const char *const mi_lttng_element_event_rule_jul_logging;
-extern const char *const mi_lttng_element_event_rule_kernel_kprobe;
-extern const char *const mi_lttng_element_event_rule_kernel_syscall;
-extern const char
-               *const mi_lttng_element_event_rule_kernel_tracepoint;
-extern const char *const mi_lttng_element_event_rule_kernel_uprobe;
-extern const char *const mi_lttng_element_event_rule_log4j_logging;
-extern const char *const mi_lttng_element_event_rule_python_logging;
-extern const char
-               *const mi_lttng_element_event_rule_user_tracepoint;
-
-/* String related to lttng_event_rule_kernel_syscall. */
-extern const char
-               *const mi_lttng_element_event_rule_kernel_syscall_emission_site;
-
-/* String related to enum lttng_event_rule_kernel_syscall_emission_site. */
-extern const char *const
-               mi_lttng_event_rule_kernel_syscall_emission_site_entry_exit;
-extern const char
-               *const mi_lttng_event_rule_kernel_syscall_emission_site_entry;
-extern const char
-               *const mi_lttng_event_rule_kernel_syscall_emission_site_exit;
-
-extern const char *const
-               mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions;
-extern const char *const
-               mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion;
-
-/* String related to log level rule. */
-extern const char *const mi_lttng_element_log_level_rule;
-extern const char *const mi_lttng_element_log_level_rule_exactly;
-extern const char
-               *const mi_lttng_element_log_level_rule_at_least_as_severe_as;
-extern const char *const
-               mi_lttng_element_log_level_rule_at_least_as_severe_as_thre;
-extern const char *const mi_lttng_element_log_level_rule_level;
-
-/* String related to kernel probe location. */
-extern const char *const mi_lttng_element_kernel_probe_location;
-extern const char
-               *const mi_lttng_element_kernel_probe_location_symbol_offset;
-extern const char *const
-               mi_lttng_element_kernel_probe_location_symbol_offset_name;
-extern const char *const
-               mi_lttng_element_kernel_probe_location_symbol_offset_offset;
-extern const char
-               *const mi_lttng_element_kernel_probe_location_address;
-extern const char
-               *const mi_lttng_element_kernel_probe_location_address_address;
-
-/* String related to userspace probe location. */
-extern const char *const mi_lttng_element_userspace_probe_location;
-extern const char
-               *const mi_lttng_element_userspace_probe_location_binary_path;
-extern const char
-               *const mi_lttng_element_userspace_probe_location_function;
-extern const char
-               *const mi_lttng_element_userspace_probe_location_function_name;
-extern const char
-               *const mi_lttng_element_userspace_probe_location_lookup_method;
-extern const char *const
-               mi_lttng_element_userspace_probe_location_lookup_method_function_default;
-extern const char *const
-               mi_lttng_element_userspace_probe_location_lookup_method_function_elf;
-extern const char *const
-               mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt;
-extern const char
-               *const mi_lttng_element_userspace_probe_location_tracepoint;
-extern const char *const
-               mi_lttng_element_userspace_probe_location_tracepoint_probe_name;
-extern const char *const
-               mi_lttng_element_userspace_probe_location_tracepoint_provider_name;
-
-/* String related to enum
- * lttng_userspace_probe_location_function_instrumentation_type */
-extern const char *const
-               mi_lttng_element_userspace_probe_location_function_instrumentation_type;
-extern const char *const
-               mi_lttng_userspace_probe_location_function_instrumentation_type_entry;
-
-/* String related to trigger */
-extern const char *const mi_lttng_element_triggers;
-extern const char *const mi_lttng_element_trigger;
-extern const char *const mi_lttng_element_trigger_owner_uid;
-
-/* String related to error_query. */
-extern const char *const mi_lttng_element_error_query_result;
-extern const char
-               *const mi_lttng_element_error_query_result_counter;
-extern const char
-               *const mi_lttng_element_error_query_result_counter_value;
-extern const char
-               *const mi_lttng_element_error_query_result_description;
-extern const char *const mi_lttng_element_error_query_result_name;
-extern const char *const mi_lttng_element_error_query_result_type;
-extern const char *const mi_lttng_element_error_query_results;
-
-/* String related to add-context command */
-extern const char * const mi_lttng_element_context_symbol;
-
-/* Utility string function  */
-const char *mi_lttng_loglevel_string(int value, enum lttng_domain_type domain);
-const char *mi_lttng_logleveltype_string(enum lttng_loglevel_type value);
-const char *mi_lttng_eventfieldtype_string(enum lttng_event_field_type value);
-const char *mi_lttng_domaintype_string(enum lttng_domain_type value);
-const char *mi_lttng_buffertype_string(enum lttng_buffer_type value);
-const char *mi_lttng_rotation_state_string(enum lttng_rotation_state value);
-const char *mi_lttng_trace_archive_location_relay_protocol_type_string(
-               enum lttng_trace_archive_location_relay_protocol_type value);
-
-/*
- * Create an instance of a machine interface writer.
- *
- * fd_output File to which the XML content must be written. The file will be
- * closed once the mi_writer has been destroyed.
- *
- * Returns an instance of a machine interface writer on success, NULL on
- * error.
- */
-struct mi_writer *mi_lttng_writer_create(int fd_output, int mi_output_type);
-
-/*
- * Destroy an instance of a machine interface writer.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the XML document could be closed cleanly. Negative values
- * indicate an error.
- */
-int mi_lttng_writer_destroy(struct mi_writer *writer);
-
-/*
- * Open a command tag and add it's name node.
- *
- * writer An instance of a machine interface writer.
- * command The command name.
- *
- * Returns zero if the XML document could be closed cleanly.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_command_open(struct mi_writer *writer, const char *command);
-
-/*
- * Close a command tag.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the XML document could be closed cleanly.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_command_close(struct mi_writer *writer);
-
-/*
- * Open an element tag.
- *
- * writer An instance of a machine interface writer.
- * element_name Element tag name.
- *
- * Returns zero if the XML document could be closed cleanly.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_open_element(struct mi_writer *writer,
-               const char *element_name);
-
-/*
- * Close the current element tag.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the XML document could be closed cleanly.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_close_element(struct mi_writer *writer);
-
-/*
- * Close multiple element.
- *
- * writer An instance of a machine interface writer.
- * nb_element Number of elements.
- *
- * Returns zero if the XML document could be closed cleanly.
- * Negative values indicate an error.
- */
-int mi_lttng_close_multi_element(struct mi_writer *writer,
-               unsigned int nb_element);
-
-/*
- * Write an element of type unsigned int.
- *
- * writer An instance of a machine interface writer.
- * element_name Element name.
- * value Unsigned int value of the element
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_write_element_unsigned_int(struct mi_writer *writer,
-               const char *element_name, uint64_t value);
-
-/*
- * Write an element of type signed int.
- *
- * writer An instance of a machine interface writer.
- * element_name Element name.
- * value Signed int value of the element.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_write_element_signed_int(struct mi_writer *writer,
-               const char *element_name, int64_t value);
-
-/*
- * Write an element of type boolean.
- *
- * writer An instance of a machine interface writer.
- * element_name Element name.
- * value Boolean value of the element.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_write_element_bool(struct mi_writer *writer,
-               const char *element_name, int value);
-
-/*
- * Write an element of type string.
- *
- * writer An instance of a machine interface writer.
- * element_name Element name.
- * value String value of the element.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_write_element_string(struct mi_writer *writer,
-               const char *element_name, const char *value);
-
-/*
- * Write an element of type double.
- *
- * writer An instance of a machine interface writer.
- * element_name Element name.
- * value Double value of the element.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_writer_write_element_double(struct mi_writer *writer,
-               const char *element_name,
-               double value);
-
-/*
- * Machine interface of struct version.
- *
- * writer An instance of a machine interface writer.
- * version Version struct.
- * lttng_description String value of the version description.
- * lttng_license String value of the version license.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_version(struct mi_writer *writer, struct mi_lttng_version_data *version,
-               const char *lttng_description, const char *lttng_license);
-
-/*
- * Machine interface: open a sessions element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_sessions_open(struct mi_writer *writer);
-
-/*
- * Machine interface of struct session.
- *
- * writer An instance of a machine interface writer.
- * session An instance of a session.
- * is_open Defines whether or not the session element shall be closed.
- *         This should be used carefully and the client
- *         must close the session element.
- *         Use case: nested additional information on a session
- *                  ex: domain,channel event.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_session(struct mi_writer *writer,
-               struct lttng_session *session, int is_open);
-
-/*
- * Machine interface: open a domains element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_domains_open(struct mi_writer *writer);
-
-/*
- * Machine interface of struct domain.
- *
- * writer An instance of a machine interface writer.
- * domain An instance of a domain.
- *
- * is_open Defines whether or not the session element shall be closed.
- *         This should be used carefully and the client
- *         must close the domain element.
- *         Use case: nested addition information on a domain
- *                  ex: channel event.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_domain(struct mi_writer *writer,
-               struct lttng_domain *domain, int is_open);
-
-/*
- * Machine interface: open a channels element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_channels_open(struct mi_writer *writer);
-
-/*
- * Machine interface of struct channel.
- *
- * writer An instance of a machine interface writer.
- * channel An instance of a channel.
- *
- * is_open Defines whether or not the session element shall be closed.
- *         This should be used carefully and the client
- *         must close the channel element.
- *         Use case: nested addition information on a channel.
- *                  ex: channel event.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_channel(struct mi_writer *writer,
-               struct lttng_channel *channel, int is_open);
-
-/*
- * Machine interface of struct channel_attr.
- *
- * writer An instance of a machine interface writer.
- * attr An instance of a channel_attr struct.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_channel_attr(struct mi_writer *writer,
-               struct lttng_channel_attr *attr);
-
-/*
-* Machine interface for event common attributes.
-*
-* writer An instance of a mi writer.
-* event single trace event.
-*
-* The common attribute are:
-* - mi event element
-* - event name
-* - event type
-* - enabled tag
-* - event filter
-*
-* Returns zero if the element's value could be written.
-* Negative values indicate an error.
-*/
-int mi_lttng_event_common_attributes(struct mi_writer *writer,
-               struct lttng_event *event);
-
-/*
- * Machine interface for kernel tracepoint event with a loglevel.
- *
- * writer An instance of a mi writer.
- * event single trace event.
- * domain Event's domain
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_event_tracepoint_loglevel(struct mi_writer *writer,
-               struct lttng_event *event, enum lttng_domain_type domain);
-
-/*
- * Machine interface for kernel tracepoint event with no loglevel.
- *
- * writer An instance of a mi writer.
- * event single trace event.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_event_tracepoint_no_loglevel(struct mi_writer *writer,
-               struct lttng_event *event);
-
-/*
- * Machine interface for kernel function and probe event.
- *
- * writer An instance of a mi writer.
- * event single trace event.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_event_function_probe(struct mi_writer *writer,
-               struct lttng_event *event);
-
-/*
- * Machine interface for kernel function entry event.
- *
- * writer An instance of a mi writer.
- * event single trace event.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_event_function_entry(struct mi_writer *writer,
-               struct lttng_event *event);
-
-/*
- * Machine interface: open an events element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_events_open(struct mi_writer *writer);
-
-/*
- * Machine interface for printing an event.
- * The trace event type currently supported are:
- *  TRACEPOINT,
- *  PROBE,
- *  FUNCTION,
- *  FUNCTION_ENTRY,
- *  SYSCALL
- *
- * writer An instance of a mi writer.
- * event single trace event.
- * is_open Defines whether or not the session element shall be closed.
- *         This should be used carefully and the client
- *         must close the event element.
- *         Use case: nested additional information
- * domain Event's domain
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_event(struct mi_writer *writer, struct lttng_event *event,
-               int is_open, enum lttng_domain_type domain);
-
-/*
- * Machine interface for struct lttng_event_field.
- *
- * writer An instance of a mi writer.
- * field An event_field instance.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_event_field(struct mi_writer *writer,
-               struct lttng_event_field *field);
-
-/*
- * Machine interface: open a event_fields element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element have be written.
- * Negative values indicate an error.
- */
-int mi_lttng_event_fields_open(struct mi_writer *writer);
-
-/*
- * Machine interface: open a trackers element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_trackers_open(struct mi_writer *writer);
-
-/*
- * Machine interface: open a process attribute tracker element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- *
- * Note: A targets element is also opened for each tracker definition
- */
-int mi_lttng_process_attribute_tracker_open(
-               struct mi_writer *writer, enum lttng_process_attr process_attr);
-
-/*
- * Machine interface: open a PIDs element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_pids_open(struct mi_writer *writer);
-
-/*
- * Machine interface: open a processes element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_processes_open(struct mi_writer *writer);
-
-/*
- * Machine interface of a Process.
- *
- * writer An instance of a machine interface writer.
- * pid A PID.
- *
- * is_open Defines whether or not the session element shall be closed.
- *         This should be used carefully and the client
- *         must close the pid element.
- *         Use case: nested addition information on a domain
- *                  ex: channel event.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_process(struct mi_writer *writer, pid_t pid , const char *name,
-               int is_open);
-
-/*
- * TODO: move pid of lttng list -u to process semantic on mi api bump
- * Machine interface of a Process.
- *
- * writer An instance of a machine interface writer.
- * pid A PID.
- *
- * is_open Defines whether or not the session element shall be closed.
- *         This should be used carefully and the client
- *         must close the pid element.
- *         Use case: nested addition information on a domain
- *                  ex: channel event.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_pid(struct mi_writer *writer, pid_t pid , const char *name,
-               int is_open);
-
-/*
- * Machine interface: open a process attribute values element.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_process_attr_values_open(struct mi_writer *writer);
-
-/*
- * Machine interface for track/untrack of all process attribute values.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_all_process_attribute_value(struct mi_writer *writer,
-               enum lttng_process_attr process_attr,
-               bool is_open);
-
-/*
- * Machine interface for track/untrack of an integral process attribute value.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_integral_process_attribute_value(struct mi_writer *writer,
-               enum lttng_process_attr process_attr,
-               int64_t value,
-               bool is_open);
-
-/*
- * Machine interface for track/untrack of a string process attribute value.
- *
- * writer An instance of a machine interface writer.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_string_process_attribute_value(struct mi_writer *writer,
-               enum lttng_process_attr process_attr,
-               const char *value,
-               bool is_open);
-
-/*
- * Machine interface of a context.
- *
- * writer An instance of a machine interface writer
- *
- * context An instance of a lttng_event_context
- *
- * is_open Define if we close the context element
- *         This should be used carefully and the client
- *         need to close the context element.
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_context(struct mi_writer *writer,
-               struct lttng_event_context *context, int is_open);
-
-/*
- * Machine interface of a perf_counter_context.
- *
- * writer An instance of a machine interface writer
- *
- * contest An instance of a lttng_event_perf_counter_ctx
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_perf_counter_context(struct mi_writer *writer,
-               struct lttng_event_perf_counter_ctx  *perf_context);
-
-/*
- * Machine interface of the snapshot list_output.
- * It specifies the session for which we are listing snapshots,
- * and it opens a snapshots element to list a sequence
- * of snapshots.
- *
- * writer An instance of a machine interface writer.
- *
- * session_name: Snapshot output for session "session_name".
- *
- * Note: The client has to close the session and the snapshots elements after
- * having listed every lttng_snapshot_output.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_snapshot_output_session_name(struct mi_writer *writer,
-               const char *session_name);
-
-/*
- * Machine interface of the snapshot output.
- * The machine interface serializes the following attributes:
- * - id: ID of the snapshot output.
- * - name: Name of the output.
- * - data_url : Destination of the output.
- * - ctrl_url: Destination of the output.
- * - max_size: total size of all stream combined.
- *
- * writer An instance of a machine interface writer.
- *
- * output: A list of snapshot_output.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_snapshot_list_output(struct mi_writer *writer,
-               const struct lttng_snapshot_output *output);
-
-/*
- * Machine interface of the output of the command snapshot del output
- * when deleting a snapshot either by id or by name.
- * If the snapshot was found and successfully deleted using its id,
- * it return the id of the snapshot and the current session name on which it
- * was attached.
- *
- * Otherwise, it do the same process with the name of the snapshot, if the
- * snapshot output id is undefined.
- *
- * writer An instance of a machine interface writer.
- *
- * id: ID of the snapshot output.
- *
- * name: Name of the snapshot.
- *
- * current_session_name: Session to which the snapshot belongs.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_snapshot_del_output(struct mi_writer *writer, int id,
-               const char *name, const char *current_session_name);
-
-/*
- * Machine interface of the output of the command snapshot add output
- * when adding a snapshot from a user URL.
- *
- * If the snapshot was successfully added, the machine interface lists
- * these information:
- * - id: ID of the newly add snapshot output.
- * - current_session_name: Name of the session to which the output was added.
- * - ctrl_url: Destination of the output.
- * - max_size: total size of all stream combined.
- *
- * writer An instance of a machine interface writer.
- *
- * current_session_name: Session to which the snapshot belongs.
- *
- * n_ptr:
- *
- * output: iterator over a lttng_snapshot_output_list which contain
- * the snapshot output informations.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_snapshot_add_output(struct mi_writer *writer,
-               const char *current_session_name, const char *n_ptr,
-               struct lttng_snapshot_output *output);
-
-/*
- * Machine interface of the output of the command snapshot
- * record  from a URL (if given).
- *
- * If the snapshot is successfully recorded from a url, the machine interface
- * output the following information:
- * - url: Destination of the output stored in the snapshot.
- *
- * Otherwise, the machine interface output the data and ctrl url received
- * from the command-line.
- *
- * writer An instance of a machine interface writer.
- *
- * current_session_name: Snapshot record for session "current_session_name".
- *
- * ctrl_url, data_url: Destination of the output receive from the command-line.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_snapshot_record(struct mi_writer *writer,
-               const char *current_session_name, const char *url,
-               const char *cmdline_ctrl_url, const char *cmdline_data_url);
-
-/*
- * Machine interface representation of a session rotation schedule.
- *
- * The machine interface serializes the provided schedule as one of the choices
- * from 'rotation_schedule_type'.
- *
- * writer: An instance of a machine interface writer.
- *
- * schedule: An lttng rotation schedule descriptor object.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_rotation_schedule(struct mi_writer *writer,
-               const struct lttng_rotation_schedule *schedule);
-
-/*
- * Machine interface of a session rotation schedule result.
- * This is an element that is part of the output of the enable-rotation and
- * disable-rotation commands.
- *
- * The machine interface provides the following information:
- * - schedule: the session rotation schedule descriptor.
- * - success: whether the sub-command succeeded.
- *
- * writer: An instance of a machine interface writer.
- *
- * schedule: An lttng rotation schedule descriptor object.
- *
- * success: Whether the sub-command suceeded.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_rotation_schedule_result(struct mi_writer *writer,
-               const struct lttng_rotation_schedule *schedule,
-               bool success);
-
-/*
- * Machine interface of a session rotation result.
- * This is an element that is part of the output of the rotate command.
- *
- * The machine interface provides the following information:
- * - session_name: the session to be rotated.
- * - state: the session rotation state.
- * - location: the location of the completed chunk archive.
- *
- * writer: An instance of a machine interface writer.
- *
- * session_name: The session to which the rotate command applies.
- *
- * location: A location descriptor object.
- *
- * success: Whether the sub-command suceeded.
- *
- * Returns zero if the element's value could be written.
- * Negative values indicate an error.
- */
-int mi_lttng_rotate(struct mi_writer *writer,
-               const char *session_name,
-               enum lttng_rotation_state rotation_state,
-               const struct lttng_trace_archive_location *location);
-
-#endif /* _MI_LTTNG_H */
diff --git a/src/common/mi-lttng.hpp b/src/common/mi-lttng.hpp
new file mode 100644 (file)
index 0000000..4f1d0f9
--- /dev/null
@@ -0,0 +1,1120 @@
+/*
+ * Copyright (C) 2014 Jonathan Rajotte <jonathan.r.julien@gmail.com>
+ * Copyright (C) 2014 Olivier Cotte <olivier.cotte@polymtl.ca>
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _MI_LTTNG_H
+#define _MI_LTTNG_H
+
+#include <stdint.h>
+
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/config/session-config.hpp>
+#include <lttng/lttng.h>
+
+/* Don't want to reference snapshot-internal.h here */
+struct lttng_snapshot_output;
+
+/* Instance of a machine interface writer. */
+struct mi_writer {
+       struct config_writer *writer;
+       enum lttng_mi_output_type type;
+};
+
+/*
+ * Version information for the machine interface.
+ */
+struct mi_lttng_version_data {
+       char version[LTTNG_NAME_MAX]; /* Version number of package */
+       uint32_t version_major; /* LTTng-Tools major version number */
+       uint32_t version_minor; /* LTTng-Tools minor version number */
+       uint32_t version_patchlevel; /* LTTng-Tools patchlevel version number */
+       char version_commit[LTTNG_NAME_MAX]; /* Commit hash of the current version */
+       char version_name[LTTNG_NAME_MAX];
+       char package_url[LTTNG_NAME_MAX]; /* Define to the home page for this package. */
+};
+
+/* Error query callbacks. */
+typedef enum lttng_error_code (*mi_lttng_error_query_trigger_cb)(
+               const struct lttng_trigger *trigger,
+               struct lttng_error_query_results **results);
+typedef enum lttng_error_code (*mi_lttng_error_query_condition_cb)(
+               const struct lttng_trigger *trigger,
+               struct lttng_error_query_results **results);
+typedef enum lttng_error_code (*mi_lttng_error_query_action_cb)(
+               const struct lttng_trigger *trigger,
+               const struct lttng_action_path *action_path,
+               struct lttng_error_query_results **results);
+
+struct mi_lttng_error_query_callbacks {
+       mi_lttng_error_query_trigger_cb trigger_cb;
+       mi_lttng_error_query_condition_cb condition_cb;
+       mi_lttng_error_query_action_cb action_cb;
+};
+
+/* Strings related to command */
+LTTNG_EXPORT extern const char * const mi_lttng_element_command;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_action;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_add_context;
+extern const char * const mi_lttng_element_command_add_trigger;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_create;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_destroy;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_disable_channel;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_disable_event;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_enable_channels;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_enable_event;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_list;
+extern const char * const mi_lttng_element_command_list_trigger;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_load;
+extern const char * const mi_lttng_element_command_metadata;
+extern const char * const mi_lttng_element_command_metadata_action;
+extern const char * const mi_lttng_element_command_regenerate;
+extern const char * const mi_lttng_element_command_regenerate_action;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_name;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_output;
+extern const char * const mi_lttng_element_command_remove_trigger;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_save;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_set_session;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_add;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_del;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_list;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_snapshot_record;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_start;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_stop;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_success;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_track;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_untrack;
+LTTNG_EXPORT extern const char * const mi_lttng_element_command_version;
+extern const char * const mi_lttng_element_command_rotate;
+extern const char * const mi_lttng_element_command_enable_rotation;
+extern const char * const mi_lttng_element_command_disable_rotation;
+extern const char * const mi_lttng_element_command_clear;
+
+/* Strings related to version command */
+LTTNG_EXPORT extern const char * const mi_lttng_element_version;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_commit;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_description;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_license;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_major;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_minor;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_patch_level;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_str;
+LTTNG_EXPORT extern const char * const mi_lttng_element_version_web;
+
+/* String related to a lttng_event_field */
+LTTNG_EXPORT extern const char * const mi_lttng_element_event_field;
+LTTNG_EXPORT extern const char * const mi_lttng_element_event_fields;
+
+/* String related to lttng_event_perf_counter_ctx */
+LTTNG_EXPORT extern const char * const mi_lttng_element_perf_counter_context;
+
+/* Strings related to pid */
+LTTNG_EXPORT extern const char * const mi_lttng_element_pid_id;
+
+/* Strings related to save command */
+LTTNG_EXPORT extern const char * const mi_lttng_element_save;
+
+/* Strings related to load command */
+LTTNG_EXPORT extern const char * const mi_lttng_element_load;
+extern const char * const mi_lttng_element_load_overrides;
+extern const char * const mi_lttng_element_load_override_url;
+
+/* General element of mi_lttng */
+LTTNG_EXPORT extern const char * const mi_lttng_element_empty;
+LTTNG_EXPORT extern const char * const mi_lttng_element_id;
+LTTNG_EXPORT extern const char * const mi_lttng_element_nowrite;
+LTTNG_EXPORT extern const char * const mi_lttng_element_success;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_enum;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_float;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_integer;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_other;
+LTTNG_EXPORT extern const char * const mi_lttng_element_type_string;
+
+/* String related to loglevel */
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_alert;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_crit;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_function;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_line;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_module;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_process;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_program;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_system;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_debug_unit;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_emerg;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_err;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_info;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_notice;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_unknown;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_warning;
+
+/* String related to loglevel JUL */
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_all;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_config;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_fine;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_finer;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_finest;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_info;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_off;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_severe;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_jul_warning;
+
+/* String related to loglevel Log4j */
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_off;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_fatal;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_error;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_warn;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_info;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_debug;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_trace;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_log4j_all;
+
+/* String related to loglevel Python */
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_critical;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_error;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_warning;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_info;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_debug;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_str_python_notset;
+
+/* String related to loglevel type */
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_all;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_range;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_single;
+LTTNG_EXPORT extern const char * const mi_lttng_loglevel_type_unknown;
+
+/* String related to a lttng_snapshot */
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_ctrl_url;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_data_url;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_max_size;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_n_ptr;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshot_session_name;
+LTTNG_EXPORT extern const char * const mi_lttng_element_snapshots;
+
+/* String related to track/untrack command */
+LTTNG_EXPORT extern const char * const mi_lttng_element_track_untrack_all_wildcard;
+
+extern const char * const mi_lttng_element_session_name;
+
+/* String related to rotate command */
+extern const char * const mi_lttng_element_rotation;
+extern const char * const mi_lttng_element_rotate_status;
+extern const char * const mi_lttng_element_rotation_schedule;
+extern const char * const mi_lttng_element_rotation_schedules;
+extern const char * const mi_lttng_element_rotation_schedule_periodic;
+extern const char * const mi_lttng_element_rotation_schedule_periodic_time_us;
+extern const char * const mi_lttng_element_rotation_schedule_size_threshold;
+extern const char * const mi_lttng_element_rotation_schedule_size_threshold_bytes;
+extern const char * const mi_lttng_element_rotation_schedule_result;
+extern const char * const mi_lttng_element_rotation_schedule_results;
+extern const char * const mi_lttng_element_rotation_state;
+extern const char * const mi_lttng_element_rotation_location;
+extern const char * const mi_lttng_element_rotation_location_local;
+extern const char * const mi_lttng_element_rotation_location_local_absolute_path;
+extern const char * const mi_lttng_element_rotation_location_relay;
+extern const char * const mi_lttng_element_rotation_location_relay_host;
+extern const char * const mi_lttng_element_rotation_location_relay_control_port;
+extern const char * const mi_lttng_element_rotation_location_relay_data_port;
+extern const char * const mi_lttng_element_rotation_location_relay_protocol;
+extern const char * const mi_lttng_element_rotation_location_relay_relative_path;
+
+/* String related to enum lttng_rotation_state */
+extern const char * const mi_lttng_rotation_state_str_ongoing;
+extern const char * const mi_lttng_rotation_state_str_completed;
+extern const char * const mi_lttng_rotation_state_str_expired;
+extern const char * const mi_lttng_rotation_state_str_error;
+
+/* String related to enum lttng_trace_archive_location_relay_protocol_type */
+extern const char * const mi_lttng_rotation_location_relay_protocol_str_tcp;
+
+/* String related to rate_policy elements */
+extern const char *const mi_lttng_element_rate_policy;
+extern const char *const mi_lttng_element_rate_policy_every_n;
+extern const char *const mi_lttng_element_rate_policy_once_after_n;
+
+extern const char
+               *const mi_lttng_element_rate_policy_every_n_interval;
+extern const char
+               *const mi_lttng_element_rate_policy_once_after_n_threshold;
+
+/* String related to action elements */
+extern const char *const mi_lttng_element_action;
+extern const char *const mi_lttng_element_action_list;
+extern const char *const mi_lttng_element_action_notify;
+extern const char *const mi_lttng_element_action_start_session;
+extern const char *const mi_lttng_element_action_stop_session;
+extern const char *const mi_lttng_element_action_rotate_session;
+extern const char *const mi_lttng_element_action_snapshot_session;
+extern const char
+               *const mi_lttng_element_action_snapshot_session_output;
+
+/* String related to condition */
+extern const char *const mi_lttng_element_condition;
+extern const char
+               *const mi_lttng_element_condition_buffer_usage_high;
+extern const char
+               *const mi_lttng_element_condition_buffer_usage_low;
+extern const char
+               *const mi_lttng_element_condition_event_rule_matches;
+extern const char
+               *const mi_lttng_element_condition_session_consumed_size;
+extern const char
+               *const mi_lttng_element_condition_session_rotation;
+extern const char
+               *const mi_lttng_element_condition_session_rotation_completed;
+extern const char
+               *const mi_lttng_element_condition_session_rotation_ongoing;
+extern const char *const mi_lttng_element_condition_channel_name;
+extern const char *const mi_lttng_element_condition_threshold_ratio;
+extern const char *const mi_lttng_element_condition_threshold_bytes;
+
+/* String related to capture descriptor */
+extern const char *const mi_lttng_element_capture_descriptor;
+extern const char *const mi_lttng_element_capture_descriptors;
+
+/* String related to event expression */
+extern const char *const mi_lttng_element_event_expr;
+extern const char *const mi_lttng_element_event_expr_payload_field;
+extern const char
+               *const mi_lttng_element_event_expr_channel_context_field;
+extern const char
+               *const mi_lttng_element_event_expr_app_specific_context_field;
+extern const char
+               *const mi_lttng_element_event_expr_array_field_element;
+
+extern const char *const mi_lttng_element_event_expr_provider_name;
+extern const char *const mi_lttng_element_event_expr_type_name;
+extern const char *const mi_lttng_element_event_expr_index;
+
+/* String related to event rule */
+extern const char *const mi_lttng_element_event_rule;
+
+/* String related to lttng_event_rule */
+extern const char *const mi_lttng_element_event_rule_event_name;
+extern const char *const mi_lttng_element_event_rule_name_pattern;
+extern const char
+               *const mi_lttng_element_event_rule_filter_expression;
+extern const char *const mi_lttng_element_event_rule_jul_logging;
+extern const char *const mi_lttng_element_event_rule_kernel_kprobe;
+extern const char *const mi_lttng_element_event_rule_kernel_syscall;
+extern const char
+               *const mi_lttng_element_event_rule_kernel_tracepoint;
+extern const char *const mi_lttng_element_event_rule_kernel_uprobe;
+extern const char *const mi_lttng_element_event_rule_log4j_logging;
+extern const char *const mi_lttng_element_event_rule_python_logging;
+extern const char
+               *const mi_lttng_element_event_rule_user_tracepoint;
+
+/* String related to lttng_event_rule_kernel_syscall. */
+extern const char
+               *const mi_lttng_element_event_rule_kernel_syscall_emission_site;
+
+/* String related to enum lttng_event_rule_kernel_syscall_emission_site. */
+extern const char *const
+               mi_lttng_event_rule_kernel_syscall_emission_site_entry_exit;
+extern const char
+               *const mi_lttng_event_rule_kernel_syscall_emission_site_entry;
+extern const char
+               *const mi_lttng_event_rule_kernel_syscall_emission_site_exit;
+
+extern const char *const
+               mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions;
+extern const char *const
+               mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion;
+
+/* String related to log level rule. */
+extern const char *const mi_lttng_element_log_level_rule;
+extern const char *const mi_lttng_element_log_level_rule_exactly;
+extern const char
+               *const mi_lttng_element_log_level_rule_at_least_as_severe_as;
+extern const char *const
+               mi_lttng_element_log_level_rule_at_least_as_severe_as_thre;
+extern const char *const mi_lttng_element_log_level_rule_level;
+
+/* String related to kernel probe location. */
+extern const char *const mi_lttng_element_kernel_probe_location;
+extern const char
+               *const mi_lttng_element_kernel_probe_location_symbol_offset;
+extern const char *const
+               mi_lttng_element_kernel_probe_location_symbol_offset_name;
+extern const char *const
+               mi_lttng_element_kernel_probe_location_symbol_offset_offset;
+extern const char
+               *const mi_lttng_element_kernel_probe_location_address;
+extern const char
+               *const mi_lttng_element_kernel_probe_location_address_address;
+
+/* String related to userspace probe location. */
+extern const char *const mi_lttng_element_userspace_probe_location;
+extern const char
+               *const mi_lttng_element_userspace_probe_location_binary_path;
+extern const char
+               *const mi_lttng_element_userspace_probe_location_function;
+extern const char
+               *const mi_lttng_element_userspace_probe_location_function_name;
+extern const char
+               *const mi_lttng_element_userspace_probe_location_lookup_method;
+extern const char *const
+               mi_lttng_element_userspace_probe_location_lookup_method_function_default;
+extern const char *const
+               mi_lttng_element_userspace_probe_location_lookup_method_function_elf;
+extern const char *const
+               mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt;
+extern const char
+               *const mi_lttng_element_userspace_probe_location_tracepoint;
+extern const char *const
+               mi_lttng_element_userspace_probe_location_tracepoint_probe_name;
+extern const char *const
+               mi_lttng_element_userspace_probe_location_tracepoint_provider_name;
+
+/* String related to enum
+ * lttng_userspace_probe_location_function_instrumentation_type */
+extern const char *const
+               mi_lttng_element_userspace_probe_location_function_instrumentation_type;
+extern const char *const
+               mi_lttng_userspace_probe_location_function_instrumentation_type_entry;
+
+/* String related to trigger */
+extern const char *const mi_lttng_element_triggers;
+extern const char *const mi_lttng_element_trigger;
+extern const char *const mi_lttng_element_trigger_owner_uid;
+
+/* String related to error_query. */
+extern const char *const mi_lttng_element_error_query_result;
+extern const char
+               *const mi_lttng_element_error_query_result_counter;
+extern const char
+               *const mi_lttng_element_error_query_result_counter_value;
+extern const char
+               *const mi_lttng_element_error_query_result_description;
+extern const char *const mi_lttng_element_error_query_result_name;
+extern const char *const mi_lttng_element_error_query_result_type;
+extern const char *const mi_lttng_element_error_query_results;
+
+/* String related to add-context command */
+extern const char * const mi_lttng_element_context_symbol;
+
+/* Utility string function  */
+const char *mi_lttng_loglevel_string(int value, enum lttng_domain_type domain);
+const char *mi_lttng_logleveltype_string(enum lttng_loglevel_type value);
+const char *mi_lttng_eventfieldtype_string(enum lttng_event_field_type value);
+const char *mi_lttng_domaintype_string(enum lttng_domain_type value);
+const char *mi_lttng_buffertype_string(enum lttng_buffer_type value);
+const char *mi_lttng_rotation_state_string(enum lttng_rotation_state value);
+const char *mi_lttng_trace_archive_location_relay_protocol_type_string(
+               enum lttng_trace_archive_location_relay_protocol_type value);
+
+/*
+ * Create an instance of a machine interface writer.
+ *
+ * fd_output File to which the XML content must be written. The file will be
+ * closed once the mi_writer has been destroyed.
+ *
+ * Returns an instance of a machine interface writer on success, NULL on
+ * error.
+ */
+struct mi_writer *mi_lttng_writer_create(int fd_output, int mi_output_type);
+
+/*
+ * Destroy an instance of a machine interface writer.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the XML document could be closed cleanly. Negative values
+ * indicate an error.
+ */
+int mi_lttng_writer_destroy(struct mi_writer *writer);
+
+/*
+ * Open a command tag and add it's name node.
+ *
+ * writer An instance of a machine interface writer.
+ * command The command name.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_command_open(struct mi_writer *writer, const char *command);
+
+/*
+ * Close a command tag.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_command_close(struct mi_writer *writer);
+
+/*
+ * Open an element tag.
+ *
+ * writer An instance of a machine interface writer.
+ * element_name Element tag name.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_open_element(struct mi_writer *writer,
+               const char *element_name);
+
+/*
+ * Close the current element tag.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_close_element(struct mi_writer *writer);
+
+/*
+ * Close multiple element.
+ *
+ * writer An instance of a machine interface writer.
+ * nb_element Number of elements.
+ *
+ * Returns zero if the XML document could be closed cleanly.
+ * Negative values indicate an error.
+ */
+int mi_lttng_close_multi_element(struct mi_writer *writer,
+               unsigned int nb_element);
+
+/*
+ * Write an element of type unsigned int.
+ *
+ * writer An instance of a machine interface writer.
+ * element_name Element name.
+ * value Unsigned int value of the element
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_unsigned_int(struct mi_writer *writer,
+               const char *element_name, uint64_t value);
+
+/*
+ * Write an element of type signed int.
+ *
+ * writer An instance of a machine interface writer.
+ * element_name Element name.
+ * value Signed int value of the element.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_signed_int(struct mi_writer *writer,
+               const char *element_name, int64_t value);
+
+/*
+ * Write an element of type boolean.
+ *
+ * writer An instance of a machine interface writer.
+ * element_name Element name.
+ * value Boolean value of the element.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_bool(struct mi_writer *writer,
+               const char *element_name, int value);
+
+/*
+ * Write an element of type string.
+ *
+ * writer An instance of a machine interface writer.
+ * element_name Element name.
+ * value String value of the element.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_string(struct mi_writer *writer,
+               const char *element_name, const char *value);
+
+/*
+ * Write an element of type double.
+ *
+ * writer An instance of a machine interface writer.
+ * element_name Element name.
+ * value Double value of the element.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_writer_write_element_double(struct mi_writer *writer,
+               const char *element_name,
+               double value);
+
+/*
+ * Machine interface of struct version.
+ *
+ * writer An instance of a machine interface writer.
+ * version Version struct.
+ * lttng_description String value of the version description.
+ * lttng_license String value of the version license.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_version(struct mi_writer *writer, struct mi_lttng_version_data *version,
+               const char *lttng_description, const char *lttng_license);
+
+/*
+ * Machine interface: open a sessions element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_sessions_open(struct mi_writer *writer);
+
+/*
+ * Machine interface of struct session.
+ *
+ * writer An instance of a machine interface writer.
+ * session An instance of a session.
+ * is_open Defines whether or not the session element shall be closed.
+ *         This should be used carefully and the client
+ *         must close the session element.
+ *         Use case: nested additional information on a session
+ *                  ex: domain,channel event.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_session(struct mi_writer *writer,
+               struct lttng_session *session, int is_open);
+
+/*
+ * Machine interface: open a domains element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_domains_open(struct mi_writer *writer);
+
+/*
+ * Machine interface of struct domain.
+ *
+ * writer An instance of a machine interface writer.
+ * domain An instance of a domain.
+ *
+ * is_open Defines whether or not the session element shall be closed.
+ *         This should be used carefully and the client
+ *         must close the domain element.
+ *         Use case: nested addition information on a domain
+ *                  ex: channel event.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_domain(struct mi_writer *writer,
+               struct lttng_domain *domain, int is_open);
+
+/*
+ * Machine interface: open a channels element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_channels_open(struct mi_writer *writer);
+
+/*
+ * Machine interface of struct channel.
+ *
+ * writer An instance of a machine interface writer.
+ * channel An instance of a channel.
+ *
+ * is_open Defines whether or not the session element shall be closed.
+ *         This should be used carefully and the client
+ *         must close the channel element.
+ *         Use case: nested addition information on a channel.
+ *                  ex: channel event.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_channel(struct mi_writer *writer,
+               struct lttng_channel *channel, int is_open);
+
+/*
+ * Machine interface of struct channel_attr.
+ *
+ * writer An instance of a machine interface writer.
+ * attr An instance of a channel_attr struct.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_channel_attr(struct mi_writer *writer,
+               struct lttng_channel_attr *attr);
+
+/*
+* Machine interface for event common attributes.
+*
+* writer An instance of a mi writer.
+* event single trace event.
+*
+* The common attribute are:
+* - mi event element
+* - event name
+* - event type
+* - enabled tag
+* - event filter
+*
+* Returns zero if the element's value could be written.
+* Negative values indicate an error.
+*/
+int mi_lttng_event_common_attributes(struct mi_writer *writer,
+               struct lttng_event *event);
+
+/*
+ * Machine interface for kernel tracepoint event with a loglevel.
+ *
+ * writer An instance of a mi writer.
+ * event single trace event.
+ * domain Event's domain
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_event_tracepoint_loglevel(struct mi_writer *writer,
+               struct lttng_event *event, enum lttng_domain_type domain);
+
+/*
+ * Machine interface for kernel tracepoint event with no loglevel.
+ *
+ * writer An instance of a mi writer.
+ * event single trace event.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_event_tracepoint_no_loglevel(struct mi_writer *writer,
+               struct lttng_event *event);
+
+/*
+ * Machine interface for kernel function and probe event.
+ *
+ * writer An instance of a mi writer.
+ * event single trace event.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_event_function_probe(struct mi_writer *writer,
+               struct lttng_event *event);
+
+/*
+ * Machine interface for kernel function entry event.
+ *
+ * writer An instance of a mi writer.
+ * event single trace event.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_event_function_entry(struct mi_writer *writer,
+               struct lttng_event *event);
+
+/*
+ * Machine interface: open an events element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_events_open(struct mi_writer *writer);
+
+/*
+ * Machine interface for printing an event.
+ * The trace event type currently supported are:
+ *  TRACEPOINT,
+ *  PROBE,
+ *  FUNCTION,
+ *  FUNCTION_ENTRY,
+ *  SYSCALL
+ *
+ * writer An instance of a mi writer.
+ * event single trace event.
+ * is_open Defines whether or not the session element shall be closed.
+ *         This should be used carefully and the client
+ *         must close the event element.
+ *         Use case: nested additional information
+ * domain Event's domain
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_event(struct mi_writer *writer, struct lttng_event *event,
+               int is_open, enum lttng_domain_type domain);
+
+/*
+ * Machine interface for struct lttng_event_field.
+ *
+ * writer An instance of a mi writer.
+ * field An event_field instance.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_event_field(struct mi_writer *writer,
+               struct lttng_event_field *field);
+
+/*
+ * Machine interface: open a event_fields element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element have be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_event_fields_open(struct mi_writer *writer);
+
+/*
+ * Machine interface: open a trackers element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_trackers_open(struct mi_writer *writer);
+
+/*
+ * Machine interface: open a process attribute tracker element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ *
+ * Note: A targets element is also opened for each tracker definition
+ */
+int mi_lttng_process_attribute_tracker_open(
+               struct mi_writer *writer, enum lttng_process_attr process_attr);
+
+/*
+ * Machine interface: open a PIDs element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_pids_open(struct mi_writer *writer);
+
+/*
+ * Machine interface: open a processes element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_processes_open(struct mi_writer *writer);
+
+/*
+ * Machine interface of a Process.
+ *
+ * writer An instance of a machine interface writer.
+ * pid A PID.
+ *
+ * is_open Defines whether or not the session element shall be closed.
+ *         This should be used carefully and the client
+ *         must close the pid element.
+ *         Use case: nested addition information on a domain
+ *                  ex: channel event.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_process(struct mi_writer *writer, pid_t pid , const char *name,
+               int is_open);
+
+/*
+ * TODO: move pid of lttng list -u to process semantic on mi api bump
+ * Machine interface of a Process.
+ *
+ * writer An instance of a machine interface writer.
+ * pid A PID.
+ *
+ * is_open Defines whether or not the session element shall be closed.
+ *         This should be used carefully and the client
+ *         must close the pid element.
+ *         Use case: nested addition information on a domain
+ *                  ex: channel event.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_pid(struct mi_writer *writer, pid_t pid , const char *name,
+               int is_open);
+
+/*
+ * Machine interface: open a process attribute values element.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_process_attr_values_open(struct mi_writer *writer);
+
+/*
+ * Machine interface for track/untrack of all process attribute values.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_all_process_attribute_value(struct mi_writer *writer,
+               enum lttng_process_attr process_attr,
+               bool is_open);
+
+/*
+ * Machine interface for track/untrack of an integral process attribute value.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_integral_process_attribute_value(struct mi_writer *writer,
+               enum lttng_process_attr process_attr,
+               int64_t value,
+               bool is_open);
+
+/*
+ * Machine interface for track/untrack of a string process attribute value.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_string_process_attribute_value(struct mi_writer *writer,
+               enum lttng_process_attr process_attr,
+               const char *value,
+               bool is_open);
+
+/*
+ * Machine interface of a context.
+ *
+ * writer An instance of a machine interface writer
+ *
+ * context An instance of a lttng_event_context
+ *
+ * is_open Define if we close the context element
+ *         This should be used carefully and the client
+ *         need to close the context element.
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_context(struct mi_writer *writer,
+               struct lttng_event_context *context, int is_open);
+
+/*
+ * Machine interface of a perf_counter_context.
+ *
+ * writer An instance of a machine interface writer
+ *
+ * contest An instance of a lttng_event_perf_counter_ctx
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_perf_counter_context(struct mi_writer *writer,
+               struct lttng_event_perf_counter_ctx  *perf_context);
+
+/*
+ * Machine interface of the snapshot list_output.
+ * It specifies the session for which we are listing snapshots,
+ * and it opens a snapshots element to list a sequence
+ * of snapshots.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * session_name: Snapshot output for session "session_name".
+ *
+ * Note: The client has to close the session and the snapshots elements after
+ * having listed every lttng_snapshot_output.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_snapshot_output_session_name(struct mi_writer *writer,
+               const char *session_name);
+
+/*
+ * Machine interface of the snapshot output.
+ * The machine interface serializes the following attributes:
+ * - id: ID of the snapshot output.
+ * - name: Name of the output.
+ * - data_url : Destination of the output.
+ * - ctrl_url: Destination of the output.
+ * - max_size: total size of all stream combined.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * output: A list of snapshot_output.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_snapshot_list_output(struct mi_writer *writer,
+               const struct lttng_snapshot_output *output);
+
+/*
+ * Machine interface of the output of the command snapshot del output
+ * when deleting a snapshot either by id or by name.
+ * If the snapshot was found and successfully deleted using its id,
+ * it return the id of the snapshot and the current session name on which it
+ * was attached.
+ *
+ * Otherwise, it do the same process with the name of the snapshot, if the
+ * snapshot output id is undefined.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * id: ID of the snapshot output.
+ *
+ * name: Name of the snapshot.
+ *
+ * current_session_name: Session to which the snapshot belongs.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_snapshot_del_output(struct mi_writer *writer, int id,
+               const char *name, const char *current_session_name);
+
+/*
+ * Machine interface of the output of the command snapshot add output
+ * when adding a snapshot from a user URL.
+ *
+ * If the snapshot was successfully added, the machine interface lists
+ * these information:
+ * - id: ID of the newly add snapshot output.
+ * - current_session_name: Name of the session to which the output was added.
+ * - ctrl_url: Destination of the output.
+ * - max_size: total size of all stream combined.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * current_session_name: Session to which the snapshot belongs.
+ *
+ * n_ptr:
+ *
+ * output: iterator over a lttng_snapshot_output_list which contain
+ * the snapshot output informations.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_snapshot_add_output(struct mi_writer *writer,
+               const char *current_session_name, const char *n_ptr,
+               struct lttng_snapshot_output *output);
+
+/*
+ * Machine interface of the output of the command snapshot
+ * record  from a URL (if given).
+ *
+ * If the snapshot is successfully recorded from a url, the machine interface
+ * output the following information:
+ * - url: Destination of the output stored in the snapshot.
+ *
+ * Otherwise, the machine interface output the data and ctrl url received
+ * from the command-line.
+ *
+ * writer An instance of a machine interface writer.
+ *
+ * current_session_name: Snapshot record for session "current_session_name".
+ *
+ * ctrl_url, data_url: Destination of the output receive from the command-line.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_snapshot_record(struct mi_writer *writer,
+               const char *current_session_name, const char *url,
+               const char *cmdline_ctrl_url, const char *cmdline_data_url);
+
+/*
+ * Machine interface representation of a session rotation schedule.
+ *
+ * The machine interface serializes the provided schedule as one of the choices
+ * from 'rotation_schedule_type'.
+ *
+ * writer: An instance of a machine interface writer.
+ *
+ * schedule: An lttng rotation schedule descriptor object.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_rotation_schedule(struct mi_writer *writer,
+               const struct lttng_rotation_schedule *schedule);
+
+/*
+ * Machine interface of a session rotation schedule result.
+ * This is an element that is part of the output of the enable-rotation and
+ * disable-rotation commands.
+ *
+ * The machine interface provides the following information:
+ * - schedule: the session rotation schedule descriptor.
+ * - success: whether the sub-command succeeded.
+ *
+ * writer: An instance of a machine interface writer.
+ *
+ * schedule: An lttng rotation schedule descriptor object.
+ *
+ * success: Whether the sub-command suceeded.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_rotation_schedule_result(struct mi_writer *writer,
+               const struct lttng_rotation_schedule *schedule,
+               bool success);
+
+/*
+ * Machine interface of a session rotation result.
+ * This is an element that is part of the output of the rotate command.
+ *
+ * The machine interface provides the following information:
+ * - session_name: the session to be rotated.
+ * - state: the session rotation state.
+ * - location: the location of the completed chunk archive.
+ *
+ * writer: An instance of a machine interface writer.
+ *
+ * session_name: The session to which the rotate command applies.
+ *
+ * location: A location descriptor object.
+ *
+ * success: Whether the sub-command suceeded.
+ *
+ * Returns zero if the element's value could be written.
+ * Negative values indicate an error.
+ */
+int mi_lttng_rotate(struct mi_writer *writer,
+               const char *session_name,
+               enum lttng_rotation_state rotation_state,
+               const struct lttng_trace_archive_location *location);
+
+#endif /* _MI_LTTNG_H */
index 989c20ade5e1f126ffcf2609e7f0eea21e2f4028..248dd42e7529cf3f9ae16fdb69f0d4e2f9c013dc 100644 (file)
@@ -5,14 +5,14 @@
  *
  */
 
-#include <lttng/notification/notification-internal.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/evaluation-internal.h>
+#include <lttng/notification/notification-internal.hpp>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/evaluation-internal.hpp>
 #include <lttng/condition/condition.h>
 #include <lttng/condition/evaluation.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
+#include <lttng/trigger/trigger-internal.hpp>
+#include <common/payload.hpp>
+#include <common/payload-view.hpp>
 
 struct lttng_notification *lttng_notification_create(
                struct lttng_trigger *trigger,
diff --git a/src/common/optional.h b/src/common/optional.h
deleted file mode 100644 (file)
index 52139d5..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_OPTIONAL_H
-#define LTTNG_OPTIONAL_H
-
-#include <stdint.h>
-
-/*
- * Define wrapper structure representing an optional value.
- *
- * This macro defines an "is_set" boolean field that must be checked
- * when accessing the optional field. This "is_set" field provides
- * the semantics that would be expected of a typical "raw pointer" field
- * which would be checked for NULL.
- *
- * Prefer using this macro where "special" values would be used, e.g.
- * -1ULL for uint64_t types.
- *
- * Declaration example:
- * struct my_struct {
- *     int a;
- *     LTTNG_OPTIONAL(int) b;
- * };
- *
- * Usage example:
- * struct my_struct foo = LTTNG_OPTIONAL_INIT;
- *
- * LTTNG_OPTIONAL_SET(&foo.b, 42);
- * if (foo.b.is_set) {
- *     printf("%d", foo.b.value);
- * }
- *
- * LTTNG_OPTIONAL_UNSET(&foo.b);
- */
-#define LTTNG_OPTIONAL(type) \
-       struct {             \
-               uint8_t is_set; \
-               type value;  \
-       }
-
-/*
- * Alias used for communication structures. If the layout of an LTTNG_OPTIONAL
- * is changed, the original layout should still be used for communication
- * purposes.
- *
- * LTTNG_OPTIONAL_COMM should be combined with the LTTNG_PACKED macro when
- * used for IPC / network communication.
- */
-#define LTTNG_OPTIONAL_COMM LTTNG_OPTIONAL
-
-/*
- * This macro is available as a 'convenience' to allow sites that assume
- * an optional value is set to LTTNG_ASSERT() that it is set when accessing it.
- *
- * Since this returns the 'optional' by value, it is not suitable for all
- * wrapped optional types. It is meant to be used with PODs.
- */
-#define LTTNG_OPTIONAL_GET(optional)                   \
-       ({                                              \
-               LTTNG_ASSERT((optional).is_set);                \
-               (optional).value;                       \
-       })
-
-/*
- * This macro is available as a 'convenience' to allow sites that assume
- * an optional value is set to LTTNG_ASSERT() that it is set when fecthing the
- * underlying value's address.
- */
-#define LTTNG_OPTIONAL_GET_PTR(optional)                       \
-       ({                                              \
-               LTTNG_ASSERT((optional).is_set);                \
-               &(optional).value;                      \
-       })
-
-/*
- * Initialize an optional field as unset.
- *
- * The wrapped field is set to the value it would gave if it had static storage
- * duration.
- */
-#define LTTNG_OPTIONAL_INIT_UNSET { .is_set = 0 }
-
-/*
- * Initialize an optional field as 'set' with a given value.
- */
-#define LTTNG_OPTIONAL_INIT_VALUE(val) { .is_set = 1, .value = val }
-
-/* Set the value of an optional field. */
-#define LTTNG_OPTIONAL_SET(field_ptr, val)     \
-       do {                                    \
-               (field_ptr)->is_set = 1;        \
-               (field_ptr)->value = (val);     \
-       } while (0)
-
-/* Put an optional field in the "unset" (NULL-ed) state. */
-#define LTTNG_OPTIONAL_UNSET(field_ptr)                \
-       do {                                    \
-               (field_ptr)->is_set = 0;        \
-       } while (0)
-
-#endif /* LTTNG_OPTIONAL_H */
diff --git a/src/common/optional.hpp b/src/common/optional.hpp
new file mode 100644 (file)
index 0000000..52139d5
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_OPTIONAL_H
+#define LTTNG_OPTIONAL_H
+
+#include <stdint.h>
+
+/*
+ * Define wrapper structure representing an optional value.
+ *
+ * This macro defines an "is_set" boolean field that must be checked
+ * when accessing the optional field. This "is_set" field provides
+ * the semantics that would be expected of a typical "raw pointer" field
+ * which would be checked for NULL.
+ *
+ * Prefer using this macro where "special" values would be used, e.g.
+ * -1ULL for uint64_t types.
+ *
+ * Declaration example:
+ * struct my_struct {
+ *     int a;
+ *     LTTNG_OPTIONAL(int) b;
+ * };
+ *
+ * Usage example:
+ * struct my_struct foo = LTTNG_OPTIONAL_INIT;
+ *
+ * LTTNG_OPTIONAL_SET(&foo.b, 42);
+ * if (foo.b.is_set) {
+ *     printf("%d", foo.b.value);
+ * }
+ *
+ * LTTNG_OPTIONAL_UNSET(&foo.b);
+ */
+#define LTTNG_OPTIONAL(type) \
+       struct {             \
+               uint8_t is_set; \
+               type value;  \
+       }
+
+/*
+ * Alias used for communication structures. If the layout of an LTTNG_OPTIONAL
+ * is changed, the original layout should still be used for communication
+ * purposes.
+ *
+ * LTTNG_OPTIONAL_COMM should be combined with the LTTNG_PACKED macro when
+ * used for IPC / network communication.
+ */
+#define LTTNG_OPTIONAL_COMM LTTNG_OPTIONAL
+
+/*
+ * This macro is available as a 'convenience' to allow sites that assume
+ * an optional value is set to LTTNG_ASSERT() that it is set when accessing it.
+ *
+ * Since this returns the 'optional' by value, it is not suitable for all
+ * wrapped optional types. It is meant to be used with PODs.
+ */
+#define LTTNG_OPTIONAL_GET(optional)                   \
+       ({                                              \
+               LTTNG_ASSERT((optional).is_set);                \
+               (optional).value;                       \
+       })
+
+/*
+ * This macro is available as a 'convenience' to allow sites that assume
+ * an optional value is set to LTTNG_ASSERT() that it is set when fecthing the
+ * underlying value's address.
+ */
+#define LTTNG_OPTIONAL_GET_PTR(optional)                       \
+       ({                                              \
+               LTTNG_ASSERT((optional).is_set);                \
+               &(optional).value;                      \
+       })
+
+/*
+ * Initialize an optional field as unset.
+ *
+ * The wrapped field is set to the value it would gave if it had static storage
+ * duration.
+ */
+#define LTTNG_OPTIONAL_INIT_UNSET { .is_set = 0 }
+
+/*
+ * Initialize an optional field as 'set' with a given value.
+ */
+#define LTTNG_OPTIONAL_INIT_VALUE(val) { .is_set = 1, .value = val }
+
+/* Set the value of an optional field. */
+#define LTTNG_OPTIONAL_SET(field_ptr, val)     \
+       do {                                    \
+               (field_ptr)->is_set = 1;        \
+               (field_ptr)->value = (val);     \
+       } while (0)
+
+/* Put an optional field in the "unset" (NULL-ed) state. */
+#define LTTNG_OPTIONAL_UNSET(field_ptr)                \
+       do {                                    \
+               (field_ptr)->is_set = 0;        \
+       } while (0)
+
+#endif /* LTTNG_OPTIONAL_H */
index 3ea043c8aa0c7fb4a9051a890e020465f09d8636..95b8458d8fde4075519d6496aa239bdaa7659327 100644 (file)
@@ -5,10 +5,10 @@
  *
  */
 
-#include <common/dynamic-array.h>
-#include <common/buffer-view.h>
-#include "payload-view.h"
-#include "payload.h"
+#include <common/dynamic-array.hpp>
+#include <common/buffer-view.hpp>
+#include "payload-view.hpp"
+#include "payload.hpp"
 #include <stddef.h>
 
 bool lttng_payload_view_is_valid(const struct lttng_payload_view *view)
diff --git a/src/common/payload-view.h b/src/common/payload-view.h
deleted file mode 100644 (file)
index deaa965..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_PAYLOAD_VIEW_H
-#define LTTNG_PAYLOAD_VIEW_H
-
-#include <common/buffer-view.h>
-#include <common/dynamic-array.h>
-
-struct lttng_payload;
-struct fd_handle;
-
-/*
- * An lttng_payload_view references a payload and allows code to share
- * a `const` version of a subset of a payload.
- *
- * A payload view is invalidated whenever its source (a payload, or another
- * payload view) is modified.
- *
- * While a payload view does not allow users to modify the underlying bytes
- * of the payload, it can be used to 'pop' file descriptor handles using an
- * iterator belonging to the top-level payload view.
- *
- * Hence, a payload view created from a        payload or a dynamic buffer contains
- * an implicit file descriptor handle iterator. Any payload view created from
- * another payload view will share the same underlying file descriptor handle
- * iterator.
- *
- * The rationale for this is that a payload is never consumed directly, it must
- * be consumed through a payload view.
- *
- * Typically, a payload view will be used to rebuild a previously serialized
- * object hierarchy. Sharing an underlying iterator allows aggregate objects
- * to provide a restricted view of the payload to their members, which will
- * report the number of bytes consumed and `pop` the file descriptor handle they
- * should own. In return, those objects can create an even narrower view for
- * their children, allowing them to also consume file descriptor handles.
- *
- * Note that a payload view never assumes any ownership of the underlying
- * payload.
- */
-struct lttng_payload_view {
-       struct lttng_buffer_view buffer;
-       /* private */
-
-       const struct lttng_dynamic_pointer_array _fd_handles;
-
-       struct {
-               size_t *p_fd_handles_position;
-               size_t fd_handles_position;
-       } _iterator;
-};
-
-/**
- * Checks if a payload view's buffer is safe to access.
- *
- * After calling the payload view creation functions, callers should verify
- * if the resquested length (if any is explicitly provided) could be mapped
- * to a new view.
- *
- * @view       Payload to validate
- */
-bool lttng_payload_view_is_valid(const struct lttng_payload_view *view);
-
-/**
- * Return a payload view referencing a subset of a payload.
- *
- * @payload    Source payload to reference
- * @offset     Offset to apply to the payload's buffer
- * @len                Length of the contents to reference. Passing -1 will
- *             cause the view to reference the whole payload from the
- *             offset provided.
- */
-struct lttng_payload_view lttng_payload_view_from_payload(
-               const struct lttng_payload *payload, size_t offset,
-               ptrdiff_t len);
-
-/**
- * Return a payload view referencing a subset of a payload referenced by
- * another payload view.
- *
- * @view       Source payload view to reference
- * @offset     Offset to apply to the payload view's buffer view
- * @len                Length of the contents to reference. Passing -1 will
- *             cause the payload view to reference the whole payload view's
- *             buffer view from the offset provided.
- */
-struct lttng_payload_view lttng_payload_view_from_view(
-               struct lttng_payload_view *view, size_t offset,
-               ptrdiff_t len);
-
-/**
- * Return a payload view referencing a subset of a dynamic buffer.
- *
- * Meant as an adapter for code paths that need to create a payload view
- * from an existing dynamic buffer.
- *
- * @src                Source dynamic buffer to reference
- * @offset     Offset to apply to the dynamic buffer
- * @len                Length of the buffer contents to reference. Passing -1 will
- *             cause the payload view to reference the whole payload from the
- *             offset provided.
- */
-struct lttng_payload_view lttng_payload_view_from_dynamic_buffer(
-               const struct lttng_dynamic_buffer *buffer, size_t offset,
-               ptrdiff_t len);
-/**
- *
- * Return a payload view referencing a subset of a dynamic buffer.
- *
- * Meant as an adapter for code paths that need to create a payload view
- * from an existing buffer view.
- *
- * @src                Source buffer view to reference
- * @offset     Offset to apply to the buffer view
- * @len                Length of the buffer contents to reference. Passing -1 will
- *             cause the payload view to reference the whole payload from the
- *             offset provided.
- */
-struct lttng_payload_view lttng_payload_view_from_buffer_view(
-               const struct lttng_buffer_view *view, size_t offset,
-               ptrdiff_t len);
-
-/**
- * Return a payload view referencing a subset of the memory referenced by a raw
- * pointer.
- *
- * @src                Source buffer to reference
- * @offset     Offset to apply to the source memory buffer
- * @len                Length of the memory contents to reference.
- *
- * Note that a payload view never assumes the ownership of the memory it
- * references.
- */
-struct lttng_payload_view lttng_payload_view_init_from_buffer(
-               const char *src, size_t offset, ptrdiff_t len);
-
-/**
- * Get the number of file descriptor handles left in a payload view.
- *
- * @payload    Payload instance
- *
- * Returns the number of file descriptor handles left on success, -1 on error.
- */
-int lttng_payload_view_get_fd_handle_count(
-               const struct lttng_payload_view *payload_view);
-
-/**
- * Pop an fd handle from a payload view.
- *
- * A reference to the returned fd_handle is acquired on behalf of the caller.
- *
- * @payload    Payload instance
- *
- * Returns an fd_handle on success, -1 on error.
- */
-struct fd_handle *lttng_payload_view_pop_fd_handle(
-               struct lttng_payload_view *payload_view);
-
-#endif /* LTTNG_PAYLOAD_VIEW_H */
diff --git a/src/common/payload-view.hpp b/src/common/payload-view.hpp
new file mode 100644 (file)
index 0000000..06bb3d1
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_PAYLOAD_VIEW_H
+#define LTTNG_PAYLOAD_VIEW_H
+
+#include <common/buffer-view.hpp>
+#include <common/dynamic-array.hpp>
+
+struct lttng_payload;
+struct fd_handle;
+
+/*
+ * An lttng_payload_view references a payload and allows code to share
+ * a `const` version of a subset of a payload.
+ *
+ * A payload view is invalidated whenever its source (a payload, or another
+ * payload view) is modified.
+ *
+ * While a payload view does not allow users to modify the underlying bytes
+ * of the payload, it can be used to 'pop' file descriptor handles using an
+ * iterator belonging to the top-level payload view.
+ *
+ * Hence, a payload view created from a        payload or a dynamic buffer contains
+ * an implicit file descriptor handle iterator. Any payload view created from
+ * another payload view will share the same underlying file descriptor handle
+ * iterator.
+ *
+ * The rationale for this is that a payload is never consumed directly, it must
+ * be consumed through a payload view.
+ *
+ * Typically, a payload view will be used to rebuild a previously serialized
+ * object hierarchy. Sharing an underlying iterator allows aggregate objects
+ * to provide a restricted view of the payload to their members, which will
+ * report the number of bytes consumed and `pop` the file descriptor handle they
+ * should own. In return, those objects can create an even narrower view for
+ * their children, allowing them to also consume file descriptor handles.
+ *
+ * Note that a payload view never assumes any ownership of the underlying
+ * payload.
+ */
+struct lttng_payload_view {
+       struct lttng_buffer_view buffer;
+       /* private */
+
+       const struct lttng_dynamic_pointer_array _fd_handles;
+
+       struct {
+               size_t *p_fd_handles_position;
+               size_t fd_handles_position;
+       } _iterator;
+};
+
+/**
+ * Checks if a payload view's buffer is safe to access.
+ *
+ * After calling the payload view creation functions, callers should verify
+ * if the resquested length (if any is explicitly provided) could be mapped
+ * to a new view.
+ *
+ * @view       Payload to validate
+ */
+bool lttng_payload_view_is_valid(const struct lttng_payload_view *view);
+
+/**
+ * Return a payload view referencing a subset of a payload.
+ *
+ * @payload    Source payload to reference
+ * @offset     Offset to apply to the payload's buffer
+ * @len                Length of the contents to reference. Passing -1 will
+ *             cause the view to reference the whole payload from the
+ *             offset provided.
+ */
+struct lttng_payload_view lttng_payload_view_from_payload(
+               const struct lttng_payload *payload, size_t offset,
+               ptrdiff_t len);
+
+/**
+ * Return a payload view referencing a subset of a payload referenced by
+ * another payload view.
+ *
+ * @view       Source payload view to reference
+ * @offset     Offset to apply to the payload view's buffer view
+ * @len                Length of the contents to reference. Passing -1 will
+ *             cause the payload view to reference the whole payload view's
+ *             buffer view from the offset provided.
+ */
+struct lttng_payload_view lttng_payload_view_from_view(
+               struct lttng_payload_view *view, size_t offset,
+               ptrdiff_t len);
+
+/**
+ * Return a payload view referencing a subset of a dynamic buffer.
+ *
+ * Meant as an adapter for code paths that need to create a payload view
+ * from an existing dynamic buffer.
+ *
+ * @src                Source dynamic buffer to reference
+ * @offset     Offset to apply to the dynamic buffer
+ * @len                Length of the buffer contents to reference. Passing -1 will
+ *             cause the payload view to reference the whole payload from the
+ *             offset provided.
+ */
+struct lttng_payload_view lttng_payload_view_from_dynamic_buffer(
+               const struct lttng_dynamic_buffer *buffer, size_t offset,
+               ptrdiff_t len);
+/**
+ *
+ * Return a payload view referencing a subset of a dynamic buffer.
+ *
+ * Meant as an adapter for code paths that need to create a payload view
+ * from an existing buffer view.
+ *
+ * @src                Source buffer view to reference
+ * @offset     Offset to apply to the buffer view
+ * @len                Length of the buffer contents to reference. Passing -1 will
+ *             cause the payload view to reference the whole payload from the
+ *             offset provided.
+ */
+struct lttng_payload_view lttng_payload_view_from_buffer_view(
+               const struct lttng_buffer_view *view, size_t offset,
+               ptrdiff_t len);
+
+/**
+ * Return a payload view referencing a subset of the memory referenced by a raw
+ * pointer.
+ *
+ * @src                Source buffer to reference
+ * @offset     Offset to apply to the source memory buffer
+ * @len                Length of the memory contents to reference.
+ *
+ * Note that a payload view never assumes the ownership of the memory it
+ * references.
+ */
+struct lttng_payload_view lttng_payload_view_init_from_buffer(
+               const char *src, size_t offset, ptrdiff_t len);
+
+/**
+ * Get the number of file descriptor handles left in a payload view.
+ *
+ * @payload    Payload instance
+ *
+ * Returns the number of file descriptor handles left on success, -1 on error.
+ */
+int lttng_payload_view_get_fd_handle_count(
+               const struct lttng_payload_view *payload_view);
+
+/**
+ * Pop an fd handle from a payload view.
+ *
+ * A reference to the returned fd_handle is acquired on behalf of the caller.
+ *
+ * @payload    Payload instance
+ *
+ * Returns an fd_handle on success, -1 on error.
+ */
+struct fd_handle *lttng_payload_view_pop_fd_handle(
+               struct lttng_payload_view *payload_view);
+
+#endif /* LTTNG_PAYLOAD_VIEW_H */
index 0097e65bcf1191cb75cacb10dbb4f07531797a90..fa07dae31c840c2fa7661088e9d35ed691e3bad0 100644 (file)
@@ -5,10 +5,10 @@
  *
  */
 
-#include "payload.h"
-#include <common/dynamic-array.h>
-#include <common/dynamic-buffer.h>
-#include <common/error.h>
+#include "payload.hpp"
+#include <common/dynamic-array.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/error.hpp>
 
 static
 void release_fd_handle_ref(void *ptr)
diff --git a/src/common/payload.h b/src/common/payload.h
deleted file mode 100644 (file)
index d6c0cc1..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_PAYLOAD_H
-#define LTTNG_PAYLOAD_H
-
-#include <common/dynamic-buffer.h>
-#include <common/dynamic-array.h>
-#include <common/fd-handle.h>
-
-/*
- * An lttng_payload encompasses the 'data' (bytes) and any passed file
- * descriptors as part of a message between liblttng-ctl and the session
- * daemon.
- */
-struct lttng_payload {
-       struct lttng_dynamic_buffer buffer;
-       /* private */
-       struct lttng_dynamic_pointer_array _fd_handles;
-};
-
-/*
- * Initialize a payload. This performs no allocation and is meant
- * to be used instead of zero-ing the payload structure.
- */
-void lttng_payload_init(struct lttng_payload *payload);
-
-/* Copy a payload. */
-int lttng_payload_copy(const struct lttng_payload *src_payload,
-               struct lttng_payload *dst_payload);
-
-/* Release any memory and references held by the payload. */
-void lttng_payload_reset(struct lttng_payload *payload);
-
-/*
- * Empty the contents of a payload, releasing all references held.
- * This should be used to put a payload in a re-usable state.
- *
- * lttng_payload_reset must still be called on an lttng_payload to
- * free all allocated memory.
- */
-void lttng_payload_clear(struct lttng_payload *payload);
-
-/**
- * Add an fd to the payload.
- * The payload acquires a reference to the fd_handle.
- *
- * @payload    Payload instance
- * @fd_handle  File descriptor handle to add to the payload
- *
- * Returns 0 on success, -1 on allocation error.
- */
-int lttng_payload_push_fd_handle(struct lttng_payload *payload,
-               struct fd_handle *fd_handle);
-
-#endif /* LTTNG_PAYLOAD_H */
diff --git a/src/common/payload.hpp b/src/common/payload.hpp
new file mode 100644 (file)
index 0000000..9747f59
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_PAYLOAD_H
+#define LTTNG_PAYLOAD_H
+
+#include <common/dynamic-buffer.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/fd-handle.hpp>
+
+/*
+ * An lttng_payload encompasses the 'data' (bytes) and any passed file
+ * descriptors as part of a message between liblttng-ctl and the session
+ * daemon.
+ */
+struct lttng_payload {
+       struct lttng_dynamic_buffer buffer;
+       /* private */
+       struct lttng_dynamic_pointer_array _fd_handles;
+};
+
+/*
+ * Initialize a payload. This performs no allocation and is meant
+ * to be used instead of zero-ing the payload structure.
+ */
+void lttng_payload_init(struct lttng_payload *payload);
+
+/* Copy a payload. */
+int lttng_payload_copy(const struct lttng_payload *src_payload,
+               struct lttng_payload *dst_payload);
+
+/* Release any memory and references held by the payload. */
+void lttng_payload_reset(struct lttng_payload *payload);
+
+/*
+ * Empty the contents of a payload, releasing all references held.
+ * This should be used to put a payload in a re-usable state.
+ *
+ * lttng_payload_reset must still be called on an lttng_payload to
+ * free all allocated memory.
+ */
+void lttng_payload_clear(struct lttng_payload *payload);
+
+/**
+ * Add an fd to the payload.
+ * The payload acquires a reference to the fd_handle.
+ *
+ * @payload    Payload instance
+ * @fd_handle  File descriptor handle to add to the payload
+ *
+ * Returns 0 on success, -1 on allocation error.
+ */
+int lttng_payload_push_fd_handle(struct lttng_payload *payload,
+               struct fd_handle *fd_handle);
+
+#endif /* LTTNG_PAYLOAD_H */
index 2de91f5a06eaac1f87aec7e724d9a98c5ef25eb3..c2dce78816f0fad0e41a935d49371b20f5bbcd0d 100644 (file)
@@ -11,9 +11,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <common/common.h>
+#include <common/common.hpp>
 
-#include "pipe.h"
+#include "pipe.hpp"
 
 /*
  * Lock read side of a pipe.
diff --git a/src/common/pipe.h b/src/common/pipe.h
deleted file mode 100644 (file)
index d9f43d6..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef LTTNG_PIPE_H
-#define LTTNG_PIPE_H
-
-#include <pthread.h>
-#include <common/macros.h>
-#include <sys/types.h>
-
-enum lttng_pipe_state {
-       LTTNG_PIPE_STATE_OPENED = 1,
-       LTTNG_PIPE_STATE_CLOSED = 2,
-};
-
-struct lttng_pipe {
-       /* Read: 0, Write: 1. */
-       int fd[2];
-       /*
-        * Flags of the pipe once opened. pipe(2) specifies either O_NONBLOCK or
-        * O_CLOEXEC can be used. Flags are set using fcntl(2) call.
-        */
-       int flags;
-
-       /*
-        * These states are protected by the operation mutex below.
-        */
-       enum lttng_pipe_state r_state;
-       enum lttng_pipe_state w_state;
-
-       /* Held for each read(2) operation. */
-       pthread_mutex_t read_mutex;
-       /* Held for each write(2) operation. */
-       pthread_mutex_t write_mutex;
-};
-
-/*
- * Return 1 if read side is open else 0.
- */
-static inline int lttng_pipe_is_read_open(const struct lttng_pipe *pipe)
-{
-       return pipe->r_state == LTTNG_PIPE_STATE_OPENED ? 1 : 0;
-}
-
-/*
- * Return 1 if write side is open else 0.
- */
-static inline int lttng_pipe_is_write_open(const struct lttng_pipe *pipe)
-{
-       return pipe->w_state == LTTNG_PIPE_STATE_OPENED ? 1 : 0;
-}
-
-static inline int lttng_pipe_get_readfd(const struct lttng_pipe *pipe)
-{
-       return pipe->fd[0];
-}
-
-static inline int lttng_pipe_get_writefd(const struct lttng_pipe *pipe)
-{
-       return pipe->fd[1];
-}
-
-struct lttng_pipe *lttng_pipe_open(int flags);
-struct lttng_pipe *lttng_pipe_named_open(const char *path, mode_t mode,
-               int flags);
-int lttng_pipe_write_close(struct lttng_pipe *pipe);
-int lttng_pipe_read_close(struct lttng_pipe *pipe);
-/* Close both side of pipe. */
-int lttng_pipe_close(struct lttng_pipe *pipe);
-void lttng_pipe_destroy(struct lttng_pipe *pipe);
-
-ssize_t lttng_pipe_read(struct lttng_pipe *pipe, void *buf, size_t count);
-ssize_t lttng_pipe_write(struct lttng_pipe *pipe, const void *buf,
-               size_t count);
-/* Returns and releases the read end of the pipe. */
-int lttng_pipe_release_readfd(struct lttng_pipe *pipe);
-/* Returns and releases the write end of the pipe. */
-int lttng_pipe_release_writefd(struct lttng_pipe *pipe);
-
-#endif /* LTTNG_PIPE_H */
diff --git a/src/common/pipe.hpp b/src/common/pipe.hpp
new file mode 100644 (file)
index 0000000..d46e65d
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_PIPE_H
+#define LTTNG_PIPE_H
+
+#include <pthread.h>
+#include <common/macros.hpp>
+#include <sys/types.h>
+
+enum lttng_pipe_state {
+       LTTNG_PIPE_STATE_OPENED = 1,
+       LTTNG_PIPE_STATE_CLOSED = 2,
+};
+
+struct lttng_pipe {
+       /* Read: 0, Write: 1. */
+       int fd[2];
+       /*
+        * Flags of the pipe once opened. pipe(2) specifies either O_NONBLOCK or
+        * O_CLOEXEC can be used. Flags are set using fcntl(2) call.
+        */
+       int flags;
+
+       /*
+        * These states are protected by the operation mutex below.
+        */
+       enum lttng_pipe_state r_state;
+       enum lttng_pipe_state w_state;
+
+       /* Held for each read(2) operation. */
+       pthread_mutex_t read_mutex;
+       /* Held for each write(2) operation. */
+       pthread_mutex_t write_mutex;
+};
+
+/*
+ * Return 1 if read side is open else 0.
+ */
+static inline int lttng_pipe_is_read_open(const struct lttng_pipe *pipe)
+{
+       return pipe->r_state == LTTNG_PIPE_STATE_OPENED ? 1 : 0;
+}
+
+/*
+ * Return 1 if write side is open else 0.
+ */
+static inline int lttng_pipe_is_write_open(const struct lttng_pipe *pipe)
+{
+       return pipe->w_state == LTTNG_PIPE_STATE_OPENED ? 1 : 0;
+}
+
+static inline int lttng_pipe_get_readfd(const struct lttng_pipe *pipe)
+{
+       return pipe->fd[0];
+}
+
+static inline int lttng_pipe_get_writefd(const struct lttng_pipe *pipe)
+{
+       return pipe->fd[1];
+}
+
+struct lttng_pipe *lttng_pipe_open(int flags);
+struct lttng_pipe *lttng_pipe_named_open(const char *path, mode_t mode,
+               int flags);
+int lttng_pipe_write_close(struct lttng_pipe *pipe);
+int lttng_pipe_read_close(struct lttng_pipe *pipe);
+/* Close both side of pipe. */
+int lttng_pipe_close(struct lttng_pipe *pipe);
+void lttng_pipe_destroy(struct lttng_pipe *pipe);
+
+ssize_t lttng_pipe_read(struct lttng_pipe *pipe, void *buf, size_t count);
+ssize_t lttng_pipe_write(struct lttng_pipe *pipe, const void *buf,
+               size_t count);
+/* Returns and releases the read end of the pipe. */
+int lttng_pipe_release_readfd(struct lttng_pipe *pipe);
+/* Returns and releases the write end of the pipe. */
+int lttng_pipe_release_writefd(struct lttng_pipe *pipe);
+
+#endif /* LTTNG_PIPE_H */
index 857781c6ae7ed3ab345d392fb0fddeaa0423a696..8e901c9fec81f0027d120064ed90572765710ea6 100644 (file)
@@ -9,9 +9,9 @@
 #include <limits.h>
 #include <unistd.h>
 
-#include <common/compat/errno.h>
+#include <common/compat/errno.hpp>
 
-#include "readwrite.h"
+#include "readwrite.hpp"
 
 /*
  * lttng_read and lttng_write take care of EINTR and partial read/write.
diff --git a/src/common/readwrite.h b/src/common/readwrite.h
deleted file mode 100644 (file)
index ac3668a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef LTTNG_COMMON_READWRITE_H
-#define LTTNG_COMMON_READWRITE_H
-
-/*
- * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <unistd.h>
-#include <common/macros.h>
-
-/*
- * lttng_read and lttng_write take care of EINTR and partial read/write.
- * Upon success, they return the "count" received as parameter.
- * They can return a negative value if an error occurs.
- * If a value lower than the requested "count" is returned, it means an
- * error occurred.
- * The error can be checked by querying errno.
- */
-ssize_t lttng_read(int fd, void *buf, size_t count);
-ssize_t lttng_write(int fd, const void *buf, size_t count);
-
-#endif /* LTTNG_COMMON_READWRITE_H */
diff --git a/src/common/readwrite.hpp b/src/common/readwrite.hpp
new file mode 100644 (file)
index 0000000..1818fdb
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef LTTNG_COMMON_READWRITE_H
+#define LTTNG_COMMON_READWRITE_H
+
+/*
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <unistd.h>
+#include <common/macros.hpp>
+
+/*
+ * lttng_read and lttng_write take care of EINTR and partial read/write.
+ * Upon success, they return the "count" received as parameter.
+ * They can return a negative value if an error occurs.
+ * If a value lower than the requested "count" is returned, it means an
+ * error occurred.
+ * The error can be checked by querying errno.
+ */
+ssize_t lttng_read(int fd, void *buf, size_t count);
+ssize_t lttng_write(int fd, const void *buf, size_t count);
+
+#endif /* LTTNG_COMMON_READWRITE_H */
diff --git a/src/common/relayd/Makefile.am b/src/common/relayd/Makefile.am
deleted file mode 100644 (file)
index 32623cc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = librelayd.la
-
-librelayd_la_SOURCES = \
-       relayd.cpp \
-       relayd.h
-
-librelayd_la_LIBADD = $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la
index 6c2641ac03bec575f2c7ad469bac9ddd19bb7fe0..28cab7bc5c8d0500f8615e071d1eac758ca1896c 100644 (file)
 #include <sys/stat.h>
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/compat/endian.h>
-#include <common/compat/string.h>
-#include <common/sessiond-comm/relayd.h>
-#include <common/index/ctf-index.h>
-#include <common/trace-chunk.h>
-#include <common/string-utils/format.h>
-
-#include "relayd.h"
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/compat/endian.hpp>
+#include <common/compat/string.hpp>
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/index/ctf-index.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/string-utils/format.hpp>
+
+#include "relayd.hpp"
 
 static
 bool relayd_supports_chunks(const struct lttcomm_relayd_sock *sock)
diff --git a/src/common/relayd/relayd.h b/src/common/relayd/relayd.h
deleted file mode 100644 (file)
index 1fbe226..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _RELAYD_H
-#define _RELAYD_H
-
-#include <unistd.h>
-#include <stdbool.h>
-
-#include <common/sessiond-comm/relayd.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/trace-chunk.h>
-#include <common/dynamic-array.h>
-
-struct relayd_stream_rotation_position {
-       uint64_t stream_id;
-       /*
-        * Packet sequence number of the first packet belonging to the new
-        * "destination" trace chunk to which the stream is rotating.
-        *
-        * Ignored for metadata streams.
-        */
-       uint64_t rotate_at_seq_num;
-};
-
-int relayd_connect(struct lttcomm_relayd_sock *sock);
-int relayd_close(struct lttcomm_relayd_sock *sock);
-int relayd_create_session(struct lttcomm_relayd_sock *rsock,
-               uint64_t *relayd_session_id,
-               const char *session_name, const char *hostname,
-               const char *base_path, int session_live_timer,
-               unsigned int snapshot, uint64_t sessiond_session_id,
-               const lttng_uuid sessiond_uuid,
-               const uint64_t *current_chunk_id,
-               time_t creation_time, bool session_name_contains_creation_time,
-               char *output_path);
-int relayd_add_stream(struct lttcomm_relayd_sock *sock, const char *channel_name,
-               const char *domain_name, const char *pathname, uint64_t *stream_id,
-               uint64_t tracefile_size, uint64_t tracefile_count,
-               struct lttng_trace_chunk *trace_chunk);
-int relayd_streams_sent(struct lttcomm_relayd_sock *rsock);
-int relayd_send_close_stream(struct lttcomm_relayd_sock *sock, uint64_t stream_id,
-               uint64_t last_net_seq_num);
-int relayd_version_check(struct lttcomm_relayd_sock *sock);
-int relayd_start_data(struct lttcomm_relayd_sock *sock);
-int relayd_send_metadata(struct lttcomm_relayd_sock *sock, size_t len);
-int relayd_send_data_hdr(struct lttcomm_relayd_sock *sock,
-               struct lttcomm_relayd_data_hdr *hdr, size_t size);
-int relayd_data_pending(struct lttcomm_relayd_sock *sock, uint64_t stream_id,
-               uint64_t last_net_seq_num);
-int relayd_quiescent_control(struct lttcomm_relayd_sock *sock,
-               uint64_t metadata_stream_id);
-int relayd_begin_data_pending(struct lttcomm_relayd_sock *sock, uint64_t id);
-int relayd_end_data_pending(struct lttcomm_relayd_sock *sock, uint64_t id,
-               unsigned int *is_data_inflight);
-int relayd_send_index(struct lttcomm_relayd_sock *rsock,
-               struct ctf_packet_index *index, uint64_t relay_stream_id,
-               uint64_t net_seq_num);
-int relayd_reset_metadata(struct lttcomm_relayd_sock *rsock,
-               uint64_t stream_id, uint64_t version);
-/* `positions` is an array of `stream_count` relayd_stream_rotation_position. */
-int relayd_rotate_streams(struct lttcomm_relayd_sock *sock,
-               unsigned int stream_count, const uint64_t *new_chunk_id,
-               const struct relayd_stream_rotation_position *positions);
-int relayd_create_trace_chunk(struct lttcomm_relayd_sock *sock,
-               struct lttng_trace_chunk *chunk);
-int relayd_close_trace_chunk(struct lttcomm_relayd_sock *sock,
-               struct lttng_trace_chunk *chunk,
-               char *path);
-int relayd_trace_chunk_exists(struct lttcomm_relayd_sock *sock,
-               uint64_t chunk_id, bool *chunk_exists);
-int relayd_get_configuration(struct lttcomm_relayd_sock *sock,
-               uint64_t query_flags,
-               uint64_t *result_flags);
-
-#endif /* _RELAYD_H */
diff --git a/src/common/relayd/relayd.hpp b/src/common/relayd/relayd.hpp
new file mode 100644 (file)
index 0000000..d4a903a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _RELAYD_H
+#define _RELAYD_H
+
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <common/sessiond-comm/relayd.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/dynamic-array.hpp>
+
+struct relayd_stream_rotation_position {
+       uint64_t stream_id;
+       /*
+        * Packet sequence number of the first packet belonging to the new
+        * "destination" trace chunk to which the stream is rotating.
+        *
+        * Ignored for metadata streams.
+        */
+       uint64_t rotate_at_seq_num;
+};
+
+int relayd_connect(struct lttcomm_relayd_sock *sock);
+int relayd_close(struct lttcomm_relayd_sock *sock);
+int relayd_create_session(struct lttcomm_relayd_sock *rsock,
+               uint64_t *relayd_session_id,
+               const char *session_name, const char *hostname,
+               const char *base_path, int session_live_timer,
+               unsigned int snapshot, uint64_t sessiond_session_id,
+               const lttng_uuid sessiond_uuid,
+               const uint64_t *current_chunk_id,
+               time_t creation_time, bool session_name_contains_creation_time,
+               char *output_path);
+int relayd_add_stream(struct lttcomm_relayd_sock *sock, const char *channel_name,
+               const char *domain_name, const char *pathname, uint64_t *stream_id,
+               uint64_t tracefile_size, uint64_t tracefile_count,
+               struct lttng_trace_chunk *trace_chunk);
+int relayd_streams_sent(struct lttcomm_relayd_sock *rsock);
+int relayd_send_close_stream(struct lttcomm_relayd_sock *sock, uint64_t stream_id,
+               uint64_t last_net_seq_num);
+int relayd_version_check(struct lttcomm_relayd_sock *sock);
+int relayd_start_data(struct lttcomm_relayd_sock *sock);
+int relayd_send_metadata(struct lttcomm_relayd_sock *sock, size_t len);
+int relayd_send_data_hdr(struct lttcomm_relayd_sock *sock,
+               struct lttcomm_relayd_data_hdr *hdr, size_t size);
+int relayd_data_pending(struct lttcomm_relayd_sock *sock, uint64_t stream_id,
+               uint64_t last_net_seq_num);
+int relayd_quiescent_control(struct lttcomm_relayd_sock *sock,
+               uint64_t metadata_stream_id);
+int relayd_begin_data_pending(struct lttcomm_relayd_sock *sock, uint64_t id);
+int relayd_end_data_pending(struct lttcomm_relayd_sock *sock, uint64_t id,
+               unsigned int *is_data_inflight);
+int relayd_send_index(struct lttcomm_relayd_sock *rsock,
+               struct ctf_packet_index *index, uint64_t relay_stream_id,
+               uint64_t net_seq_num);
+int relayd_reset_metadata(struct lttcomm_relayd_sock *rsock,
+               uint64_t stream_id, uint64_t version);
+/* `positions` is an array of `stream_count` relayd_stream_rotation_position. */
+int relayd_rotate_streams(struct lttcomm_relayd_sock *sock,
+               unsigned int stream_count, const uint64_t *new_chunk_id,
+               const struct relayd_stream_rotation_position *positions);
+int relayd_create_trace_chunk(struct lttcomm_relayd_sock *sock,
+               struct lttng_trace_chunk *chunk);
+int relayd_close_trace_chunk(struct lttcomm_relayd_sock *sock,
+               struct lttng_trace_chunk *chunk,
+               char *path);
+int relayd_trace_chunk_exists(struct lttcomm_relayd_sock *sock,
+               uint64_t chunk_id, bool *chunk_exists);
+int relayd_get_configuration(struct lttcomm_relayd_sock *sock,
+               uint64_t query_flags,
+               uint64_t *result_flags);
+
+#endif /* _RELAYD_H */
index 3c9eea8c33f6be46b9044c673e1fb160408cc22d..76177a423c5f84363bed7843402439713c1b9199 100644 (file)
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include <common/bytecode/bytecode.h>
-#include <common/lttng-kernel.h>
-#include <common/common.h>
-#include <common/utils.h>
-#include <common/compat/errno.h>
-#include <common/compat/getenv.h>
-#include <common/compat/string.h>
-#include <common/unix.h>
-#include <common/defaults.h>
-#include <common/lttng-elf.h>
-#include <common/thread.h>
+#include <common/bytecode/bytecode.hpp>
+#include <common/lttng-kernel.hpp>
+#include <common/common.hpp>
+#include <common/utils.hpp>
+#include <common/compat/errno.hpp>
+#include <common/compat/getenv.hpp>
+#include <common/compat/string.hpp>
+#include <common/unix.hpp>
+#include <common/defaults.hpp>
+#include <common/lttng-elf.hpp>
+#include <common/thread.hpp>
 
 #include <lttng/constant.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/filter/filter-ast.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/filter/filter-ast.hpp>
 
-#include "runas.h"
+#include "runas.hpp"
 
 #define GETPW_BUFFER_FALLBACK_SIZE 4096
 
diff --git a/src/common/runas.h b/src/common/runas.h
deleted file mode 100644 (file)
index 406dfca..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef _RUNAS_H
-#define _RUNAS_H
-
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <common/macros.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-
-/*
- * The run-as process is launched by forking without an exec*() call. This means
- * that any resource allocated before the run-as worker is launched should be
- * cleaned-up after the fork(). This callback allows the user to perform this
- * clean-up.
- *
- * Note that the callback will _not_ be invoked if the LTTNG_DEBUG_NOCLONE
- * environment variable is set as the clean-up is not needed (and may not be
- * expected).
- *
- * A negative return value will cause the run-as process to exit with a non-zero
- * value.
- */
-typedef int (*post_fork_cleanup_cb)(void *user_data);
-
-int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int run_as_mkdirat_recursive(int dirfd, const char *path, mode_t mode,
-               uid_t uid, gid_t gid);
-int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int run_as_mkdirat(int dirfd, const char *path, mode_t mode,
-               uid_t uid, gid_t gid);
-int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid);
-int run_as_openat(int dirfd, const char *filename, int flags, mode_t mode,
-               uid_t uid, gid_t gid);
-int run_as_unlink(const char *path, uid_t uid, gid_t gid);
-int run_as_unlinkat(int dirfd, const char *filename, uid_t uid, gid_t gid);
-int run_as_rmdir(const char *path, uid_t uid, gid_t gid);
-int run_as_rmdir_recursive(const char *path, uid_t uid, gid_t gid, int flags);
-int run_as_rmdirat(int dirfd, const char *path, uid_t uid, gid_t gid);
-int run_as_rmdirat_recursive(int dirfd, const char *path, uid_t uid, gid_t gid, int flags);
-int run_as_rename(const char *old_name, const char *new_name, uid_t uid, gid_t gid);
-int run_as_renameat(int old_dirfd, const char *old_name,
-               int new_dirfd, const char *new_name, uid_t uid, gid_t gid);
-int run_as_extract_elf_symbol_offset(int fd, const char* function,
-               uid_t uid, gid_t gid, uint64_t *offset);
-int run_as_extract_sdt_probe_offsets(int fd, const char *provider_name,
-               const char* probe_name, uid_t uid, gid_t gid,
-               uint64_t **offsets, uint32_t *num_offset);
-int run_as_generate_filter_bytecode(const char *filter_expression,
-               const struct lttng_credentials *creds,
-               struct lttng_bytecode **bytecode);
-int run_as_create_worker(const char *procname,
-               post_fork_cleanup_cb clean_up_func, void *clean_up_user_data);
-void run_as_destroy_worker(void);
-
-#endif /* _RUNAS_H */
diff --git a/src/common/runas.hpp b/src/common/runas.hpp
new file mode 100644 (file)
index 0000000..a8235b6
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _RUNAS_H
+#define _RUNAS_H
+
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <common/macros.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+
+/*
+ * The run-as process is launched by forking without an exec*() call. This means
+ * that any resource allocated before the run-as worker is launched should be
+ * cleaned-up after the fork(). This callback allows the user to perform this
+ * clean-up.
+ *
+ * Note that the callback will _not_ be invoked if the LTTNG_DEBUG_NOCLONE
+ * environment variable is set as the clean-up is not needed (and may not be
+ * expected).
+ *
+ * A negative return value will cause the run-as process to exit with a non-zero
+ * value.
+ */
+typedef int (*post_fork_cleanup_cb)(void *user_data);
+
+int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int run_as_mkdirat_recursive(int dirfd, const char *path, mode_t mode,
+               uid_t uid, gid_t gid);
+int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int run_as_mkdirat(int dirfd, const char *path, mode_t mode,
+               uid_t uid, gid_t gid);
+int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid);
+int run_as_openat(int dirfd, const char *filename, int flags, mode_t mode,
+               uid_t uid, gid_t gid);
+int run_as_unlink(const char *path, uid_t uid, gid_t gid);
+int run_as_unlinkat(int dirfd, const char *filename, uid_t uid, gid_t gid);
+int run_as_rmdir(const char *path, uid_t uid, gid_t gid);
+int run_as_rmdir_recursive(const char *path, uid_t uid, gid_t gid, int flags);
+int run_as_rmdirat(int dirfd, const char *path, uid_t uid, gid_t gid);
+int run_as_rmdirat_recursive(int dirfd, const char *path, uid_t uid, gid_t gid, int flags);
+int run_as_rename(const char *old_name, const char *new_name, uid_t uid, gid_t gid);
+int run_as_renameat(int old_dirfd, const char *old_name,
+               int new_dirfd, const char *new_name, uid_t uid, gid_t gid);
+int run_as_extract_elf_symbol_offset(int fd, const char* function,
+               uid_t uid, gid_t gid, uint64_t *offset);
+int run_as_extract_sdt_probe_offsets(int fd, const char *provider_name,
+               const char* probe_name, uid_t uid, gid_t gid,
+               uint64_t **offsets, uint32_t *num_offset);
+int run_as_generate_filter_bytecode(const char *filter_expression,
+               const struct lttng_credentials *creds,
+               struct lttng_bytecode **bytecode);
+int run_as_create_worker(const char *procname,
+               post_fork_cleanup_cb clean_up_func, void *clean_up_user_data);
+void run_as_destroy_worker(void);
+
+#endif /* _RUNAS_H */
index ec510b0c6e392b1299f27dee414551bc64e7a03d..408d5c8e553231ec4094e47fc0edbd5d93a33603 100644 (file)
@@ -4,11 +4,11 @@
  * SPDX-License-Identifier: GPL-2.0-only
  */
 
-#include <lttng/session-descriptor-internal.h>
-#include <common/macros.h>
-#include <common/uri.h>
-#include <common/defaults.h>
-#include <common/error.h>
+#include <lttng/session-descriptor-internal.hpp>
+#include <common/macros.hpp>
+#include <common/uri.hpp>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
 #include <time.h>
 #include <stdio.h>
 
diff --git a/src/common/session.xsd b/src/common/session.xsd
new file mode 100644 (file)
index 0000000..986fb2d
--- /dev/null
@@ -0,0 +1,534 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+
+SPDX-License-Identifier: MIT
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+elementFormDefault="qualified" version="2.12">
+
+<xs:simpleType name="name_type">
+       <xs:restriction base="xs:string">
+               <xs:maxLength value="255"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="uint64_type">
+       <xs:restriction base="xs:integer">
+               <xs:minInclusive value="0"/>
+               <xs:maxInclusive value="18446744073709551615"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="uint32_type">
+       <xs:restriction base="xs:integer">
+               <xs:minInclusive value="0"/>
+               <xs:maxInclusive value="4294967295"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<!--
+Maps to the range allowed for blocking timeout: -1 (block forever),
+0 (do not block), positive integer value (blocking time in usec) limited
+by its signed 32-bit representation when converted to msec.
+-->
+<xs:simpleType name="blocking_timeout_type">
+       <xs:restriction base="xs:integer">
+               <xs:minInclusive value="-1" />
+               <xs:maxInclusive value="2147483648000" />
+       </xs:restriction>
+</xs:simpleType>
+
+<xs:simpleType name="channel_overwrite_mode_type">
+       <xs:restriction base="xs:string">
+               <xs:enumeration value="DISCARD"/>
+               <xs:enumeration value="OVERWRITE"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<!-- Maps to the lttng_event_output enum -->
+<xs:simpleType name="event_output_type">
+       <xs:restriction base="xs:string">
+               <xs:enumeration value="SPLICE"/>
+               <xs:enumeration value="MMAP"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<!-- Maps to the lttng_loglevel_type enum -->
+<xs:simpleType name="loglevel_type">
+       <xs:restriction base="xs:string">
+               <xs:enumeration value="ALL"/>
+               <xs:enumeration value="RANGE"/>
+               <xs:enumeration value="SINGLE"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<!-- Maps to the lttng_event_type enum -->
+<xs:simpleType name="event_type_type">
+       <xs:restriction base="xs:string">
+               <xs:enumeration value="ALL"/>
+               <xs:enumeration value="TRACEPOINT"/>
+               <xs:enumeration value="PROBE"/>
+               <xs:enumeration value="USERSPACE_PROBE"/>
+               <xs:enumeration value="FUNCTION"/>
+               <xs:enumeration value="FUNCTION_ENTRY"/>
+               <xs:enumeration value="NOOP"/>
+               <xs:enumeration value="SYSCALL"/>
+               <xs:enumeration value="KPROBE"/>
+               <xs:enumeration value="KRETPROBE"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<xs:complexType name="event_probe_attributes_type">
+       <xs:all>
+               <xs:element name="symbol_name" type="name_type" minOccurs="0"/>
+               <xs:element name="address" type="uint64_type" minOccurs="0"/>
+               <xs:element name="offset" type="uint64_type" minOccurs="0"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:simpleType name="userspace_probe_lookup_method">
+       <xs:restriction base="xs:string">
+               <xs:enumeration value="DEFAULT"/>
+               <xs:enumeration value="ELF"/>
+               <xs:enumeration value="SDT"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<xs:complexType name="event_userspace_probe_function_attributes_type">
+       <xs:all>
+               <xs:element name="lookup_method" type="userspace_probe_lookup_method"/>
+               <xs:element name="binary_path" type="xs:string"/>
+               <xs:element name="function_name" type="xs:string"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="event_userspace_probe_tracepoint_attributes_type">
+       <xs:all>
+               <xs:element name="lookup_method" type="userspace_probe_lookup_method"/>
+               <xs:element name="binary_path" type="xs:string"/>
+               <xs:element name="probe_name" type="xs:string"/>
+               <xs:element name="provider_name" type="xs:string"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="event_ftrace_attributes_type">
+       <xs:all>
+               <xs:element name="symbol_name" type="name_type"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="event_attributes_type">
+       <xs:choice>
+               <xs:element name="probe_attributes" type="event_probe_attributes_type"/>
+               <xs:element name="function_attributes" type="event_ftrace_attributes_type"/>
+               <xs:element name="userspace_probe_function_attributes" type="event_userspace_probe_function_attributes_type"/>
+               <xs:element name="userspace_probe_tracepoint_attributes" type="event_userspace_probe_tracepoint_attributes_type"/>
+       </xs:choice>
+</xs:complexType>
+
+<xs:complexType name="event_exclusion_list_type">
+       <xs:sequence>
+               <xs:element name="exclusion" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+       </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="event_type">
+       <xs:all>
+               <xs:element name="name" type="name_type" minOccurs="0"/>
+               <xs:element name="enabled" type="xs:boolean" default="true" minOccurs="0"/>
+               <xs:element name="type" type="event_type_type" default="TRACEPOINT" minOccurs="0"/>
+               <xs:element name="loglevel_type" type="loglevel_type" default="ALL" minOccurs="0"/>
+               <xs:element name="loglevel" type="xs:int" default="-1" minOccurs="0"/>
+               <xs:element name="filter" type="xs:string" minOccurs="0"/>
+               <xs:element name="exclusions" type="event_exclusion_list_type" minOccurs="0"/>
+               <xs:element name="attributes" type="event_attributes_type" minOccurs="0"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="event_list_type">
+       <xs:sequence>
+               <xs:element name="event" type="event_type" minOccurs="0" maxOccurs="unbounded"/>
+       </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="event_perf_context_type">
+       <xs:all>
+               <xs:element name="type" type="uint32_type"/>
+               <xs:element name="config" type="uint64_type"/>
+               <xs:element name="name" type="name_type"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="event_app_context_type">
+       <xs:all>
+         <xs:element name="provider_name" type="xs:string"/>
+         <xs:element name="ctx_name" type="xs:string"/>
+       </xs:all>
+</xs:complexType>
+
+<!-- Maps to the lttng_event_context_type enum -->
+<xs:simpleType name="event_context_type_type">
+       <xs:restriction base="xs:string">
+               <xs:enumeration value="PID"/>
+               <xs:enumeration value="PROCNAME"/>
+               <xs:enumeration value="PRIO"/>
+               <xs:enumeration value="NICE"/>
+               <xs:enumeration value="VPID"/>
+               <xs:enumeration value="TID"/>
+               <xs:enumeration value="VTID"/>
+               <xs:enumeration value="PPID"/>
+               <xs:enumeration value="VPPID"/>
+               <xs:enumeration value="PTHREAD_ID"/>
+               <xs:enumeration value="HOSTNAME"/>
+               <xs:enumeration value="IP"/>
+               <xs:enumeration value="APP"/>
+               <xs:enumeration value="INTERRUPTIBLE" />
+               <xs:enumeration value="PREEMPTIBLE" />
+               <xs:enumeration value="NEED_RESCHEDULE" />
+               <xs:enumeration value="MIGRATABLE" />
+               <xs:enumeration value="CALLSTACK_USER" />
+               <xs:enumeration value="CALLSTACK_KERNEL" />
+       </xs:restriction>
+</xs:simpleType>
+
+<xs:complexType name="event_context_type">
+       <xs:choice>
+               <xs:element name="type" type="event_context_type_type"/>
+               <xs:element name="perf" type="event_perf_context_type"/>
+               <xs:element name="app" type="event_app_context_type"/>
+       </xs:choice>
+</xs:complexType>
+
+<xs:complexType name="event_context_list_type">
+       <xs:sequence>
+               <xs:element name="context" type="event_context_type" minOccurs="0" maxOccurs="unbounded"/>
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to struct lttng_channel -->
+<xs:complexType name="channel_type">
+       <xs:all>
+               <xs:element name="name" type="name_type"/>
+               <xs:element name="enabled" type="xs:boolean" default="true" minOccurs="0"/>
+               <xs:element name="overwrite_mode" type="channel_overwrite_mode_type" default="DISCARD" minOccurs="0"/>
+               <xs:element name="subbuffer_size" type="uint64_type" minOccurs="0"/> <!-- bytes -->
+               <xs:element name="subbuffer_count" type="uint64_type" default="4" minOccurs="0"/>
+               <xs:element name="switch_timer_interval" type="uint32_type" default="0" minOccurs="0"/>  <!-- usec -->
+               <xs:element name="read_timer_interval" type="uint32_type"/>  <!-- usec -->
+               <xs:element name="blocking_timeout" type="blocking_timeout_type" default="0" minOccurs="0" /> <!-- usec -->
+               <xs:element name="output_type" type="event_output_type"/>
+               <xs:element name="tracefile_size" type="uint64_type" default="0" minOccurs="0"/> <!-- bytes -->
+               <xs:element name="tracefile_count" type="uint64_type" default="0" minOccurs="0"/>
+               <xs:element name="live_timer_interval" type="uint32_type" default="0" minOccurs="0"/> <!-- usec -->
+               <xs:element name="events" type="event_list_type" minOccurs="0"/>
+               <xs:element name="contexts" type="event_context_list_type" minOccurs="0"/>
+               <xs:element name="monitor_timer_interval" type="uint64_type" default="0" minOccurs="0"/>  <!-- usec -->
+       </xs:all>
+</xs:complexType>
+
+<!-- Maps to the lttng_domain_type enum -->
+<xs:simpleType name="domain_type_type">
+       <xs:restriction base="xs:string">
+               <xs:enumeration value="KERNEL"/>
+               <xs:enumeration value="UST"/>
+               <xs:enumeration value="JUL"/>
+               <xs:enumeration value="LOG4J"/>
+               <xs:enumeration value="PYTHON"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<!-- Maps to the lttng_buffer_type enum -->
+<xs:simpleType name="domain_buffer_type">
+       <xs:restriction base="xs:string">
+               <xs:enumeration value="PER_PID"/>
+               <xs:enumeration value="PER_UID"/>
+               <xs:enumeration value="GLOBAL"/>
+       </xs:restriction>
+</xs:simpleType>
+
+<xs:complexType name="channel_list_type">
+       <xs:sequence>
+               <xs:element name="channel" type="channel_type" minOccurs="0" maxOccurs="unbounded" />
+       </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="pid_value_type">
+       <xs:choice minOccurs="0">
+               <xs:element name="id" type="xs:integer" />
+       </xs:choice>
+</xs:complexType>
+
+<!-- Maps to a list of pid_process_attr_values-->
+<xs:complexType name="pid_process_attr_values_type">
+       <xs:sequence>
+               <xs:choice minOccurs="0" maxOccurs="unbounded" >
+                       <xs:element name="pid" type="pid_value_type" />
+               </xs:choice>
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to a pid_process_attr_tracker-->
+<xs:complexType name="pid_process_attr_tracker_type">
+       <xs:all>
+               <xs:element name="process_attr_values" type="pid_process_attr_values_type" />
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="vpid_value_type">
+       <xs:all>
+               <xs:element name="id" type="xs:integer" />
+       </xs:all>
+</xs:complexType>
+
+<!-- Maps to a list of vpid_process_attr_values-->
+<xs:complexType name="vpid_process_attr_values_type">
+       <xs:sequence>
+               <xs:element name="vpid" type="vpid_value_type" minOccurs="0" maxOccurs="unbounded" />
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to a pid_process_attr_tracker-->
+<xs:complexType name="vpid_process_attr_tracker_type">
+       <xs:all>
+               <xs:element name="process_attr_values" type="vpid_process_attr_values_type" />
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="uid_value_type">
+       <xs:choice>
+               <xs:element name="id" type="xs:integer" />
+               <xs:element name="name" type="xs:string" />
+       </xs:choice>
+</xs:complexType>
+
+<!-- Maps to a list of uid_process_attr_values-->
+<xs:complexType name="uid_process_attr_values_type">
+       <xs:sequence>
+               <xs:element name="uid" type="uid_value_type" minOccurs="0" maxOccurs="unbounded" />
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to a uid_process_attr_tracker-->
+<xs:complexType name="uid_process_attr_tracker_type">
+       <xs:all>
+               <xs:element name="process_attr_values" type="uid_process_attr_values_type" />
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="vuid_value_type">
+       <xs:choice>
+               <xs:element name="id" type="xs:integer" />
+               <xs:element name="name" type="xs:string" />
+       </xs:choice>
+</xs:complexType>
+
+<!-- Maps to a list of vuid_process_attr_values-->
+<xs:complexType name="vuid_process_attr_values_type">
+       <xs:sequence>
+               <xs:element name="vuid" type="vuid_value_type" minOccurs="0" maxOccurs="unbounded" />
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to a vuid_process_attr_tracker-->
+<xs:complexType name="vuid_process_attr_tracker_type">
+       <xs:all>
+               <xs:element name="process_attr_values" type="vuid_process_attr_values_type" />
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="gid_value_type">
+       <xs:choice>
+               <xs:element name="id" type="xs:integer" />
+               <xs:element name="name" type="xs:string" />
+       </xs:choice>
+</xs:complexType>
+
+<!-- Maps to a list of gid_process_attr_values-->
+<xs:complexType name="gid_process_attr_values_type">
+       <xs:sequence>
+               <xs:element name="gid" type="gid_value_type" minOccurs="0" maxOccurs="unbounded" />
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to a gid_process_attr_tracker-->
+<xs:complexType name="gid_process_attr_tracker_type">
+       <xs:all>
+               <xs:element name="process_attr_values" type="gid_process_attr_values_type" />
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="vgid_value_type">
+       <xs:choice>
+               <xs:element name="id" type="xs:integer" />
+               <xs:element name="name" type="xs:string" />
+       </xs:choice>
+</xs:complexType>
+
+<!-- Maps to a list of vgid_process_attr_values-->
+<xs:complexType name="vgid_process_attr_values_type">
+       <xs:sequence>
+               <xs:element name="vgid" type="vgid_value_type" minOccurs="0" maxOccurs="unbounded" />
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to a vgid_process_attr_tracker-->
+<xs:complexType name="vgid_process_attr_tracker_type">
+       <xs:all>
+               <xs:element name="process_attr_values" type="vgid_process_attr_values_type" />
+       </xs:all>
+</xs:complexType>
+
+<!-- Maps to a list of trackers-->
+<xs:complexType name="process_attr_tracker_type">
+       <xs:sequence>
+               <xs:choice minOccurs="0" maxOccurs="unbounded" >
+                       <xs:element name="pid_process_attr_tracker" type="pid_process_attr_tracker_type" maxOccurs="1" />
+                       <xs:element name="vpid_process_attr_tracker" type="vpid_process_attr_tracker_type" maxOccurs="1" />
+                       <xs:element name="uid_process_attr_tracker" type="uid_process_attr_tracker_type" maxOccurs="1" />
+                       <xs:element name="vuid_process_attr_tracker" type="vuid_process_attr_tracker_type" maxOccurs="1" />
+                       <xs:element name="gid_process_attr_tracker" type="gid_process_attr_tracker_type" maxOccurs="1" />
+                       <xs:element name="vgid_process_attr_tracker" type="vgid_process_attr_tracker_type" maxOccurs="1" />
+               </xs:choice>
+       </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="pid_target_type">
+       <xs:all>
+               <xs:element name="pid" type="xs:integer" />
+       </xs:all>
+</xs:complexType>
+
+<!-- Maps to a list of pid_targets (legacy)-->
+<xs:complexType name="targets_type">
+       <xs:sequence>
+               <xs:choice>
+                       <xs:element name="pid_target" type="pid_target_type" minOccurs="0" maxOccurs="unbounded" />
+               </xs:choice>
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to a pid_tracker (legacy)-->
+<xs:complexType name="pid_tracker_type">
+       <xs:all>
+               <xs:element name="targets" type="targets_type" />
+       </xs:all>
+</xs:complexType>
+
+<!-- Maps to a list of trackers (legacy)-->
+<xs:complexType name="trackers_type">
+       <xs:sequence minOccurs="0" maxOccurs="unbounded">
+               <xs:element name="pid_tracker" type="pid_tracker_type" maxOccurs="1" />
+       </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to struct lttng_domain, contains channels and pid_process_attr_tracker -->
+<xs:complexType name="domain_type">
+       <xs:all>
+               <xs:element name="type" type="domain_type_type"/>
+               <xs:element name="buffer_type" type="domain_buffer_type"/>
+               <xs:element name="channels" type="channel_list_type" minOccurs="0"/>
+               <xs:element name="process_attr_trackers" type="process_attr_tracker_type" minOccurs="0"/>
+               <!-- Support of legacy tracker specification -->
+               <xs:element name="trackers" type="trackers_type" minOccurs="0"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="periodic_rotation_schedule_type">
+       <xs:all>
+               <xs:element name="time_us" type="uint64_type" minOccurs="0" />
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="size_threshold_rotation_schedule_type">
+       <xs:all>
+               <xs:element name="bytes" type="uint64_type" minOccurs="0" />
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="rotation_schedule_type">
+       <xs:sequence>
+               <xs:choice maxOccurs="unbounded">
+                       <xs:element name="periodic" type="periodic_rotation_schedule_type" maxOccurs="unbounded" />
+                       <xs:element name="size_threshold" type="size_threshold_rotation_schedule_type" maxOccurs="unbounded" />
+               </xs:choice>
+       </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="session_attributes_type">
+       <xs:all>
+               <xs:element name="snapshot_mode" type="xs:boolean" minOccurs="0"/>
+               <xs:element name="live_timer_interval" type="uint32_type" minOccurs="0"/> <!-- usec -->
+               <xs:element name="rotation_schedules" type="rotation_schedule_type" minOccurs="0" />
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="domain_list_type">
+       <xs:sequence>
+               <xs:element name="domain" type="domain_type" minOccurs="0" maxOccurs="unbounded"/>
+       </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="net_output_type">
+       <xs:all>
+               <xs:element name="control_uri" type="xs:string"/>
+               <xs:element name="data_uri" type="xs:string"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="destination_type">
+       <xs:choice>
+               <xs:element name="path" type="xs:string"/>
+               <xs:element name="net_output" type="net_output_type"/>
+       </xs:choice>
+</xs:complexType>
+
+<xs:complexType name="consumer_output_type">
+       <xs:all>
+               <xs:element name="enabled" type="xs:boolean" default="true"/>
+               <xs:element name="destination" type="destination_type"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="snapshot_output_type">
+       <xs:all>
+               <xs:element name="name" type="name_type"/>
+               <xs:element name="max_size" type="uint64_type"/>
+               <xs:element name="consumer_output" type="consumer_output_type"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:complexType name="snapshot_output_list_type">
+       <xs:sequence>
+               <xs:element name="output" type="snapshot_output_type" minOccurs="0" maxOccurs="unbounded"/>
+       </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="session_output_type">
+       <xs:choice>
+               <xs:element name="snapshot_outputs" type="snapshot_output_list_type"/>
+               <xs:element name="consumer_output" type="consumer_output_type"/>
+       </xs:choice>
+</xs:complexType>
+
+<xs:complexType name="session_type">
+       <xs:all>
+               <xs:element name="name" type="name_type"/>
+               <xs:element name="shared_memory_path" type="xs:string" minOccurs="0"/>
+               <xs:element name="domains" type="domain_list_type" minOccurs="0"/>
+               <xs:element name="started" type="xs:boolean" default="0" minOccurs="0"/>
+               <xs:element name="attributes" type="session_attributes_type" minOccurs="0"/>
+               <xs:element name="output" type="session_output_type" minOccurs="0"/>
+       </xs:all>
+</xs:complexType>
+
+<xs:element name="sessions">
+       <xs:complexType>
+               <xs:sequence>
+                       <xs:element name="session" type="session_type" maxOccurs="unbounded"/>
+               </xs:sequence>
+       </xs:complexType>
+</xs:element>
+
+</xs:schema>
diff --git a/src/common/sessiond-comm/Makefile.am b/src/common/sessiond-comm/Makefile.am
deleted file mode 100644 (file)
index 8086cb0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libsessiond-comm.la
-
-libsessiond_comm_la_SOURCES = \
-       agent.h \
-       inet.cpp \
-       inet.h \
-       inet6.cpp \
-       inet6.h \
-       relayd.h \
-       sessiond-comm.cpp \
-       sessiond-comm.h
diff --git a/src/common/sessiond-comm/agent.h b/src/common/sessiond-comm/agent.h
deleted file mode 100644 (file)
index 92ac068..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef AGENT_COMM
-#define AGENT_COMM
-
-#include <stdint.h>
-
-#include <common/macros.h>
-#include <lttng/lttng.h>
-
-/*
- * Command value passed in the header.
- */
-enum lttcomm_agent_command {
-       AGENT_CMD_LIST                  = 1,
-       AGENT_CMD_ENABLE                = 2,
-       AGENT_CMD_DISABLE               = 3,
-       AGENT_CMD_REG_DONE              = 4,    /* End registration process. */
-       AGENT_CMD_APP_CTX_ENABLE        = 5,
-       AGENT_CMD_APP_CTX_DISABLE       = 6,
-};
-
-/*
- * Return codes from the agent.
- */
-enum lttcomm_agent_ret_code {
-       /* Success, assumed to be the first entry */
-       AGENT_RET_CODE_SUCCESS          = 1,
-       /* Invalid command */
-       AGENT_RET_CODE_INVALID          = 2,
-       /* Unknown logger name */
-       AGENT_RET_CODE_UNKNOWN_NAME     = 3,
-       AGENT_RET_CODE_NR,
-};
-
-/*
- * Agent application communication header.
- */
-struct lttcomm_agent_hdr {
-       uint64_t data_size;             /* data size following this header */
-       uint32_t cmd;                   /* Enum of agent command. */
-       uint32_t cmd_version;   /* command version */
-} LTTNG_PACKED;
-
-/*
- * Enable event command payload. Will be immediately followed by the
- * variable-length string representing the filter expression.
- */
-struct lttcomm_agent_enable_event {
-       uint32_t loglevel_value;
-       uint32_t loglevel_type;
-       char name[LTTNG_SYMBOL_NAME_LEN];
-       uint32_t filter_expression_length;
-} LTTNG_PACKED;
-
-/*
- * Disable event command payload.
- */
-struct lttcomm_agent_disable_event {
-       char name[LTTNG_SYMBOL_NAME_LEN];
-} LTTNG_PACKED;
-
-/*
- * Generic reply coming from the agent.
- */
-struct lttcomm_agent_generic_reply {
-       uint32_t ret_code;
-} LTTNG_PACKED;
-
-/*
- * List command reply header.
- */
-struct lttcomm_agent_list_reply_hdr {
-       uint32_t ret_code;
-       uint32_t data_size;
-} LTTNG_PACKED;
-
-/*
- * List command reply payload coming from the agent.
- */
-struct lttcomm_agent_list_reply {
-       uint32_t nb_event;
-       /* List of event name each of them ending by a NULL byte. */
-       char payload[];
-} LTTNG_PACKED;
-
-#endif /* AGENT_COMM */
diff --git a/src/common/sessiond-comm/agent.hpp b/src/common/sessiond-comm/agent.hpp
new file mode 100644 (file)
index 0000000..9fcb1f3
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef AGENT_COMM
+#define AGENT_COMM
+
+#include <stdint.h>
+
+#include <common/macros.hpp>
+#include <lttng/lttng.h>
+
+/*
+ * Command value passed in the header.
+ */
+enum lttcomm_agent_command {
+       AGENT_CMD_LIST                  = 1,
+       AGENT_CMD_ENABLE                = 2,
+       AGENT_CMD_DISABLE               = 3,
+       AGENT_CMD_REG_DONE              = 4,    /* End registration process. */
+       AGENT_CMD_APP_CTX_ENABLE        = 5,
+       AGENT_CMD_APP_CTX_DISABLE       = 6,
+};
+
+/*
+ * Return codes from the agent.
+ */
+enum lttcomm_agent_ret_code {
+       /* Success, assumed to be the first entry */
+       AGENT_RET_CODE_SUCCESS          = 1,
+       /* Invalid command */
+       AGENT_RET_CODE_INVALID          = 2,
+       /* Unknown logger name */
+       AGENT_RET_CODE_UNKNOWN_NAME     = 3,
+       AGENT_RET_CODE_NR,
+};
+
+/*
+ * Agent application communication header.
+ */
+struct lttcomm_agent_hdr {
+       uint64_t data_size;             /* data size following this header */
+       uint32_t cmd;                   /* Enum of agent command. */
+       uint32_t cmd_version;   /* command version */
+} LTTNG_PACKED;
+
+/*
+ * Enable event command payload. Will be immediately followed by the
+ * variable-length string representing the filter expression.
+ */
+struct lttcomm_agent_enable_event {
+       uint32_t loglevel_value;
+       uint32_t loglevel_type;
+       char name[LTTNG_SYMBOL_NAME_LEN];
+       uint32_t filter_expression_length;
+} LTTNG_PACKED;
+
+/*
+ * Disable event command payload.
+ */
+struct lttcomm_agent_disable_event {
+       char name[LTTNG_SYMBOL_NAME_LEN];
+} LTTNG_PACKED;
+
+/*
+ * Generic reply coming from the agent.
+ */
+struct lttcomm_agent_generic_reply {
+       uint32_t ret_code;
+} LTTNG_PACKED;
+
+/*
+ * List command reply header.
+ */
+struct lttcomm_agent_list_reply_hdr {
+       uint32_t ret_code;
+       uint32_t data_size;
+} LTTNG_PACKED;
+
+/*
+ * List command reply payload coming from the agent.
+ */
+struct lttcomm_agent_list_reply {
+       uint32_t nb_event;
+       /* List of event name each of them ending by a NULL byte. */
+       char payload[];
+} LTTNG_PACKED;
+
+#endif /* AGENT_COMM */
index 20eb613a82aa2182662f65062cc6f8119871bb1d..30aa8c6134a42903f2df14cd6e0e69c103d2173a 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <common/compat/time.h>
+#include <common/compat/time.hpp>
 #include <poll.h>
 
-#include <common/common.h>
-#include <common/time.h>
-#include <common/compat/errno.h>
+#include <common/common.hpp>
+#include <common/time.hpp>
+#include <common/compat/errno.hpp>
 
-#include "inet.h"
+#include "inet.hpp"
 
 #define RECONNECT_DELAY        200     /* ms */
 
diff --git a/src/common/sessiond-comm/inet.h b/src/common/sessiond-comm/inet.h
deleted file mode 100644 (file)
index fd7cffe..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTCOMM_INET_H
-#define _LTTCOMM_INET_H
-
-#include <limits.h>
-
-#include "sessiond-comm.h"
-
-/* See man tcp(7) for more detail about this value. */
-#define LTTCOMM_INET_PROC_SYN_RETRIES_PATH "/proc/sys/net/ipv4/tcp_syn_retries"
-#define LTTCOMM_INET_PROC_FIN_TIMEOUT_PATH "/proc/sys/net/ipv4/tcp_fin_timeout"
-
-/*
- * The timeout value of a connect() is computed with an algorithm inside the
- * kernel using the defined TCP SYN retries so the end value in time is
- * approximative. According to tcp(7) man page, a value of 5 is roughly 180
- * seconds of timeout. With that information, we've computed a factor of 36
- * (180/5) by considering that it grows linearly. This is of course uncertain
- * but this is the best approximation we can do at runtime.
- */
-#define LTTCOMM_INET_SYN_TIMEOUT_FACTOR                36
-
-/*
- * Maximum timeout value in seconds of a TCP connection for both send/recv and
- * connect operations.
- */
-LTTNG_EXPORT extern unsigned long lttcomm_inet_tcp_timeout;
-
-/* Stub */
-struct lttcomm_sock;
-
-/* Net family callback */
-extern int lttcomm_create_inet_sock(struct lttcomm_sock *sock, int type,
-               int proto);
-
-extern struct lttcomm_sock *lttcomm_accept_inet_sock(struct lttcomm_sock *sock);
-extern int lttcomm_bind_inet_sock(struct lttcomm_sock *sock);
-extern int lttcomm_close_inet_sock(struct lttcomm_sock *sock);
-extern int lttcomm_connect_inet_sock(struct lttcomm_sock *sock);
-extern int lttcomm_listen_inet_sock(struct lttcomm_sock *sock, int backlog);
-
-extern ssize_t lttcomm_recvmsg_inet_sock(struct lttcomm_sock *sock, void *buf,
-               size_t len, int flags);
-extern ssize_t lttcomm_sendmsg_inet_sock(struct lttcomm_sock *sock,
-               const void *buf, size_t len, int flags);
-
-/* Initialize inet communication layer. */
-extern void lttcomm_inet_init(void);
-
-#endif /* _LTTCOMM_INET_H */
diff --git a/src/common/sessiond-comm/inet.hpp b/src/common/sessiond-comm/inet.hpp
new file mode 100644 (file)
index 0000000..dca1cc1
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTCOMM_INET_H
+#define _LTTCOMM_INET_H
+
+#include <limits.h>
+
+#include "sessiond-comm.hpp"
+
+/* See man tcp(7) for more detail about this value. */
+#define LTTCOMM_INET_PROC_SYN_RETRIES_PATH "/proc/sys/net/ipv4/tcp_syn_retries"
+#define LTTCOMM_INET_PROC_FIN_TIMEOUT_PATH "/proc/sys/net/ipv4/tcp_fin_timeout"
+
+/*
+ * The timeout value of a connect() is computed with an algorithm inside the
+ * kernel using the defined TCP SYN retries so the end value in time is
+ * approximative. According to tcp(7) man page, a value of 5 is roughly 180
+ * seconds of timeout. With that information, we've computed a factor of 36
+ * (180/5) by considering that it grows linearly. This is of course uncertain
+ * but this is the best approximation we can do at runtime.
+ */
+#define LTTCOMM_INET_SYN_TIMEOUT_FACTOR                36
+
+/*
+ * Maximum timeout value in seconds of a TCP connection for both send/recv and
+ * connect operations.
+ */
+LTTNG_EXPORT extern unsigned long lttcomm_inet_tcp_timeout;
+
+/* Stub */
+struct lttcomm_sock;
+
+/* Net family callback */
+extern int lttcomm_create_inet_sock(struct lttcomm_sock *sock, int type,
+               int proto);
+
+extern struct lttcomm_sock *lttcomm_accept_inet_sock(struct lttcomm_sock *sock);
+extern int lttcomm_bind_inet_sock(struct lttcomm_sock *sock);
+extern int lttcomm_close_inet_sock(struct lttcomm_sock *sock);
+extern int lttcomm_connect_inet_sock(struct lttcomm_sock *sock);
+extern int lttcomm_listen_inet_sock(struct lttcomm_sock *sock, int backlog);
+
+extern ssize_t lttcomm_recvmsg_inet_sock(struct lttcomm_sock *sock, void *buf,
+               size_t len, int flags);
+extern ssize_t lttcomm_sendmsg_inet_sock(struct lttcomm_sock *sock,
+               const void *buf, size_t len, int flags);
+
+/* Initialize inet communication layer. */
+extern void lttcomm_inet_init(void);
+
+#endif /* _LTTCOMM_INET_H */
index adabebfaeb3ec176ccabcc12a12474a8be969203..caa4d7eb3906b691d1762b6e0fd41268b0ff53ed 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <common/compat/time.h>
+#include <common/compat/time.hpp>
 #include <poll.h>
 
-#include <common/common.h>
-#include <common/time.h>
-#include <common/compat/errno.h>
+#include <common/common.hpp>
+#include <common/time.hpp>
+#include <common/compat/errno.hpp>
 
-#include "inet6.h"
+#include "inet6.hpp"
 
 #define RECONNECT_DELAY        200     /* ms */
 
diff --git a/src/common/sessiond-comm/inet6.h b/src/common/sessiond-comm/inet6.h
deleted file mode 100644 (file)
index b292848..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTCOMM_INET6_H
-#define _LTTCOMM_INET6_H
-
-#include <limits.h>
-
-#include "sessiond-comm.h"
-
-/* Stub */
-struct lttcomm_sock;
-
-/* Net family callback */
-extern int lttcomm_create_inet6_sock(struct lttcomm_sock *sock, int type,
-               int proto);
-
-extern struct lttcomm_sock *lttcomm_accept_inet6_sock(
-               struct lttcomm_sock *sock);
-extern int lttcomm_bind_inet6_sock(struct lttcomm_sock *sock);
-extern int lttcomm_close_inet6_sock(struct lttcomm_sock *sock);
-extern int lttcomm_connect_inet6_sock(struct lttcomm_sock *sock);
-extern int lttcomm_listen_inet6_sock(struct lttcomm_sock *sock, int backlog);
-
-extern ssize_t lttcomm_recvmsg_inet6_sock(struct lttcomm_sock *sock, void *buf,
-               size_t len, int flags);
-extern ssize_t lttcomm_sendmsg_inet6_sock(struct lttcomm_sock *sock,
-               const void *buf, size_t len, int flags);
-
-#endif /* _LTTCOMM_INET6_H */
diff --git a/src/common/sessiond-comm/inet6.hpp b/src/common/sessiond-comm/inet6.hpp
new file mode 100644 (file)
index 0000000..d6122fd
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTCOMM_INET6_H
+#define _LTTCOMM_INET6_H
+
+#include <limits.h>
+
+#include "sessiond-comm.hpp"
+
+/* Stub */
+struct lttcomm_sock;
+
+/* Net family callback */
+extern int lttcomm_create_inet6_sock(struct lttcomm_sock *sock, int type,
+               int proto);
+
+extern struct lttcomm_sock *lttcomm_accept_inet6_sock(
+               struct lttcomm_sock *sock);
+extern int lttcomm_bind_inet6_sock(struct lttcomm_sock *sock);
+extern int lttcomm_close_inet6_sock(struct lttcomm_sock *sock);
+extern int lttcomm_connect_inet6_sock(struct lttcomm_sock *sock);
+extern int lttcomm_listen_inet6_sock(struct lttcomm_sock *sock, int backlog);
+
+extern ssize_t lttcomm_recvmsg_inet6_sock(struct lttcomm_sock *sock, void *buf,
+               size_t len, int flags);
+extern ssize_t lttcomm_sendmsg_inet6_sock(struct lttcomm_sock *sock,
+               const void *buf, size_t len, int flags);
+
+#endif /* _LTTCOMM_INET6_H */
diff --git a/src/common/sessiond-comm/relayd.h b/src/common/sessiond-comm/relayd.h
deleted file mode 100644 (file)
index 36a9107..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- * Copyright (C) 2012 Julien Desfossez <julien.desfossez@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _RELAYD_COMM
-#define _RELAYD_COMM
-
-#include <limits.h>
-#include <stdint.h>
-
-#include <lttng/lttng.h>
-#include <common/defaults.h>
-#include <common/index/ctf-index.h>
-#include <common/macros.h>
-#include <common/uuid.h>
-#include <common/optional.h>
-
-#define RELAYD_VERSION_COMM_MAJOR             VERSION_MAJOR
-#define RELAYD_VERSION_COMM_MINOR             VERSION_MINOR
-
-#define RELAYD_COMM_LTTNG_HOST_NAME_MAX_2_4    64
-#define RELAYD_COMM_LTTNG_NAME_MAX_2_4 255
-#define RELAYD_COMM_LTTNG_PATH_MAX     4096
-#define RELAYD_COMM_DEFAULT_STREAM_NAME_LEN    264 /* 256 + 8 */
-
-/*
- * lttng-relayd communication header.
- */
-struct lttcomm_relayd_hdr {
-       /* Circuit ID not used for now so always ignored */
-       uint64_t circuit_id;
-       uint64_t data_size;             /* data size following this header */
-       uint32_t cmd;                   /* enum lttcomm_relayd_command */
-       uint32_t cmd_version;   /* command version */
-} LTTNG_PACKED;
-
-/*
- * lttng-relayd data header.
- */
-struct lttcomm_relayd_data_hdr {
-       /* Circuit ID not used for now so always ignored */
-       uint64_t circuit_id;
-       uint64_t stream_id;     /* Stream ID known by the relayd */
-       uint64_t net_seq_num;   /* Network sequence number, per stream. */
-       uint32_t data_size;     /* data size following this header */
-       uint32_t padding_size;  /* Size of 0 padding the data */
-} LTTNG_PACKED;
-
-/*
- * Reply from a create session command.
- */
-struct lttcomm_relayd_status_session {
-       uint64_t session_id;
-       uint32_t ret_code;
-} LTTNG_PACKED;
-
-/*
- * Used to add a stream on the relay daemon.
- */
-struct lttcomm_relayd_add_stream {
-       char channel_name[RELAYD_COMM_DEFAULT_STREAM_NAME_LEN];
-       char pathname[RELAYD_COMM_LTTNG_PATH_MAX];
-} LTTNG_PACKED;
-
-/*
- * Used to add a stream on the relay daemon.
- * Protocol version 2.2
- */
-struct lttcomm_relayd_add_stream_2_2 {
-       char channel_name[RELAYD_COMM_DEFAULT_STREAM_NAME_LEN];
-       char pathname[RELAYD_COMM_LTTNG_PATH_MAX];
-       uint64_t tracefile_size;
-       uint64_t tracefile_count;
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_add_stream_2_11 {
-       uint32_t channel_name_len;
-       uint32_t pathname_len;
-       uint64_t tracefile_size;
-       uint64_t tracefile_count;
-       uint64_t trace_chunk_id;
-       char names[];
-} LTTNG_PACKED;
-
-/*
- * Answer from an add stream command.
- */
-struct lttcomm_relayd_status_stream {
-       uint64_t handle;
-       uint32_t ret_code;
-} LTTNG_PACKED;
-
-/*
- * Used to return command code for command not needing special data.
- */
-struct lttcomm_relayd_generic_reply {
-       uint32_t ret_code;
-} LTTNG_PACKED;
-
-/*
- * Version command.
- */
-struct lttcomm_relayd_version {
-       uint32_t major;
-       uint32_t minor;
-} LTTNG_PACKED;
-
-/*
- * Metadata payload used when metadata command is sent.
- */
-struct lttcomm_relayd_metadata_payload {
-       uint64_t stream_id;
-       uint32_t padding_size;
-       char payload[];
-} LTTNG_PACKED;
-
-/*
- * Used to indicate that a specific stream id can now be closed.
- */
-struct lttcomm_relayd_close_stream {
-       uint64_t stream_id;
-       uint64_t last_net_seq_num;      /* sequence number of last packet */
-} LTTNG_PACKED;
-
-/*
- * Used to test if for a given stream id the data is pending on the relayd side
- * for reading.
- */
-struct lttcomm_relayd_data_pending {
-       uint64_t stream_id;
-       uint64_t last_net_seq_num; /* Sequence number of the last packet */
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_begin_data_pending {
-       uint64_t session_id;
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_end_data_pending {
-       uint64_t session_id;
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_quiescent_control {
-       uint64_t stream_id;
-} LTTNG_PACKED;
-
-/*
- * Index data.
- */
-struct lttcomm_relayd_index {
-       uint64_t relay_stream_id;
-       uint64_t net_seq_num;
-       uint64_t packet_size;
-       uint64_t content_size;
-       uint64_t timestamp_begin;
-       uint64_t timestamp_end;
-       uint64_t events_discarded;
-       uint64_t stream_id;
-       /* 2.8+ */
-       uint64_t stream_instance_id;
-       uint64_t packet_seq_num;
-} LTTNG_PACKED;
-
-static inline size_t lttcomm_relayd_index_len(uint32_t major, uint32_t minor)
-{
-       if (major == 1) {
-               switch (minor) {
-               case 0:
-                       return offsetof(struct lttcomm_relayd_index, stream_id)
-                               + member_sizeof(struct lttcomm_relayd_index,
-                                               stream_id);
-               case 1:
-                       return offsetof(struct lttcomm_relayd_index, packet_seq_num)
-                               + member_sizeof(struct lttcomm_relayd_index,
-                                               packet_seq_num);
-               default:
-                       abort();
-               }
-       }
-       abort();
-}
-
-/*
- * Create session in 2.4 adds additionnal parameters for live reading.
- */
-struct lttcomm_relayd_create_session_2_4 {
-       char session_name[RELAYD_COMM_LTTNG_NAME_MAX_2_4];
-       char hostname[RELAYD_COMM_LTTNG_HOST_NAME_MAX_2_4];
-       uint32_t live_timer;
-       uint32_t snapshot;
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_create_session_2_11 {
-       uint32_t session_name_len;
-       uint32_t hostname_len;
-       /* Optional, set to 0 to indicate it is not user-specified. */
-       uint32_t base_path_len;
-       uint32_t live_timer;
-       uint8_t snapshot;
-       uint8_t session_name_contains_creation_time;
-       /* Sessiond instance UUID */
-       lttng_uuid sessiond_uuid;
-       /* Sessiond session id */
-       uint64_t session_id;
-       /* Session creation time, in seconds since UNIX Epoch. */
-       uint64_t creation_time;
-       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED current_chunk_id;
-       /* Contains the session_name, hostname, base_path. */
-       char names[];
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_create_session_reply_2_11 {
-       struct lttcomm_relayd_status_session generic;
-       /* Includes the '\0' terminator. */
-       uint32_t output_path_length;
-       char output_path[];
-} LTTNG_PACKED;
-
-/*
- * Used to ask the relay to reset the metadata trace file (regeneration).
- * Send the new version of the metadata (starts at 0).
- */
-struct lttcomm_relayd_reset_metadata {
-       uint64_t stream_id;
-       uint64_t version;
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_stream_rotation_position {
-       uint64_t stream_id;
-       /*
-        * Sequence number of the first packet belonging to the new
-        * "destination" trace chunk to which the stream is rotating.
-        *
-        * Ignored for metadata streams.
-        */
-       uint64_t rotate_at_seq_num;
-} LTTNG_PACKED;
-
-/*
- * For certain releases, the LTTNG_PACKED annotation was missing on the
- * `new_chunk_id` field which causes padding to be added between the
- * "optional" structure's `is_set` and `value` fields.
- *
- * Three alignment cases are handled:
- *   - `value` is aligned to the next byte boundary after `is_set`
- *     no padding is produced, see
- *     `struct lttcomm_relayd_rotate_streams_packed`,
- *   - `value` is aligned to the next 4-byte boundary after `is_set`
- *     (e.g. x86), 3 bytes of padding are produced, see
- *     `struct lttcomm_relayd_rotate_streams_3_bytes_padding`,
- *   - `value` is aligned to the next 8-byte boundary after `is_set`
- *     (e.g. x86-64), 7 bytes of padding are produced, see
- *     `struct lttcomm_relayd_rotate_streams_7_bytes_padding`.
- *
- * Note that since this structure's advertised size is used to determine
- * the size of the padding it includes, it can't be extended with new
- * optional fields. A new command would be needed.
- */
-struct lttcomm_relayd_rotate_streams {
-       uint32_t stream_count;
-       /*
-        * Streams can be rotated outside of a chunk but not be parented to
-        * a new chunk.
-        *
-        * Improperly packed, but left as-is for backwards compatibility
-        * with unpatched relay daemons.
-        */
-       LTTNG_OPTIONAL_COMM(uint64_t) new_chunk_id;
-       /* `stream_count` positions follow. */
-       struct lttcomm_relayd_stream_rotation_position rotation_positions[];
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_rotate_streams_packed {
-       uint32_t stream_count;
-       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED new_chunk_id;
-       struct lttcomm_relayd_stream_rotation_position rotation_positions[];
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_rotate_streams_3_bytes_padding {
-       uint32_t stream_count;
-       struct {
-               union {
-                       uint8_t is_set;
-                       uint32_t padding;
-               };
-               uint64_t value;
-       } LTTNG_PACKED new_chunk_id;
-       struct lttcomm_relayd_stream_rotation_position rotation_positions[];
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_rotate_streams_7_bytes_padding {
-       uint32_t stream_count;
-       struct {
-               union {
-                       uint8_t is_set;
-                       uint64_t padding;
-               };
-               uint64_t value;
-       } LTTNG_PACKED new_chunk_id;
-       struct lttcomm_relayd_stream_rotation_position rotation_positions[];
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_create_trace_chunk {
-       uint64_t chunk_id;
-       /* Seconds since EPOCH. */
-       uint64_t creation_timestamp;
-       /* Includes trailing NULL. */
-       uint32_t override_name_length;
-       char override_name[];
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_close_trace_chunk {
-       uint64_t chunk_id;
-       /* Seconds since EPOCH. */
-       uint64_t close_timestamp;
-       /* enum lttng_trace_chunk_command_type */
-       LTTNG_OPTIONAL_COMM(uint32_t) LTTNG_PACKED close_command;
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_close_trace_chunk_reply {
-       struct lttcomm_relayd_generic_reply generic;
-       /* Includes trailing NULL. */
-       uint32_t path_length;
-       char path[];
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_trace_chunk_exists {
-       uint64_t chunk_id;
-} LTTNG_PACKED;
-
-struct lttcomm_relayd_trace_chunk_exists_reply {
-       struct lttcomm_relayd_generic_reply generic;
-       uint8_t trace_chunk_exists;
-} LTTNG_PACKED;
-
-enum lttcomm_relayd_configuration_flag {
-       /* The relay daemon (2.12) is configured to allow clear operations. */
-       LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED = (1 << 0),
-};
-
-struct lttcomm_relayd_get_configuration {
-       uint64_t query_flags;
-} LTTNG_PACKED;
-
-/*
- * Used to return a relay daemon's configuration in reply to the
- * RELAYD_GET_CONFIGURATION command.
- */
-struct lttcomm_relayd_get_configuration_reply {
-       struct lttcomm_relayd_generic_reply generic;
-       /* Set of lttcomm_relayd_configuration_flag. */
-       uint64_t relayd_configuration_flags;
-       /* Optional variable-length payload. */
-       char payload[];
-} LTTNG_PACKED;
-
-#endif /* _RELAYD_COMM */
diff --git a/src/common/sessiond-comm/relayd.hpp b/src/common/sessiond-comm/relayd.hpp
new file mode 100644 (file)
index 0000000..febbe4e
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2012 Julien Desfossez <julien.desfossez@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _RELAYD_COMM
+#define _RELAYD_COMM
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <lttng/lttng.h>
+#include <common/defaults.hpp>
+#include <common/index/ctf-index.hpp>
+#include <common/macros.hpp>
+#include <common/uuid.hpp>
+#include <common/optional.hpp>
+
+#define RELAYD_VERSION_COMM_MAJOR             VERSION_MAJOR
+#define RELAYD_VERSION_COMM_MINOR             VERSION_MINOR
+
+#define RELAYD_COMM_LTTNG_HOST_NAME_MAX_2_4    64
+#define RELAYD_COMM_LTTNG_NAME_MAX_2_4 255
+#define RELAYD_COMM_LTTNG_PATH_MAX     4096
+#define RELAYD_COMM_DEFAULT_STREAM_NAME_LEN    264 /* 256 + 8 */
+
+/*
+ * lttng-relayd communication header.
+ */
+struct lttcomm_relayd_hdr {
+       /* Circuit ID not used for now so always ignored */
+       uint64_t circuit_id;
+       uint64_t data_size;             /* data size following this header */
+       uint32_t cmd;                   /* enum lttcomm_relayd_command */
+       uint32_t cmd_version;   /* command version */
+} LTTNG_PACKED;
+
+/*
+ * lttng-relayd data header.
+ */
+struct lttcomm_relayd_data_hdr {
+       /* Circuit ID not used for now so always ignored */
+       uint64_t circuit_id;
+       uint64_t stream_id;     /* Stream ID known by the relayd */
+       uint64_t net_seq_num;   /* Network sequence number, per stream. */
+       uint32_t data_size;     /* data size following this header */
+       uint32_t padding_size;  /* Size of 0 padding the data */
+} LTTNG_PACKED;
+
+/*
+ * Reply from a create session command.
+ */
+struct lttcomm_relayd_status_session {
+       uint64_t session_id;
+       uint32_t ret_code;
+} LTTNG_PACKED;
+
+/*
+ * Used to add a stream on the relay daemon.
+ */
+struct lttcomm_relayd_add_stream {
+       char channel_name[RELAYD_COMM_DEFAULT_STREAM_NAME_LEN];
+       char pathname[RELAYD_COMM_LTTNG_PATH_MAX];
+} LTTNG_PACKED;
+
+/*
+ * Used to add a stream on the relay daemon.
+ * Protocol version 2.2
+ */
+struct lttcomm_relayd_add_stream_2_2 {
+       char channel_name[RELAYD_COMM_DEFAULT_STREAM_NAME_LEN];
+       char pathname[RELAYD_COMM_LTTNG_PATH_MAX];
+       uint64_t tracefile_size;
+       uint64_t tracefile_count;
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_add_stream_2_11 {
+       uint32_t channel_name_len;
+       uint32_t pathname_len;
+       uint64_t tracefile_size;
+       uint64_t tracefile_count;
+       uint64_t trace_chunk_id;
+       char names[];
+} LTTNG_PACKED;
+
+/*
+ * Answer from an add stream command.
+ */
+struct lttcomm_relayd_status_stream {
+       uint64_t handle;
+       uint32_t ret_code;
+} LTTNG_PACKED;
+
+/*
+ * Used to return command code for command not needing special data.
+ */
+struct lttcomm_relayd_generic_reply {
+       uint32_t ret_code;
+} LTTNG_PACKED;
+
+/*
+ * Version command.
+ */
+struct lttcomm_relayd_version {
+       uint32_t major;
+       uint32_t minor;
+} LTTNG_PACKED;
+
+/*
+ * Metadata payload used when metadata command is sent.
+ */
+struct lttcomm_relayd_metadata_payload {
+       uint64_t stream_id;
+       uint32_t padding_size;
+       char payload[];
+} LTTNG_PACKED;
+
+/*
+ * Used to indicate that a specific stream id can now be closed.
+ */
+struct lttcomm_relayd_close_stream {
+       uint64_t stream_id;
+       uint64_t last_net_seq_num;      /* sequence number of last packet */
+} LTTNG_PACKED;
+
+/*
+ * Used to test if for a given stream id the data is pending on the relayd side
+ * for reading.
+ */
+struct lttcomm_relayd_data_pending {
+       uint64_t stream_id;
+       uint64_t last_net_seq_num; /* Sequence number of the last packet */
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_begin_data_pending {
+       uint64_t session_id;
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_end_data_pending {
+       uint64_t session_id;
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_quiescent_control {
+       uint64_t stream_id;
+} LTTNG_PACKED;
+
+/*
+ * Index data.
+ */
+struct lttcomm_relayd_index {
+       uint64_t relay_stream_id;
+       uint64_t net_seq_num;
+       uint64_t packet_size;
+       uint64_t content_size;
+       uint64_t timestamp_begin;
+       uint64_t timestamp_end;
+       uint64_t events_discarded;
+       uint64_t stream_id;
+       /* 2.8+ */
+       uint64_t stream_instance_id;
+       uint64_t packet_seq_num;
+} LTTNG_PACKED;
+
+static inline size_t lttcomm_relayd_index_len(uint32_t major, uint32_t minor)
+{
+       if (major == 1) {
+               switch (minor) {
+               case 0:
+                       return offsetof(struct lttcomm_relayd_index, stream_id)
+                               + member_sizeof(struct lttcomm_relayd_index,
+                                               stream_id);
+               case 1:
+                       return offsetof(struct lttcomm_relayd_index, packet_seq_num)
+                               + member_sizeof(struct lttcomm_relayd_index,
+                                               packet_seq_num);
+               default:
+                       abort();
+               }
+       }
+       abort();
+}
+
+/*
+ * Create session in 2.4 adds additionnal parameters for live reading.
+ */
+struct lttcomm_relayd_create_session_2_4 {
+       char session_name[RELAYD_COMM_LTTNG_NAME_MAX_2_4];
+       char hostname[RELAYD_COMM_LTTNG_HOST_NAME_MAX_2_4];
+       uint32_t live_timer;
+       uint32_t snapshot;
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_create_session_2_11 {
+       uint32_t session_name_len;
+       uint32_t hostname_len;
+       /* Optional, set to 0 to indicate it is not user-specified. */
+       uint32_t base_path_len;
+       uint32_t live_timer;
+       uint8_t snapshot;
+       uint8_t session_name_contains_creation_time;
+       /* Sessiond instance UUID */
+       lttng_uuid sessiond_uuid;
+       /* Sessiond session id */
+       uint64_t session_id;
+       /* Session creation time, in seconds since UNIX Epoch. */
+       uint64_t creation_time;
+       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED current_chunk_id;
+       /* Contains the session_name, hostname, base_path. */
+       char names[];
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_create_session_reply_2_11 {
+       struct lttcomm_relayd_status_session generic;
+       /* Includes the '\0' terminator. */
+       uint32_t output_path_length;
+       char output_path[];
+} LTTNG_PACKED;
+
+/*
+ * Used to ask the relay to reset the metadata trace file (regeneration).
+ * Send the new version of the metadata (starts at 0).
+ */
+struct lttcomm_relayd_reset_metadata {
+       uint64_t stream_id;
+       uint64_t version;
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_stream_rotation_position {
+       uint64_t stream_id;
+       /*
+        * Sequence number of the first packet belonging to the new
+        * "destination" trace chunk to which the stream is rotating.
+        *
+        * Ignored for metadata streams.
+        */
+       uint64_t rotate_at_seq_num;
+} LTTNG_PACKED;
+
+/*
+ * For certain releases, the LTTNG_PACKED annotation was missing on the
+ * `new_chunk_id` field which causes padding to be added between the
+ * "optional" structure's `is_set` and `value` fields.
+ *
+ * Three alignment cases are handled:
+ *   - `value` is aligned to the next byte boundary after `is_set`
+ *     no padding is produced, see
+ *     `struct lttcomm_relayd_rotate_streams_packed`,
+ *   - `value` is aligned to the next 4-byte boundary after `is_set`
+ *     (e.g. x86), 3 bytes of padding are produced, see
+ *     `struct lttcomm_relayd_rotate_streams_3_bytes_padding`,
+ *   - `value` is aligned to the next 8-byte boundary after `is_set`
+ *     (e.g. x86-64), 7 bytes of padding are produced, see
+ *     `struct lttcomm_relayd_rotate_streams_7_bytes_padding`.
+ *
+ * Note that since this structure's advertised size is used to determine
+ * the size of the padding it includes, it can't be extended with new
+ * optional fields. A new command would be needed.
+ */
+struct lttcomm_relayd_rotate_streams {
+       uint32_t stream_count;
+       /*
+        * Streams can be rotated outside of a chunk but not be parented to
+        * a new chunk.
+        *
+        * Improperly packed, but left as-is for backwards compatibility
+        * with unpatched relay daemons.
+        */
+       LTTNG_OPTIONAL_COMM(uint64_t) new_chunk_id;
+       /* `stream_count` positions follow. */
+       struct lttcomm_relayd_stream_rotation_position rotation_positions[];
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_rotate_streams_packed {
+       uint32_t stream_count;
+       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED new_chunk_id;
+       struct lttcomm_relayd_stream_rotation_position rotation_positions[];
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_rotate_streams_3_bytes_padding {
+       uint32_t stream_count;
+       struct {
+               union {
+                       uint8_t is_set;
+                       uint32_t padding;
+               };
+               uint64_t value;
+       } LTTNG_PACKED new_chunk_id;
+       struct lttcomm_relayd_stream_rotation_position rotation_positions[];
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_rotate_streams_7_bytes_padding {
+       uint32_t stream_count;
+       struct {
+               union {
+                       uint8_t is_set;
+                       uint64_t padding;
+               };
+               uint64_t value;
+       } LTTNG_PACKED new_chunk_id;
+       struct lttcomm_relayd_stream_rotation_position rotation_positions[];
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_create_trace_chunk {
+       uint64_t chunk_id;
+       /* Seconds since EPOCH. */
+       uint64_t creation_timestamp;
+       /* Includes trailing NULL. */
+       uint32_t override_name_length;
+       char override_name[];
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_close_trace_chunk {
+       uint64_t chunk_id;
+       /* Seconds since EPOCH. */
+       uint64_t close_timestamp;
+       /* enum lttng_trace_chunk_command_type */
+       LTTNG_OPTIONAL_COMM(uint32_t) LTTNG_PACKED close_command;
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_close_trace_chunk_reply {
+       struct lttcomm_relayd_generic_reply generic;
+       /* Includes trailing NULL. */
+       uint32_t path_length;
+       char path[];
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_trace_chunk_exists {
+       uint64_t chunk_id;
+} LTTNG_PACKED;
+
+struct lttcomm_relayd_trace_chunk_exists_reply {
+       struct lttcomm_relayd_generic_reply generic;
+       uint8_t trace_chunk_exists;
+} LTTNG_PACKED;
+
+enum lttcomm_relayd_configuration_flag {
+       /* The relay daemon (2.12) is configured to allow clear operations. */
+       LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED = (1 << 0),
+};
+
+struct lttcomm_relayd_get_configuration {
+       uint64_t query_flags;
+} LTTNG_PACKED;
+
+/*
+ * Used to return a relay daemon's configuration in reply to the
+ * RELAYD_GET_CONFIGURATION command.
+ */
+struct lttcomm_relayd_get_configuration_reply {
+       struct lttcomm_relayd_generic_reply generic;
+       /* Set of lttcomm_relayd_configuration_flag. */
+       uint64_t relayd_configuration_flags;
+       /* Optional variable-length payload. */
+       char payload[];
+} LTTNG_PACKED;
+
+#endif /* _RELAYD_COMM */
index 6a011b8b4cea9dfbb02661bb8bccb0668999bd95..0ddbad2ed1267dc0da9d1ebac349f7e4b74623d3 100644 (file)
 #include <unistd.h>
 #include <inttypes.h>
 
-#include <common/common.h>
-#include <common/compat/errno.h>
+#include <common/common.hpp>
+#include <common/compat/errno.hpp>
 
-#include "sessiond-comm.h"
+#include "sessiond-comm.hpp"
 
 /* For Unix socket */
-#include <common/unix.h>
+#include <common/unix.hpp>
 /* For Inet socket */
-#include "inet.h"
+#include "inet.hpp"
 /* For Inet6 socket */
-#include "inet6.h"
+#include "inet6.hpp"
 
 #define NETWORK_TIMEOUT_ENV    "LTTNG_NETWORK_SOCKET_TIMEOUT"
 
diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h
deleted file mode 100644 (file)
index ba756f8..0000000
+++ /dev/null
@@ -1,982 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-/*
- * This header is meant for liblttng and libust internal use ONLY. These
- * declarations should NOT be considered stable API.
- */
-
-#ifndef _LTTNG_SESSIOND_COMM_H
-#define _LTTNG_SESSIOND_COMM_H
-
-#include <limits.h>
-#include <lttng/lttng.h>
-#include <lttng/snapshot-internal.h>
-#include <lttng/save-internal.h>
-#include <lttng/channel-internal.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/rotate-internal.h>
-#include <common/compat/socket.h>
-#include <common/uri.h>
-#include <common/defaults.h>
-#include <common/uuid.h>
-#include <common/macros.h>
-#include <common/optional.h>
-
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <sys/un.h>
-
-#include "inet.h"
-#include "inet6.h"
-#include <common/unix.h>
-
-/* Queue size of listen(2) */
-#define LTTNG_SESSIOND_COMM_MAX_LISTEN 64
-
-/* Maximum number of FDs that can be sent over a Unix socket */
-#if defined(__linux__)
-/* Based on the kernel's SCM_MAX_FD which is 253 since 2.6.38 (255 before) */
-#define LTTCOMM_MAX_SEND_FDS           253
-#else
-#define LTTCOMM_MAX_SEND_FDS           16
-#endif
-
-enum lttcomm_sessiond_command {
-       /* Tracer command */
-       LTTNG_ADD_CONTEXT                               = 0,
-       /* LTTNG_CALIBRATE used to be here */
-       LTTNG_DISABLE_CHANNEL                           = 2,
-       LTTNG_DISABLE_EVENT                             = 3,
-       LTTNG_LIST_SYSCALLS                             = 4,
-       LTTNG_ENABLE_CHANNEL                            = 5,
-       LTTNG_ENABLE_EVENT                              = 6,
-       /* 7 */
-       /* Session daemon command */
-       /* 8 */
-       LTTNG_DESTROY_SESSION                           = 9,
-       LTTNG_LIST_CHANNELS                             = 10,
-       LTTNG_LIST_DOMAINS                              = 11,
-       LTTNG_LIST_EVENTS                               = 12,
-       LTTNG_LIST_SESSIONS                             = 13,
-       LTTNG_LIST_TRACEPOINTS                          = 14,
-       LTTNG_REGISTER_CONSUMER                         = 15,
-       LTTNG_START_TRACE                               = 16,
-       LTTNG_STOP_TRACE                                = 17,
-       LTTNG_LIST_TRACEPOINT_FIELDS                    = 18,
-
-       /* Consumer */
-       LTTNG_DISABLE_CONSUMER                          = 19,
-       LTTNG_ENABLE_CONSUMER                           = 20,
-       LTTNG_SET_CONSUMER_URI                          = 21,
-       /* 22 */
-       /* 23 */
-       LTTNG_DATA_PENDING                              = 24,
-       LTTNG_SNAPSHOT_ADD_OUTPUT                       = 25,
-       LTTNG_SNAPSHOT_DEL_OUTPUT                       = 26,
-       LTTNG_SNAPSHOT_LIST_OUTPUT                      = 27,
-       LTTNG_SNAPSHOT_RECORD                           = 28,
-       /* 29 */
-       /* 30 */
-       LTTNG_SAVE_SESSION                              = 31,
-       LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE    = 32,
-       LTTNG_PROCESS_ATTR_TRACKER_REMOVE_INCLUDE_VALUE = 33,
-       LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY           = 34,
-       LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY           = 35,
-       LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET     = 36,
-       LTTNG_SET_SESSION_SHM_PATH                      = 40,
-       LTTNG_REGENERATE_METADATA                       = 41,
-       LTTNG_REGENERATE_STATEDUMP                      = 42,
-       LTTNG_REGISTER_TRIGGER                          = 43,
-       LTTNG_UNREGISTER_TRIGGER                        = 44,
-       LTTNG_ROTATE_SESSION                            = 45,
-       LTTNG_ROTATION_GET_INFO                         = 46,
-       LTTNG_ROTATION_SET_SCHEDULE                     = 47,
-       LTTNG_SESSION_LIST_ROTATION_SCHEDULES           = 48,
-       LTTNG_CREATE_SESSION_EXT                        = 49,
-       LTTNG_CLEAR_SESSION                             = 50,
-       LTTNG_LIST_TRIGGERS                             = 51,
-       LTTNG_EXECUTE_ERROR_QUERY                       = 52,
-};
-
-static inline
-const char *lttcomm_sessiond_command_str(enum lttcomm_sessiond_command cmd)
-{
-       switch (cmd) {
-       case LTTNG_ADD_CONTEXT:
-               return "LTTNG_ADD_CONTEXT";
-       case LTTNG_DISABLE_CHANNEL:
-               return "LTTNG_DISABLE_CHANNEL";
-       case LTTNG_DISABLE_EVENT:
-               return "LTTNG_DISABLE_EVENT";
-       case LTTNG_LIST_SYSCALLS:
-               return "LTTNG_LIST_SYSCALLS";
-       case LTTNG_ENABLE_CHANNEL:
-               return "LTTNG_ENABLE_CHANNEL";
-       case LTTNG_ENABLE_EVENT:
-               return "LTTNG_ENABLE_EVENT";
-       case LTTNG_DESTROY_SESSION:
-               return "LTTNG_DESTROY_SESSION";
-       case LTTNG_LIST_CHANNELS:
-               return "LTTNG_LIST_CHANNELS";
-       case LTTNG_LIST_DOMAINS:
-               return "LTTNG_LIST_DOMAINS";
-       case LTTNG_LIST_EVENTS:
-               return "LTTNG_LIST_EVENTS";
-       case LTTNG_LIST_SESSIONS:
-               return "LTTNG_LIST_SESSIONS";
-       case LTTNG_LIST_TRACEPOINTS:
-               return "LTTNG_LIST_TRACEPOINTS";
-       case LTTNG_REGISTER_CONSUMER:
-               return "LTTNG_REGISTER_CONSUMER";
-       case LTTNG_START_TRACE:
-               return "LTTNG_START_TRACE";
-       case LTTNG_STOP_TRACE:
-               return "LTTNG_STOP_TRACE";
-       case LTTNG_LIST_TRACEPOINT_FIELDS:
-               return "LTTNG_LIST_TRACEPOINT_FIELDS";
-       case LTTNG_DISABLE_CONSUMER:
-               return "LTTNG_DISABLE_CONSUMER";
-       case LTTNG_ENABLE_CONSUMER:
-               return "LTTNG_ENABLE_CONSUMER";
-       case LTTNG_SET_CONSUMER_URI:
-               return "LTTNG_SET_CONSUMER_URI";
-       case LTTNG_DATA_PENDING:
-               return "LTTNG_DATA_PENDING";
-       case LTTNG_SNAPSHOT_ADD_OUTPUT:
-               return "LTTNG_SNAPSHOT_ADD_OUTPUT";
-       case LTTNG_SNAPSHOT_DEL_OUTPUT:
-               return "LTTNG_SNAPSHOT_DEL_OUTPUT";
-       case LTTNG_SNAPSHOT_LIST_OUTPUT:
-               return "LTTNG_SNAPSHOT_LIST_OUTPUT";
-       case LTTNG_SNAPSHOT_RECORD:
-               return "LTTNG_SNAPSHOT_RECORD";
-       case LTTNG_SAVE_SESSION:
-               return "LTTNG_SAVE_SESSION";
-       case LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE:
-               return "LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE";
-       case LTTNG_PROCESS_ATTR_TRACKER_REMOVE_INCLUDE_VALUE:
-               return "LTTNG_PROCESS_ATTR_TRACKER_REMOVE_INCLUDE_VALUE";
-       case LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY:
-               return "LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY";
-       case LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY:
-               return "LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY";
-       case LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET:
-               return "LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET";
-       case LTTNG_SET_SESSION_SHM_PATH:
-               return "LTTNG_SET_SESSION_SHM_PATH";
-       case LTTNG_REGENERATE_METADATA:
-               return "LTTNG_REGENERATE_METADATA";
-       case LTTNG_REGENERATE_STATEDUMP:
-               return "LTTNG_REGENERATE_STATEDUMP";
-       case LTTNG_REGISTER_TRIGGER:
-               return "LTTNG_REGISTER_TRIGGER";
-       case LTTNG_UNREGISTER_TRIGGER:
-               return "LTTNG_UNREGISTER_TRIGGER";
-       case LTTNG_ROTATE_SESSION:
-               return "LTTNG_ROTATE_SESSION";
-       case LTTNG_ROTATION_GET_INFO:
-               return "LTTNG_ROTATION_GET_INFO";
-       case LTTNG_ROTATION_SET_SCHEDULE:
-               return "LTTNG_ROTATION_SET_SCHEDULE";
-       case LTTNG_SESSION_LIST_ROTATION_SCHEDULES:
-               return "LTTNG_SESSION_LIST_ROTATION_SCHEDULES";
-       case LTTNG_CREATE_SESSION_EXT:
-               return "LTTNG_CREATE_SESSION_EXT";
-       case LTTNG_CLEAR_SESSION:
-               return "LTTNG_CLEAR_SESSION";
-       case LTTNG_LIST_TRIGGERS:
-               return "LTTNG_LIST_TRIGGERS";
-       case LTTNG_EXECUTE_ERROR_QUERY:
-               return "LTTNG_EXECUTE_ERROR_QUERY";
-       default:
-               abort();
-       }
-}
-
-enum lttcomm_relayd_command {
-       RELAYD_ADD_STREAM                   = 1,
-       RELAYD_CREATE_SESSION               = 2,
-       RELAYD_START_DATA                   = 3,
-       RELAYD_UPDATE_SYNC_INFO             = 4,
-       RELAYD_VERSION                      = 5,
-       RELAYD_SEND_METADATA                = 6,
-       RELAYD_CLOSE_STREAM                 = 7,
-       RELAYD_DATA_PENDING                 = 8,
-       RELAYD_QUIESCENT_CONTROL            = 9,
-       RELAYD_BEGIN_DATA_PENDING           = 10,
-       RELAYD_END_DATA_PENDING             = 11,
-       RELAYD_ADD_INDEX                    = 12,
-       RELAYD_SEND_INDEX                   = 13,
-       RELAYD_CLOSE_INDEX                  = 14,
-       /* Live-reading commands (2.4+). */
-       RELAYD_LIST_SESSIONS                = 15,
-       /* All streams of the channel have been sent to the relayd (2.4+). */
-       RELAYD_STREAMS_SENT                 = 16,
-       /* Ask the relay to reset the metadata trace file (2.8+) */
-       RELAYD_RESET_METADATA               = 17,
-       /* Ask the relay to rotate a set of stream files (2.11+) */
-       RELAYD_ROTATE_STREAMS                = 18,
-       /* Ask the relay to create a trace chunk (2.11+) */
-       RELAYD_CREATE_TRACE_CHUNK           = 19,
-       /* Ask the relay to close a trace chunk (2.11+) */
-       RELAYD_CLOSE_TRACE_CHUNK            = 20,
-       /* Ask the relay whether a trace chunk exists (2.11+) */
-       RELAYD_TRACE_CHUNK_EXISTS           = 21,
-       /* Get the current configuration of a relayd peer (2.12+) */
-       RELAYD_GET_CONFIGURATION            = 22,
-
-       /* Feature branch specific commands start at 10000. */
-};
-
-static inline
-const char *lttcomm_relayd_command_str(lttcomm_relayd_command cmd)
-{
-       switch (cmd) {
-       case RELAYD_ADD_STREAM:
-               return "RELAYD_ADD_STREAM";
-       case RELAYD_CREATE_SESSION:
-               return "RELAYD_CREATE_SESSION";
-       case RELAYD_START_DATA:
-               return "RELAYD_START_DATA";
-       case RELAYD_UPDATE_SYNC_INFO:
-               return "RELAYD_UPDATE_SYNC_INFO";
-       case RELAYD_VERSION:
-               return "RELAYD_VERSION";
-       case RELAYD_SEND_METADATA:
-               return "RELAYD_SEND_METADATA";
-       case RELAYD_CLOSE_STREAM:
-               return "RELAYD_CLOSE_STREAM";
-       case RELAYD_DATA_PENDING:
-               return "RELAYD_DATA_PENDING";
-       case RELAYD_QUIESCENT_CONTROL:
-               return "RELAYD_QUIESCENT_CONTROL";
-       case RELAYD_BEGIN_DATA_PENDING:
-               return "RELAYD_BEGIN_DATA_PENDING";
-       case RELAYD_END_DATA_PENDING:
-               return "RELAYD_END_DATA_PENDING";
-       case RELAYD_ADD_INDEX:
-               return "RELAYD_ADD_INDEX";
-       case RELAYD_SEND_INDEX:
-               return "RELAYD_SEND_INDEX";
-       case RELAYD_CLOSE_INDEX:
-               return "RELAYD_CLOSE_INDEX";
-       case RELAYD_LIST_SESSIONS:
-               return "RELAYD_LIST_SESSIONS";
-       case RELAYD_STREAMS_SENT:
-               return "RELAYD_STREAMS_SENT";
-       case RELAYD_RESET_METADATA:
-               return "RELAYD_RESET_METADATA";
-       case RELAYD_ROTATE_STREAMS:
-               return "RELAYD_ROTATE_STREAMS";
-       case RELAYD_CREATE_TRACE_CHUNK:
-               return "RELAYD_CREATE_TRACE_CHUNK";
-       case RELAYD_CLOSE_TRACE_CHUNK:
-               return "RELAYD_CLOSE_TRACE_CHUNK";
-       case RELAYD_TRACE_CHUNK_EXISTS:
-               return "RELAYD_TRACE_CHUNK_EXISTS";
-       case RELAYD_GET_CONFIGURATION:
-               return "RELAYD_GET_CONFIGURATION";
-       default:
-               abort();
-       }
-}
-
-/*
- * lttcomm error code.
- */
-enum lttcomm_return_code {
-       LTTCOMM_CONSUMERD_SUCCESS            = 0,   /* Everything went fine. */
-       /*
-        * Some code paths use -1 to express an error, others
-        * negate this consumer return code. Starting codes at
-        * 100 ensures there is no mix-up between this error value
-        * and legitimate status codes.
-        */
-       LTTCOMM_CONSUMERD_COMMAND_SOCK_READY = 100, /* Command socket ready */
-       LTTCOMM_CONSUMERD_SUCCESS_RECV_FD,          /* Success on receiving fds */
-       LTTCOMM_CONSUMERD_ERROR_RECV_FD,            /* Error on receiving fds */
-       LTTCOMM_CONSUMERD_ERROR_RECV_CMD,           /* Error on receiving command */
-       LTTCOMM_CONSUMERD_POLL_ERROR,               /* Error in polling thread */
-       LTTCOMM_CONSUMERD_POLL_NVAL,                /* Poll on closed fd */
-       LTTCOMM_CONSUMERD_POLL_HUP,                 /* All fds have hungup */
-       LTTCOMM_CONSUMERD_EXIT_SUCCESS,             /* Consumerd exiting normally */
-       LTTCOMM_CONSUMERD_EXIT_FAILURE,             /* Consumerd exiting on error */
-       LTTCOMM_CONSUMERD_OUTFD_ERROR,              /* Error opening the tracefile */
-       LTTCOMM_CONSUMERD_SPLICE_EBADF,             /* EBADF from splice(2) */
-       LTTCOMM_CONSUMERD_SPLICE_EINVAL,            /* EINVAL from splice(2) */
-       LTTCOMM_CONSUMERD_SPLICE_ENOMEM,            /* ENOMEM from splice(2) */
-       LTTCOMM_CONSUMERD_SPLICE_ESPIPE,            /* ESPIPE from splice(2) */
-       LTTCOMM_CONSUMERD_ENOMEM,                   /* Consumer is out of memory */
-       LTTCOMM_CONSUMERD_ERROR_METADATA,           /* Error with metadata. */
-       LTTCOMM_CONSUMERD_FATAL,                    /* Fatal error. */
-       LTTCOMM_CONSUMERD_RELAYD_FAIL,              /* Error on remote relayd */
-       LTTCOMM_CONSUMERD_CHANNEL_FAIL,             /* Channel creation failed. */
-       LTTCOMM_CONSUMERD_CHAN_NOT_FOUND,           /* Channel not found. */
-       LTTCOMM_CONSUMERD_ALREADY_SET,              /* Resource already set. */
-       LTTCOMM_CONSUMERD_ROTATION_FAIL,            /* Rotation has failed. */
-       LTTCOMM_CONSUMERD_SNAPSHOT_FAILED,          /* snapshot has failed. */
-       LTTCOMM_CONSUMERD_CREATE_TRACE_CHUNK_FAILED,/* Trace chunk creation failed. */
-       LTTCOMM_CONSUMERD_CLOSE_TRACE_CHUNK_FAILED, /* Trace chunk close failed. */
-       LTTCOMM_CONSUMERD_INVALID_PARAMETERS,       /* Invalid parameters. */
-       LTTCOMM_CONSUMERD_TRACE_CHUNK_EXISTS_LOCAL, /* Trace chunk exists on consumer daemon. */
-       LTTCOMM_CONSUMERD_TRACE_CHUNK_EXISTS_REMOTE,/* Trace chunk exists on relay daemon. */
-       LTTCOMM_CONSUMERD_UNKNOWN_TRACE_CHUNK,      /* Unknown trace chunk. */
-       LTTCOMM_CONSUMERD_RELAYD_CLEAR_DISALLOWED,  /* Relayd does not accept clear command. */
-       LTTCOMM_CONSUMERD_UNKNOWN_ERROR,            /* Unknown error. */
-
-       /* MUST be last element */
-       LTTCOMM_NR,                                             /* Last element */
-};
-
-/* lttng socket protocol. */
-enum lttcomm_sock_proto {
-       LTTCOMM_SOCK_UDP,
-       LTTCOMM_SOCK_TCP,
-};
-
-/*
- * Index in the net_families array below. Please keep in sync!
- */
-enum lttcomm_sock_domain {
-       LTTCOMM_INET      = 0,
-       LTTCOMM_INET6     = 1,
-};
-
-enum lttcomm_metadata_command {
-       LTTCOMM_METADATA_REQUEST = 1,
-};
-
-/*
- * Commands sent from the consumerd to the sessiond to request if new metadata
- * is available. This message is used to find the per UID _or_ per PID registry
- * for the channel key. For per UID lookup, the triplet
- * bits_per_long/uid/session_id is used. On lookup failure, we search for the
- * per PID registry indexed by session id ignoring the other values.
- */
-struct lttcomm_metadata_request_msg {
-       uint64_t session_id; /* Tracing session id */
-       uint64_t session_id_per_pid; /* Tracing session id for per-pid */
-       uint32_t bits_per_long; /* Consumer ABI */
-       uint32_t uid;
-       uint64_t key; /* Metadata channel key. */
-} LTTNG_PACKED;
-
-struct lttcomm_sockaddr {
-       enum lttcomm_sock_domain type;
-       union {
-               struct sockaddr_in sin;
-               struct sockaddr_in6 sin6;
-       } addr;
-} LTTNG_PACKED;
-
-struct lttcomm_sock {
-       int32_t fd;
-       enum lttcomm_sock_proto proto;
-       struct lttcomm_sockaddr sockaddr;
-       const struct lttcomm_proto_ops *ops;
-} LTTNG_PACKED;
-
-/*
- * Relayd sock. Adds the protocol version to use for the communications with
- * the relayd.
- */
-struct lttcomm_relayd_sock {
-       struct lttcomm_sock sock;
-       uint32_t major;
-       uint32_t minor;
-} LTTNG_PACKED;
-
-struct lttcomm_net_family {
-       int family;
-       int (*create) (struct lttcomm_sock *sock, int type, int proto);
-};
-
-struct lttcomm_proto_ops {
-       int (*bind) (struct lttcomm_sock *sock);
-       int (*close) (struct lttcomm_sock *sock);
-       int (*connect) (struct lttcomm_sock *sock);
-       struct lttcomm_sock *(*accept) (struct lttcomm_sock *sock);
-       int (*listen) (struct lttcomm_sock *sock, int backlog);
-       ssize_t (*recvmsg) (struct lttcomm_sock *sock, void *buf, size_t len,
-                       int flags);
-       ssize_t (*sendmsg) (struct lttcomm_sock *sock, const void *buf,
-                       size_t len, int flags);
-};
-
-struct process_attr_integral_value_comm {
-       union {
-               int64_t _signed;
-               uint64_t _unsigned;
-       } u;
-} LTTNG_PACKED;
-
-/*
- * Data structure received from lttng client to session daemon.
- */
-struct lttcomm_session_msg {
-       uint32_t cmd_type;      /* enum lttcomm_sessiond_command */
-       struct lttng_session session;
-       struct lttng_domain domain;
-       union {
-               /* Event data */
-               struct {
-                       char channel_name[LTTNG_SYMBOL_NAME_LEN];
-                       struct lttng_event event;
-                       /* Length of following filter expression. */
-                       uint32_t expression_len;
-                       /* Length of following bytecode for filter. */
-                       uint32_t bytecode_len;
-                       /* Exclusion count (fixed-size strings). */
-                       uint32_t exclusion_count;
-                       /* Userspace probe location size. */
-                       uint32_t userspace_probe_location_len;
-                       /*
-                        * After this structure, the following variable-length
-                        * items are transmitted:
-                        * - char exclusion_names[LTTNG_SYMBOL_NAME_LEN][exclusion_count]
-                        * - char filter_expression[expression_len]
-                        * - unsigned char filter_bytecode[bytecode_len]
-                        */
-               } LTTNG_PACKED enable;
-               struct {
-                       char channel_name[LTTNG_SYMBOL_NAME_LEN];
-                       struct lttng_event event;
-                       /* Length of following filter expression. */
-                       uint32_t expression_len;
-                       /* Length of following bytecode for filter. */
-                       uint32_t bytecode_len;
-                       /*
-                        * After this structure, the following variable-length
-                        * items are transmitted:
-                        * - unsigned char filter_expression[expression_len]
-                        * - unsigned char filter_bytecode[bytecode_len]
-                        */
-               } LTTNG_PACKED disable;
-               /* Create channel */
-               struct {
-                       struct lttng_channel chan;
-                       struct lttng_channel_extended extended;
-               } LTTNG_PACKED channel;
-               /* Context */
-               struct {
-                       char channel_name[LTTNG_SYMBOL_NAME_LEN];
-                       struct lttng_event_context ctx;
-                       uint32_t provider_name_len;
-                       uint32_t context_name_len;
-               } LTTNG_PACKED context;
-               /* Use by register_consumer */
-               struct {
-                       char path[PATH_MAX];
-               } LTTNG_PACKED reg;
-               /* List */
-               struct {
-                       char channel_name[LTTNG_SYMBOL_NAME_LEN];
-               } LTTNG_PACKED list;
-               struct lttng_calibrate calibrate;
-               /* Used by the set_consumer_url and used by create_session also call */
-               struct {
-                       /* Number of lttng_uri following */
-                       uint32_t size;
-               } LTTNG_PACKED uri;
-               struct {
-                       struct lttng_snapshot_output output;
-               } LTTNG_PACKED snapshot_output;
-               struct {
-                       uint32_t wait;
-                       struct lttng_snapshot_output output;
-               } LTTNG_PACKED snapshot_record;
-               struct {
-                       uint32_t nb_uri;
-                       unsigned int timer_interval;    /* usec */
-               } LTTNG_PACKED session_live;
-               struct {
-                       struct lttng_save_session_attr attr;
-               } LTTNG_PACKED save_session;
-               struct {
-                       char shm_path[PATH_MAX];
-               } LTTNG_PACKED set_shm_path;
-               struct {
-                       /* enum lttng_process_attr */
-                       int32_t process_attr;
-                       /* enum lttng_process_attr_value_type */
-                       int32_t value_type;
-
-                       struct process_attr_integral_value_comm integral_value;
-                       /*
-                        * For user/group names, a variable length,
-                        * zero-terminated, string of length 'name_len'
-                        * (including the terminator) follows.
-                        *
-                        * integral_value should not be used in those cases.
-                        */
-                       uint32_t name_len;
-               } LTTNG_PACKED process_attr_tracker_add_remove_include_value;
-               struct {
-                       /* enum lttng_process_attr */
-                       int32_t process_attr;
-               } LTTNG_PACKED process_attr_tracker_get_inclusion_set;
-               struct {
-                       /* enum lttng_process_attr */
-                       int32_t process_attr;
-               } LTTNG_PACKED process_attr_tracker_get_tracking_policy;
-               struct {
-                       /* enum lttng_process_attr */
-                       int32_t process_attr;
-                       /* enum lttng_tracking_policy */
-                       int32_t tracking_policy;
-               } LTTNG_PACKED process_attr_tracker_set_tracking_policy;
-               struct {
-                       uint32_t length;
-                       uint8_t is_trigger_anonymous;
-               } LTTNG_PACKED trigger;
-               struct {
-                       uint32_t length;
-               } LTTNG_PACKED error_query;
-               struct {
-                       uint64_t rotation_id;
-               } LTTNG_PACKED get_rotation_info;
-               struct {
-                       /* enum lttng_rotation_schedule_type */
-                       uint8_t type;
-                       /*
-                        * If set == 1, set schedule to value, if set == 0,
-                        * clear this schedule type.
-                        */
-                       uint8_t set;
-                       uint64_t value;
-               } LTTNG_PACKED rotation_set_schedule;
-               struct {
-                       /*
-                        * Includes the null-terminator.
-                        * Must be an absolute path.
-                        *
-                        * Size bounded by LTTNG_PATH_MAX.
-                        */
-                       uint16_t home_dir_size;
-                       uint64_t session_descriptor_size;
-                       /* An lttng_session_descriptor follows. */
-               } LTTNG_PACKED create_session;
-       } u;
-       /* Count of fds sent. */
-       uint32_t fd_count;
-} LTTNG_PACKED;
-
-#define LTTNG_FILTER_MAX_LEN   65536
-#define LTTNG_SESSION_DESCRIPTOR_MAX_LEN       65536
-
-/*
- * Filter bytecode data. The reloc table is located at the end of the
- * bytecode. It is made of tuples: (uint16_t, var. len. string). It
- * starts at reloc_table_offset.
- */
-#define LTTNG_FILTER_PADDING   32
-struct lttng_bytecode {
-       uint32_t len;   /* len of data */
-       uint32_t reloc_table_offset;
-       uint64_t seqnum;
-       char padding[LTTNG_FILTER_PADDING];
-       char data[0];
-} LTTNG_PACKED;
-
-/*
- * Event exclusion data. At the end of the structure, there will actually
- * by zero or more names, where the actual number of names is given by
- * the 'count' item of the structure.
- */
-#define LTTNG_EVENT_EXCLUSION_PADDING  32
-struct lttng_event_exclusion {
-       uint32_t count;
-       char padding[LTTNG_EVENT_EXCLUSION_PADDING];
-       char names[0][LTTNG_SYMBOL_NAME_LEN];
-} LTTNG_PACKED;
-
-#define LTTNG_EVENT_EXCLUSION_NAME_AT(_exclusion, _i) \
-       (&(_exclusion)->names[_i][0])
-
-/*
- * Event command header.
- */
-struct lttcomm_event_command_header {
-       /* Number of events */
-       uint32_t nb_events;
-} LTTNG_PACKED;
-
-/*
- * Event extended info header. This is the structure preceding each
- * extended info data.
- */
-struct lttcomm_event_extended_header {
-       /*
-        * Size of filter string immediately following this header.
-        * This size includes the terminal null character.
-        */
-       uint32_t filter_len;
-
-       /*
-        * Number of exclusion names, immediately following the filter
-        * string. Each exclusion name has a fixed length of
-        * LTTNG_SYMBOL_NAME_LEN bytes, including the terminal null
-        * character.
-        */
-       uint32_t nb_exclusions;
-
-       /*
-        * Size of the event's userspace probe location (if applicable).
-        */
-       uint32_t userspace_probe_location_len;
-} LTTNG_PACKED;
-
-/*
- * Command header of the reply to an LTTNG_DESTROY_SESSION command.
- */
-struct lttcomm_session_destroy_command_header {
-       /* enum lttng_session */
-       int32_t rotation_state;
-};
-
-/*
- * tracker command header.
- */
-struct lttcomm_tracker_command_header {
-       uint32_t nb_tracker_id;
-} LTTNG_PACKED;
-
-/*
- * Data structure for the response from sessiond to the lttng client.
- */
-struct lttcomm_lttng_msg {
-       uint32_t cmd_type;      /* enum lttcomm_sessiond_command */
-       uint32_t ret_code;      /* enum lttcomm_return_code */
-       uint32_t pid;           /* pid_t */
-       uint32_t cmd_header_size;
-       uint32_t data_size;
-       uint32_t fd_count;
-} LTTNG_PACKED;
-
-struct lttcomm_lttng_output_id {
-       uint32_t id;
-} LTTNG_PACKED;
-
-/*
- * lttcomm_consumer_msg is the message sent from sessiond to consumerd
- * to either add a channel, add a stream, update a stream, or stop
- * operation.
- */
-struct lttcomm_consumer_msg {
-       uint32_t cmd_type;      /* enum lttng_consumer_command */
-       union {
-               struct {
-                       uint64_t channel_key;
-                       uint64_t session_id;
-                       /* ID of the session's current trace chunk. */
-                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED chunk_id;
-                       char pathname[PATH_MAX];
-                       uint64_t relayd_id;
-                       /* nb_init_streams is the number of streams open initially. */
-                       uint32_t nb_init_streams;
-                       char name[LTTNG_SYMBOL_NAME_LEN];
-                       /* Use splice or mmap to consume this fd */
-                       enum lttng_event_output output;
-                       int type; /* Per cpu or metadata. */
-                       uint64_t tracefile_size; /* bytes */
-                       uint32_t tracefile_count; /* number of tracefiles */
-                       /* If the channel's streams have to be monitored or not. */
-                       uint32_t monitor;
-                       /* timer to check the streams usage in live mode (usec). */
-                       unsigned int live_timer_interval;
-                       /* is part of a live session */
-                       uint8_t is_live;
-                       /* timer to sample a channel's positions (usec). */
-                       unsigned int monitor_timer_interval;
-               } LTTNG_PACKED channel; /* Only used by Kernel. */
-               struct {
-                       uint64_t stream_key;
-                       uint64_t channel_key;
-                       int32_t cpu;    /* On which CPU this stream is assigned. */
-                       /* Tells the consumer if the stream should be or not monitored. */
-                       uint32_t no_monitor;
-               } LTTNG_PACKED stream;  /* Only used by Kernel. */
-               struct {
-                       uint64_t net_index;
-                       enum lttng_stream_type type;
-                       /* Open socket to the relayd */
-                       struct lttcomm_relayd_sock sock;
-                       /* Tracing session id associated to the relayd. */
-                       uint64_t session_id;
-                       /* Relayd session id, only used with control socket. */
-                       uint64_t relayd_session_id;
-               } LTTNG_PACKED relayd_sock;
-               struct {
-                       uint64_t net_seq_idx;
-               } LTTNG_PACKED destroy_relayd;
-               struct {
-                       uint64_t session_id;
-               } LTTNG_PACKED data_pending;
-               struct {
-                       uint64_t subbuf_size;                   /* bytes */
-                       uint64_t num_subbuf;                    /* power of 2 */
-                       int32_t overwrite;                      /* 1: overwrite, 0: discard */
-                       uint32_t switch_timer_interval;         /* usec */
-                       uint32_t read_timer_interval;           /* usec */
-                       unsigned int live_timer_interval;       /* usec */
-                       uint8_t is_live;                        /* is part of a live session */
-                       uint32_t monitor_timer_interval;        /* usec */
-                       int32_t output;                         /* splice, mmap */
-                       int32_t type;                           /* metadata or per_cpu */
-                       uint64_t session_id;                    /* Tracing session id */
-                       char pathname[PATH_MAX];                /* Channel file path. */
-                       char name[LTTNG_SYMBOL_NAME_LEN];       /* Channel name. */
-                       /* Credentials used to open the UST buffer shared mappings. */
-                       struct {
-                               uint32_t uid;
-                               uint32_t gid;
-                       } LTTNG_PACKED buffer_credentials;
-                       uint64_t relayd_id;                     /* Relayd id if apply. */
-                       uint64_t key;                           /* Unique channel key. */
-                       /* ID of the session's current trace chunk. */
-                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED chunk_id;
-                       unsigned char uuid[LTTNG_UUID_LEN];     /* uuid for ust tracer. */
-                       uint32_t chan_id;                       /* Channel ID on the tracer side. */
-                       uint64_t tracefile_size;        /* bytes */
-                       uint32_t tracefile_count;       /* number of tracefiles */
-                       uint64_t session_id_per_pid;    /* Per-pid session ID. */
-                       /* Tells the consumer if the stream should be or not monitored. */
-                       uint32_t monitor;
-                       /*
-                        * For UST per UID buffers, this is the application UID of the
-                        * channel.  This can be different from the user UID requesting the
-                        * channel creation and used for the rights on the stream file
-                        * because the application can be in the tracing for instance.
-                        */
-                       uint32_t ust_app_uid;
-                       int64_t blocking_timeout;
-                       char root_shm_path[PATH_MAX];
-                       char shm_path[PATH_MAX];
-               } LTTNG_PACKED ask_channel;
-               struct {
-                       uint64_t key;
-               } LTTNG_PACKED get_channel;
-               struct {
-                       uint64_t key;
-               } LTTNG_PACKED destroy_channel;
-               struct {
-                       uint64_t key;   /* Metadata channel key. */
-                       uint64_t target_offset; /* Offset in the consumer */
-                       uint64_t len;   /* Length of metadata to be received. */
-                       uint64_t version; /* Version of the metadata. */
-               } LTTNG_PACKED push_metadata;
-               struct {
-                       uint64_t key;   /* Metadata channel key. */
-               } LTTNG_PACKED close_metadata;
-               struct {
-                       uint64_t key;   /* Metadata channel key. */
-               } LTTNG_PACKED setup_metadata;
-               struct {
-                       uint64_t key;   /* Channel key. */
-               } LTTNG_PACKED flush_channel;
-               struct {
-                       uint64_t key;   /* Channel key. */
-               } LTTNG_PACKED clear_quiescent_channel;
-               struct {
-                       char pathname[PATH_MAX];
-                       /* Indicate if the snapshot goes on the relayd or locally. */
-                       uint32_t use_relayd;
-                       uint32_t metadata;              /* This a metadata snapshot. */
-                       uint64_t relayd_id;             /* Relayd id if apply. */
-                       uint64_t key;
-                       uint64_t nb_packets_per_stream;
-               } LTTNG_PACKED snapshot_channel;
-               struct {
-                       uint64_t channel_key;
-                       uint64_t net_seq_idx;
-               } LTTNG_PACKED sent_streams;
-               struct {
-                       uint64_t session_id;
-                       uint64_t channel_key;
-               } LTTNG_PACKED discarded_events;
-               struct {
-                       uint64_t session_id;
-                       uint64_t channel_key;
-               } LTTNG_PACKED lost_packets;
-               struct {
-                       uint64_t session_id;
-               } LTTNG_PACKED regenerate_metadata;
-               struct {
-                       uint32_t metadata; /* This is a metadata channel. */
-                       uint64_t relayd_id; /* Relayd id if apply. */
-                       uint64_t key;
-               } LTTNG_PACKED rotate_channel;
-               struct {
-                       uint64_t session_id;
-                       uint64_t chunk_id;
-               } LTTNG_PACKED check_rotation_pending_local;
-               struct {
-                       uint64_t relayd_id;
-                       uint64_t session_id;
-                       uint64_t chunk_id;
-               } LTTNG_PACKED check_rotation_pending_relay;
-               struct {
-                       /*
-                        * Relayd id, if applicable (remote).
-                        *
-                        * A directory file descriptor referring to the chunk's
-                        * output folder is transmitted if the chunk is local
-                        * (relayd_id unset).
-                        *
-                        * `override_name` is left NULL (all-zeroes) if the
-                        * chunk's name is not overridden.
-                        */
-                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED relayd_id;
-                       char override_name[LTTNG_NAME_MAX];
-                       uint64_t session_id;
-                       uint64_t chunk_id;
-                       uint64_t creation_timestamp;
-                       LTTNG_OPTIONAL_COMM(struct {
-                               uint32_t uid;
-                               uint32_t gid;
-                       } LTTNG_PACKED ) LTTNG_PACKED credentials;
-               } LTTNG_PACKED create_trace_chunk;
-               struct {
-                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED relayd_id;
-                       uint64_t session_id;
-                       uint64_t chunk_id;
-                       uint64_t close_timestamp;
-                       /* enum lttng_trace_chunk_command_type */
-                       LTTNG_OPTIONAL_COMM(uint32_t) LTTNG_PACKED close_command;
-               } LTTNG_PACKED close_trace_chunk;
-               struct {
-                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED relayd_id;
-                       uint64_t session_id;
-                       uint64_t chunk_id;
-               } LTTNG_PACKED trace_chunk_exists;
-               struct {
-                       lttng_uuid sessiond_uuid;
-               } LTTNG_PACKED init;
-               struct {
-                       uint64_t key;
-               } LTTNG_PACKED clear_channel;
-               struct {
-                       uint64_t key;
-               } LTTNG_PACKED open_channel_packets;
-       } u;
-} LTTNG_PACKED;
-
-/*
- * Channel monitoring message returned to the session daemon on every
- * monitor timer expiration.
- */
-struct lttcomm_consumer_channel_monitor_msg {
-       /* Key of the sampled channel. */
-       uint64_t key;
-       /*
-        * Lowest and highest usage (bytes) at the moment the sample was taken.
-        */
-       uint64_t lowest, highest;
-       /*
-        * Sum of all the consumed positions for a channel.
-        */
-       uint64_t total_consumed;
-} LTTNG_PACKED;
-
-/*
- * Status message returned to the sessiond after a received command.
- */
-struct lttcomm_consumer_status_msg {
-       enum lttcomm_return_code ret_code;
-} LTTNG_PACKED;
-
-struct lttcomm_consumer_status_channel {
-       enum lttcomm_return_code ret_code;
-       uint64_t key;
-       unsigned int stream_count;
-} LTTNG_PACKED;
-
-struct lttcomm_consumer_close_trace_chunk_reply {
-       enum lttcomm_return_code ret_code;
-       uint32_t path_length;
-       char path[];
-};
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-#include <lttng/ust-abi.h>
-
-/*
- * Data structure for the commands sent from sessiond to UST.
- */
-struct lttcomm_ust_msg {
-       uint32_t handle;
-       uint32_t cmd;
-       union {
-               struct lttng_ust_abi_channel channel;
-               struct lttng_ust_abi_stream stream;
-               struct lttng_ust_abi_event event;
-               struct lttng_ust_abi_context context;
-               struct lttng_ust_abi_tracer_version version;
-       } u;
-} LTTNG_PACKED;
-
-/*
- * Data structure for the response from UST to the session daemon.
- * cmd_type is sent back in the reply for validation.
- */
-struct lttcomm_ust_reply {
-       uint32_t handle;
-       uint32_t cmd;
-       uint32_t ret_code;      /* enum lttcomm_return_code */
-       uint32_t ret_val;       /* return value */
-       union {
-               struct {
-                       uint64_t memory_map_size;
-               } LTTNG_PACKED channel;
-               struct {
-                       uint64_t memory_map_size;
-               } LTTNG_PACKED stream;
-               struct lttng_ust_abi_tracer_version version;
-       } u;
-} LTTNG_PACKED;
-
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-const char *lttcomm_get_readable_code(enum lttcomm_return_code code);
-
-int lttcomm_init_inet_sockaddr(struct lttcomm_sockaddr *sockaddr,
-               const char *ip, unsigned int port);
-int lttcomm_init_inet6_sockaddr(struct lttcomm_sockaddr *sockaddr,
-               const char *ip, unsigned int port);
-
-struct lttcomm_sock *lttcomm_alloc_sock(enum lttcomm_sock_proto proto);
-int lttcomm_create_sock(struct lttcomm_sock *sock);
-struct lttcomm_sock *lttcomm_alloc_sock_from_uri(struct lttng_uri *uri);
-void lttcomm_destroy_sock(struct lttcomm_sock *sock);
-struct lttcomm_sock *lttcomm_alloc_copy_sock(struct lttcomm_sock *src);
-void lttcomm_copy_sock(struct lttcomm_sock *dst,
-               struct lttcomm_sock *src);
-
-/* Relayd socket object. */
-struct lttcomm_relayd_sock *lttcomm_alloc_relayd_sock(
-               struct lttng_uri *uri, uint32_t major, uint32_t minor);
-
-int lttcomm_setsockopt_rcv_timeout(int sock, unsigned int msec);
-int lttcomm_setsockopt_snd_timeout(int sock, unsigned int msec);
-
-int lttcomm_sock_get_port(const struct lttcomm_sock *sock,
-               uint16_t *port);
-/*
- * Set a port to an lttcomm_sock. This will have no effect is the socket is
- * already bound.
- */
-int lttcomm_sock_set_port(struct lttcomm_sock *sock, uint16_t port);
-
-void lttcomm_init(void);
-/* Get network timeout, in milliseconds */
-unsigned long lttcomm_get_network_timeout(void);
-
-#endif /* _LTTNG_SESSIOND_COMM_H */
diff --git a/src/common/sessiond-comm/sessiond-comm.hpp b/src/common/sessiond-comm/sessiond-comm.hpp
new file mode 100644 (file)
index 0000000..871f62c
--- /dev/null
@@ -0,0 +1,982 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+/*
+ * This header is meant for liblttng and libust internal use ONLY. These
+ * declarations should NOT be considered stable API.
+ */
+
+#ifndef _LTTNG_SESSIOND_COMM_H
+#define _LTTNG_SESSIOND_COMM_H
+
+#include <limits.h>
+#include <lttng/lttng.h>
+#include <lttng/snapshot-internal.hpp>
+#include <lttng/save-internal.hpp>
+#include <lttng/channel-internal.hpp>
+#include <lttng/trigger/trigger-internal.hpp>
+#include <lttng/rotate-internal.hpp>
+#include <common/compat/socket.hpp>
+#include <common/uri.hpp>
+#include <common/defaults.hpp>
+#include <common/uuid.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "inet.hpp"
+#include "inet6.hpp"
+#include <common/unix.hpp>
+
+/* Queue size of listen(2) */
+#define LTTNG_SESSIOND_COMM_MAX_LISTEN 64
+
+/* Maximum number of FDs that can be sent over a Unix socket */
+#if defined(__linux__)
+/* Based on the kernel's SCM_MAX_FD which is 253 since 2.6.38 (255 before) */
+#define LTTCOMM_MAX_SEND_FDS           253
+#else
+#define LTTCOMM_MAX_SEND_FDS           16
+#endif
+
+enum lttcomm_sessiond_command {
+       /* Tracer command */
+       LTTNG_ADD_CONTEXT                               = 0,
+       /* LTTNG_CALIBRATE used to be here */
+       LTTNG_DISABLE_CHANNEL                           = 2,
+       LTTNG_DISABLE_EVENT                             = 3,
+       LTTNG_LIST_SYSCALLS                             = 4,
+       LTTNG_ENABLE_CHANNEL                            = 5,
+       LTTNG_ENABLE_EVENT                              = 6,
+       /* 7 */
+       /* Session daemon command */
+       /* 8 */
+       LTTNG_DESTROY_SESSION                           = 9,
+       LTTNG_LIST_CHANNELS                             = 10,
+       LTTNG_LIST_DOMAINS                              = 11,
+       LTTNG_LIST_EVENTS                               = 12,
+       LTTNG_LIST_SESSIONS                             = 13,
+       LTTNG_LIST_TRACEPOINTS                          = 14,
+       LTTNG_REGISTER_CONSUMER                         = 15,
+       LTTNG_START_TRACE                               = 16,
+       LTTNG_STOP_TRACE                                = 17,
+       LTTNG_LIST_TRACEPOINT_FIELDS                    = 18,
+
+       /* Consumer */
+       LTTNG_DISABLE_CONSUMER                          = 19,
+       LTTNG_ENABLE_CONSUMER                           = 20,
+       LTTNG_SET_CONSUMER_URI                          = 21,
+       /* 22 */
+       /* 23 */
+       LTTNG_DATA_PENDING                              = 24,
+       LTTNG_SNAPSHOT_ADD_OUTPUT                       = 25,
+       LTTNG_SNAPSHOT_DEL_OUTPUT                       = 26,
+       LTTNG_SNAPSHOT_LIST_OUTPUT                      = 27,
+       LTTNG_SNAPSHOT_RECORD                           = 28,
+       /* 29 */
+       /* 30 */
+       LTTNG_SAVE_SESSION                              = 31,
+       LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE    = 32,
+       LTTNG_PROCESS_ATTR_TRACKER_REMOVE_INCLUDE_VALUE = 33,
+       LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY           = 34,
+       LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY           = 35,
+       LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET     = 36,
+       LTTNG_SET_SESSION_SHM_PATH                      = 40,
+       LTTNG_REGENERATE_METADATA                       = 41,
+       LTTNG_REGENERATE_STATEDUMP                      = 42,
+       LTTNG_REGISTER_TRIGGER                          = 43,
+       LTTNG_UNREGISTER_TRIGGER                        = 44,
+       LTTNG_ROTATE_SESSION                            = 45,
+       LTTNG_ROTATION_GET_INFO                         = 46,
+       LTTNG_ROTATION_SET_SCHEDULE                     = 47,
+       LTTNG_SESSION_LIST_ROTATION_SCHEDULES           = 48,
+       LTTNG_CREATE_SESSION_EXT                        = 49,
+       LTTNG_CLEAR_SESSION                             = 50,
+       LTTNG_LIST_TRIGGERS                             = 51,
+       LTTNG_EXECUTE_ERROR_QUERY                       = 52,
+};
+
+static inline
+const char *lttcomm_sessiond_command_str(enum lttcomm_sessiond_command cmd)
+{
+       switch (cmd) {
+       case LTTNG_ADD_CONTEXT:
+               return "LTTNG_ADD_CONTEXT";
+       case LTTNG_DISABLE_CHANNEL:
+               return "LTTNG_DISABLE_CHANNEL";
+       case LTTNG_DISABLE_EVENT:
+               return "LTTNG_DISABLE_EVENT";
+       case LTTNG_LIST_SYSCALLS:
+               return "LTTNG_LIST_SYSCALLS";
+       case LTTNG_ENABLE_CHANNEL:
+               return "LTTNG_ENABLE_CHANNEL";
+       case LTTNG_ENABLE_EVENT:
+               return "LTTNG_ENABLE_EVENT";
+       case LTTNG_DESTROY_SESSION:
+               return "LTTNG_DESTROY_SESSION";
+       case LTTNG_LIST_CHANNELS:
+               return "LTTNG_LIST_CHANNELS";
+       case LTTNG_LIST_DOMAINS:
+               return "LTTNG_LIST_DOMAINS";
+       case LTTNG_LIST_EVENTS:
+               return "LTTNG_LIST_EVENTS";
+       case LTTNG_LIST_SESSIONS:
+               return "LTTNG_LIST_SESSIONS";
+       case LTTNG_LIST_TRACEPOINTS:
+               return "LTTNG_LIST_TRACEPOINTS";
+       case LTTNG_REGISTER_CONSUMER:
+               return "LTTNG_REGISTER_CONSUMER";
+       case LTTNG_START_TRACE:
+               return "LTTNG_START_TRACE";
+       case LTTNG_STOP_TRACE:
+               return "LTTNG_STOP_TRACE";
+       case LTTNG_LIST_TRACEPOINT_FIELDS:
+               return "LTTNG_LIST_TRACEPOINT_FIELDS";
+       case LTTNG_DISABLE_CONSUMER:
+               return "LTTNG_DISABLE_CONSUMER";
+       case LTTNG_ENABLE_CONSUMER:
+               return "LTTNG_ENABLE_CONSUMER";
+       case LTTNG_SET_CONSUMER_URI:
+               return "LTTNG_SET_CONSUMER_URI";
+       case LTTNG_DATA_PENDING:
+               return "LTTNG_DATA_PENDING";
+       case LTTNG_SNAPSHOT_ADD_OUTPUT:
+               return "LTTNG_SNAPSHOT_ADD_OUTPUT";
+       case LTTNG_SNAPSHOT_DEL_OUTPUT:
+               return "LTTNG_SNAPSHOT_DEL_OUTPUT";
+       case LTTNG_SNAPSHOT_LIST_OUTPUT:
+               return "LTTNG_SNAPSHOT_LIST_OUTPUT";
+       case LTTNG_SNAPSHOT_RECORD:
+               return "LTTNG_SNAPSHOT_RECORD";
+       case LTTNG_SAVE_SESSION:
+               return "LTTNG_SAVE_SESSION";
+       case LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE:
+               return "LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE";
+       case LTTNG_PROCESS_ATTR_TRACKER_REMOVE_INCLUDE_VALUE:
+               return "LTTNG_PROCESS_ATTR_TRACKER_REMOVE_INCLUDE_VALUE";
+       case LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY:
+               return "LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY";
+       case LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY:
+               return "LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY";
+       case LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET:
+               return "LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET";
+       case LTTNG_SET_SESSION_SHM_PATH:
+               return "LTTNG_SET_SESSION_SHM_PATH";
+       case LTTNG_REGENERATE_METADATA:
+               return "LTTNG_REGENERATE_METADATA";
+       case LTTNG_REGENERATE_STATEDUMP:
+               return "LTTNG_REGENERATE_STATEDUMP";
+       case LTTNG_REGISTER_TRIGGER:
+               return "LTTNG_REGISTER_TRIGGER";
+       case LTTNG_UNREGISTER_TRIGGER:
+               return "LTTNG_UNREGISTER_TRIGGER";
+       case LTTNG_ROTATE_SESSION:
+               return "LTTNG_ROTATE_SESSION";
+       case LTTNG_ROTATION_GET_INFO:
+               return "LTTNG_ROTATION_GET_INFO";
+       case LTTNG_ROTATION_SET_SCHEDULE:
+               return "LTTNG_ROTATION_SET_SCHEDULE";
+       case LTTNG_SESSION_LIST_ROTATION_SCHEDULES:
+               return "LTTNG_SESSION_LIST_ROTATION_SCHEDULES";
+       case LTTNG_CREATE_SESSION_EXT:
+               return "LTTNG_CREATE_SESSION_EXT";
+       case LTTNG_CLEAR_SESSION:
+               return "LTTNG_CLEAR_SESSION";
+       case LTTNG_LIST_TRIGGERS:
+               return "LTTNG_LIST_TRIGGERS";
+       case LTTNG_EXECUTE_ERROR_QUERY:
+               return "LTTNG_EXECUTE_ERROR_QUERY";
+       default:
+               abort();
+       }
+}
+
+enum lttcomm_relayd_command {
+       RELAYD_ADD_STREAM                   = 1,
+       RELAYD_CREATE_SESSION               = 2,
+       RELAYD_START_DATA                   = 3,
+       RELAYD_UPDATE_SYNC_INFO             = 4,
+       RELAYD_VERSION                      = 5,
+       RELAYD_SEND_METADATA                = 6,
+       RELAYD_CLOSE_STREAM                 = 7,
+       RELAYD_DATA_PENDING                 = 8,
+       RELAYD_QUIESCENT_CONTROL            = 9,
+       RELAYD_BEGIN_DATA_PENDING           = 10,
+       RELAYD_END_DATA_PENDING             = 11,
+       RELAYD_ADD_INDEX                    = 12,
+       RELAYD_SEND_INDEX                   = 13,
+       RELAYD_CLOSE_INDEX                  = 14,
+       /* Live-reading commands (2.4+). */
+       RELAYD_LIST_SESSIONS                = 15,
+       /* All streams of the channel have been sent to the relayd (2.4+). */
+       RELAYD_STREAMS_SENT                 = 16,
+       /* Ask the relay to reset the metadata trace file (2.8+) */
+       RELAYD_RESET_METADATA               = 17,
+       /* Ask the relay to rotate a set of stream files (2.11+) */
+       RELAYD_ROTATE_STREAMS                = 18,
+       /* Ask the relay to create a trace chunk (2.11+) */
+       RELAYD_CREATE_TRACE_CHUNK           = 19,
+       /* Ask the relay to close a trace chunk (2.11+) */
+       RELAYD_CLOSE_TRACE_CHUNK            = 20,
+       /* Ask the relay whether a trace chunk exists (2.11+) */
+       RELAYD_TRACE_CHUNK_EXISTS           = 21,
+       /* Get the current configuration of a relayd peer (2.12+) */
+       RELAYD_GET_CONFIGURATION            = 22,
+
+       /* Feature branch specific commands start at 10000. */
+};
+
+static inline
+const char *lttcomm_relayd_command_str(lttcomm_relayd_command cmd)
+{
+       switch (cmd) {
+       case RELAYD_ADD_STREAM:
+               return "RELAYD_ADD_STREAM";
+       case RELAYD_CREATE_SESSION:
+               return "RELAYD_CREATE_SESSION";
+       case RELAYD_START_DATA:
+               return "RELAYD_START_DATA";
+       case RELAYD_UPDATE_SYNC_INFO:
+               return "RELAYD_UPDATE_SYNC_INFO";
+       case RELAYD_VERSION:
+               return "RELAYD_VERSION";
+       case RELAYD_SEND_METADATA:
+               return "RELAYD_SEND_METADATA";
+       case RELAYD_CLOSE_STREAM:
+               return "RELAYD_CLOSE_STREAM";
+       case RELAYD_DATA_PENDING:
+               return "RELAYD_DATA_PENDING";
+       case RELAYD_QUIESCENT_CONTROL:
+               return "RELAYD_QUIESCENT_CONTROL";
+       case RELAYD_BEGIN_DATA_PENDING:
+               return "RELAYD_BEGIN_DATA_PENDING";
+       case RELAYD_END_DATA_PENDING:
+               return "RELAYD_END_DATA_PENDING";
+       case RELAYD_ADD_INDEX:
+               return "RELAYD_ADD_INDEX";
+       case RELAYD_SEND_INDEX:
+               return "RELAYD_SEND_INDEX";
+       case RELAYD_CLOSE_INDEX:
+               return "RELAYD_CLOSE_INDEX";
+       case RELAYD_LIST_SESSIONS:
+               return "RELAYD_LIST_SESSIONS";
+       case RELAYD_STREAMS_SENT:
+               return "RELAYD_STREAMS_SENT";
+       case RELAYD_RESET_METADATA:
+               return "RELAYD_RESET_METADATA";
+       case RELAYD_ROTATE_STREAMS:
+               return "RELAYD_ROTATE_STREAMS";
+       case RELAYD_CREATE_TRACE_CHUNK:
+               return "RELAYD_CREATE_TRACE_CHUNK";
+       case RELAYD_CLOSE_TRACE_CHUNK:
+               return "RELAYD_CLOSE_TRACE_CHUNK";
+       case RELAYD_TRACE_CHUNK_EXISTS:
+               return "RELAYD_TRACE_CHUNK_EXISTS";
+       case RELAYD_GET_CONFIGURATION:
+               return "RELAYD_GET_CONFIGURATION";
+       default:
+               abort();
+       }
+}
+
+/*
+ * lttcomm error code.
+ */
+enum lttcomm_return_code {
+       LTTCOMM_CONSUMERD_SUCCESS            = 0,   /* Everything went fine. */
+       /*
+        * Some code paths use -1 to express an error, others
+        * negate this consumer return code. Starting codes at
+        * 100 ensures there is no mix-up between this error value
+        * and legitimate status codes.
+        */
+       LTTCOMM_CONSUMERD_COMMAND_SOCK_READY = 100, /* Command socket ready */
+       LTTCOMM_CONSUMERD_SUCCESS_RECV_FD,          /* Success on receiving fds */
+       LTTCOMM_CONSUMERD_ERROR_RECV_FD,            /* Error on receiving fds */
+       LTTCOMM_CONSUMERD_ERROR_RECV_CMD,           /* Error on receiving command */
+       LTTCOMM_CONSUMERD_POLL_ERROR,               /* Error in polling thread */
+       LTTCOMM_CONSUMERD_POLL_NVAL,                /* Poll on closed fd */
+       LTTCOMM_CONSUMERD_POLL_HUP,                 /* All fds have hungup */
+       LTTCOMM_CONSUMERD_EXIT_SUCCESS,             /* Consumerd exiting normally */
+       LTTCOMM_CONSUMERD_EXIT_FAILURE,             /* Consumerd exiting on error */
+       LTTCOMM_CONSUMERD_OUTFD_ERROR,              /* Error opening the tracefile */
+       LTTCOMM_CONSUMERD_SPLICE_EBADF,             /* EBADF from splice(2) */
+       LTTCOMM_CONSUMERD_SPLICE_EINVAL,            /* EINVAL from splice(2) */
+       LTTCOMM_CONSUMERD_SPLICE_ENOMEM,            /* ENOMEM from splice(2) */
+       LTTCOMM_CONSUMERD_SPLICE_ESPIPE,            /* ESPIPE from splice(2) */
+       LTTCOMM_CONSUMERD_ENOMEM,                   /* Consumer is out of memory */
+       LTTCOMM_CONSUMERD_ERROR_METADATA,           /* Error with metadata. */
+       LTTCOMM_CONSUMERD_FATAL,                    /* Fatal error. */
+       LTTCOMM_CONSUMERD_RELAYD_FAIL,              /* Error on remote relayd */
+       LTTCOMM_CONSUMERD_CHANNEL_FAIL,             /* Channel creation failed. */
+       LTTCOMM_CONSUMERD_CHAN_NOT_FOUND,           /* Channel not found. */
+       LTTCOMM_CONSUMERD_ALREADY_SET,              /* Resource already set. */
+       LTTCOMM_CONSUMERD_ROTATION_FAIL,            /* Rotation has failed. */
+       LTTCOMM_CONSUMERD_SNAPSHOT_FAILED,          /* snapshot has failed. */
+       LTTCOMM_CONSUMERD_CREATE_TRACE_CHUNK_FAILED,/* Trace chunk creation failed. */
+       LTTCOMM_CONSUMERD_CLOSE_TRACE_CHUNK_FAILED, /* Trace chunk close failed. */
+       LTTCOMM_CONSUMERD_INVALID_PARAMETERS,       /* Invalid parameters. */
+       LTTCOMM_CONSUMERD_TRACE_CHUNK_EXISTS_LOCAL, /* Trace chunk exists on consumer daemon. */
+       LTTCOMM_CONSUMERD_TRACE_CHUNK_EXISTS_REMOTE,/* Trace chunk exists on relay daemon. */
+       LTTCOMM_CONSUMERD_UNKNOWN_TRACE_CHUNK,      /* Unknown trace chunk. */
+       LTTCOMM_CONSUMERD_RELAYD_CLEAR_DISALLOWED,  /* Relayd does not accept clear command. */
+       LTTCOMM_CONSUMERD_UNKNOWN_ERROR,            /* Unknown error. */
+
+       /* MUST be last element */
+       LTTCOMM_NR,                                             /* Last element */
+};
+
+/* lttng socket protocol. */
+enum lttcomm_sock_proto {
+       LTTCOMM_SOCK_UDP,
+       LTTCOMM_SOCK_TCP,
+};
+
+/*
+ * Index in the net_families array below. Please keep in sync!
+ */
+enum lttcomm_sock_domain {
+       LTTCOMM_INET      = 0,
+       LTTCOMM_INET6     = 1,
+};
+
+enum lttcomm_metadata_command {
+       LTTCOMM_METADATA_REQUEST = 1,
+};
+
+/*
+ * Commands sent from the consumerd to the sessiond to request if new metadata
+ * is available. This message is used to find the per UID _or_ per PID registry
+ * for the channel key. For per UID lookup, the triplet
+ * bits_per_long/uid/session_id is used. On lookup failure, we search for the
+ * per PID registry indexed by session id ignoring the other values.
+ */
+struct lttcomm_metadata_request_msg {
+       uint64_t session_id; /* Tracing session id */
+       uint64_t session_id_per_pid; /* Tracing session id for per-pid */
+       uint32_t bits_per_long; /* Consumer ABI */
+       uint32_t uid;
+       uint64_t key; /* Metadata channel key. */
+} LTTNG_PACKED;
+
+struct lttcomm_sockaddr {
+       enum lttcomm_sock_domain type;
+       union {
+               struct sockaddr_in sin;
+               struct sockaddr_in6 sin6;
+       } addr;
+} LTTNG_PACKED;
+
+struct lttcomm_sock {
+       int32_t fd;
+       enum lttcomm_sock_proto proto;
+       struct lttcomm_sockaddr sockaddr;
+       const struct lttcomm_proto_ops *ops;
+} LTTNG_PACKED;
+
+/*
+ * Relayd sock. Adds the protocol version to use for the communications with
+ * the relayd.
+ */
+struct lttcomm_relayd_sock {
+       struct lttcomm_sock sock;
+       uint32_t major;
+       uint32_t minor;
+} LTTNG_PACKED;
+
+struct lttcomm_net_family {
+       int family;
+       int (*create) (struct lttcomm_sock *sock, int type, int proto);
+};
+
+struct lttcomm_proto_ops {
+       int (*bind) (struct lttcomm_sock *sock);
+       int (*close) (struct lttcomm_sock *sock);
+       int (*connect) (struct lttcomm_sock *sock);
+       struct lttcomm_sock *(*accept) (struct lttcomm_sock *sock);
+       int (*listen) (struct lttcomm_sock *sock, int backlog);
+       ssize_t (*recvmsg) (struct lttcomm_sock *sock, void *buf, size_t len,
+                       int flags);
+       ssize_t (*sendmsg) (struct lttcomm_sock *sock, const void *buf,
+                       size_t len, int flags);
+};
+
+struct process_attr_integral_value_comm {
+       union {
+               int64_t _signed;
+               uint64_t _unsigned;
+       } u;
+} LTTNG_PACKED;
+
+/*
+ * Data structure received from lttng client to session daemon.
+ */
+struct lttcomm_session_msg {
+       uint32_t cmd_type;      /* enum lttcomm_sessiond_command */
+       struct lttng_session session;
+       struct lttng_domain domain;
+       union {
+               /* Event data */
+               struct {
+                       char channel_name[LTTNG_SYMBOL_NAME_LEN];
+                       struct lttng_event event;
+                       /* Length of following filter expression. */
+                       uint32_t expression_len;
+                       /* Length of following bytecode for filter. */
+                       uint32_t bytecode_len;
+                       /* Exclusion count (fixed-size strings). */
+                       uint32_t exclusion_count;
+                       /* Userspace probe location size. */
+                       uint32_t userspace_probe_location_len;
+                       /*
+                        * After this structure, the following variable-length
+                        * items are transmitted:
+                        * - char exclusion_names[LTTNG_SYMBOL_NAME_LEN][exclusion_count]
+                        * - char filter_expression[expression_len]
+                        * - unsigned char filter_bytecode[bytecode_len]
+                        */
+               } LTTNG_PACKED enable;
+               struct {
+                       char channel_name[LTTNG_SYMBOL_NAME_LEN];
+                       struct lttng_event event;
+                       /* Length of following filter expression. */
+                       uint32_t expression_len;
+                       /* Length of following bytecode for filter. */
+                       uint32_t bytecode_len;
+                       /*
+                        * After this structure, the following variable-length
+                        * items are transmitted:
+                        * - unsigned char filter_expression[expression_len]
+                        * - unsigned char filter_bytecode[bytecode_len]
+                        */
+               } LTTNG_PACKED disable;
+               /* Create channel */
+               struct {
+                       struct lttng_channel chan;
+                       struct lttng_channel_extended extended;
+               } LTTNG_PACKED channel;
+               /* Context */
+               struct {
+                       char channel_name[LTTNG_SYMBOL_NAME_LEN];
+                       struct lttng_event_context ctx;
+                       uint32_t provider_name_len;
+                       uint32_t context_name_len;
+               } LTTNG_PACKED context;
+               /* Use by register_consumer */
+               struct {
+                       char path[PATH_MAX];
+               } LTTNG_PACKED reg;
+               /* List */
+               struct {
+                       char channel_name[LTTNG_SYMBOL_NAME_LEN];
+               } LTTNG_PACKED list;
+               struct lttng_calibrate calibrate;
+               /* Used by the set_consumer_url and used by create_session also call */
+               struct {
+                       /* Number of lttng_uri following */
+                       uint32_t size;
+               } LTTNG_PACKED uri;
+               struct {
+                       struct lttng_snapshot_output output;
+               } LTTNG_PACKED snapshot_output;
+               struct {
+                       uint32_t wait;
+                       struct lttng_snapshot_output output;
+               } LTTNG_PACKED snapshot_record;
+               struct {
+                       uint32_t nb_uri;
+                       unsigned int timer_interval;    /* usec */
+               } LTTNG_PACKED session_live;
+               struct {
+                       struct lttng_save_session_attr attr;
+               } LTTNG_PACKED save_session;
+               struct {
+                       char shm_path[PATH_MAX];
+               } LTTNG_PACKED set_shm_path;
+               struct {
+                       /* enum lttng_process_attr */
+                       int32_t process_attr;
+                       /* enum lttng_process_attr_value_type */
+                       int32_t value_type;
+
+                       struct process_attr_integral_value_comm integral_value;
+                       /*
+                        * For user/group names, a variable length,
+                        * zero-terminated, string of length 'name_len'
+                        * (including the terminator) follows.
+                        *
+                        * integral_value should not be used in those cases.
+                        */
+                       uint32_t name_len;
+               } LTTNG_PACKED process_attr_tracker_add_remove_include_value;
+               struct {
+                       /* enum lttng_process_attr */
+                       int32_t process_attr;
+               } LTTNG_PACKED process_attr_tracker_get_inclusion_set;
+               struct {
+                       /* enum lttng_process_attr */
+                       int32_t process_attr;
+               } LTTNG_PACKED process_attr_tracker_get_tracking_policy;
+               struct {
+                       /* enum lttng_process_attr */
+                       int32_t process_attr;
+                       /* enum lttng_tracking_policy */
+                       int32_t tracking_policy;
+               } LTTNG_PACKED process_attr_tracker_set_tracking_policy;
+               struct {
+                       uint32_t length;
+                       uint8_t is_trigger_anonymous;
+               } LTTNG_PACKED trigger;
+               struct {
+                       uint32_t length;
+               } LTTNG_PACKED error_query;
+               struct {
+                       uint64_t rotation_id;
+               } LTTNG_PACKED get_rotation_info;
+               struct {
+                       /* enum lttng_rotation_schedule_type */
+                       uint8_t type;
+                       /*
+                        * If set == 1, set schedule to value, if set == 0,
+                        * clear this schedule type.
+                        */
+                       uint8_t set;
+                       uint64_t value;
+               } LTTNG_PACKED rotation_set_schedule;
+               struct {
+                       /*
+                        * Includes the null-terminator.
+                        * Must be an absolute path.
+                        *
+                        * Size bounded by LTTNG_PATH_MAX.
+                        */
+                       uint16_t home_dir_size;
+                       uint64_t session_descriptor_size;
+                       /* An lttng_session_descriptor follows. */
+               } LTTNG_PACKED create_session;
+       } u;
+       /* Count of fds sent. */
+       uint32_t fd_count;
+} LTTNG_PACKED;
+
+#define LTTNG_FILTER_MAX_LEN   65536
+#define LTTNG_SESSION_DESCRIPTOR_MAX_LEN       65536
+
+/*
+ * Filter bytecode data. The reloc table is located at the end of the
+ * bytecode. It is made of tuples: (uint16_t, var. len. string). It
+ * starts at reloc_table_offset.
+ */
+#define LTTNG_FILTER_PADDING   32
+struct lttng_bytecode {
+       uint32_t len;   /* len of data */
+       uint32_t reloc_table_offset;
+       uint64_t seqnum;
+       char padding[LTTNG_FILTER_PADDING];
+       char data[0];
+} LTTNG_PACKED;
+
+/*
+ * Event exclusion data. At the end of the structure, there will actually
+ * by zero or more names, where the actual number of names is given by
+ * the 'count' item of the structure.
+ */
+#define LTTNG_EVENT_EXCLUSION_PADDING  32
+struct lttng_event_exclusion {
+       uint32_t count;
+       char padding[LTTNG_EVENT_EXCLUSION_PADDING];
+       char names[0][LTTNG_SYMBOL_NAME_LEN];
+} LTTNG_PACKED;
+
+#define LTTNG_EVENT_EXCLUSION_NAME_AT(_exclusion, _i) \
+       (&(_exclusion)->names[_i][0])
+
+/*
+ * Event command header.
+ */
+struct lttcomm_event_command_header {
+       /* Number of events */
+       uint32_t nb_events;
+} LTTNG_PACKED;
+
+/*
+ * Event extended info header. This is the structure preceding each
+ * extended info data.
+ */
+struct lttcomm_event_extended_header {
+       /*
+        * Size of filter string immediately following this header.
+        * This size includes the terminal null character.
+        */
+       uint32_t filter_len;
+
+       /*
+        * Number of exclusion names, immediately following the filter
+        * string. Each exclusion name has a fixed length of
+        * LTTNG_SYMBOL_NAME_LEN bytes, including the terminal null
+        * character.
+        */
+       uint32_t nb_exclusions;
+
+       /*
+        * Size of the event's userspace probe location (if applicable).
+        */
+       uint32_t userspace_probe_location_len;
+} LTTNG_PACKED;
+
+/*
+ * Command header of the reply to an LTTNG_DESTROY_SESSION command.
+ */
+struct lttcomm_session_destroy_command_header {
+       /* enum lttng_session */
+       int32_t rotation_state;
+};
+
+/*
+ * tracker command header.
+ */
+struct lttcomm_tracker_command_header {
+       uint32_t nb_tracker_id;
+} LTTNG_PACKED;
+
+/*
+ * Data structure for the response from sessiond to the lttng client.
+ */
+struct lttcomm_lttng_msg {
+       uint32_t cmd_type;      /* enum lttcomm_sessiond_command */
+       uint32_t ret_code;      /* enum lttcomm_return_code */
+       uint32_t pid;           /* pid_t */
+       uint32_t cmd_header_size;
+       uint32_t data_size;
+       uint32_t fd_count;
+} LTTNG_PACKED;
+
+struct lttcomm_lttng_output_id {
+       uint32_t id;
+} LTTNG_PACKED;
+
+/*
+ * lttcomm_consumer_msg is the message sent from sessiond to consumerd
+ * to either add a channel, add a stream, update a stream, or stop
+ * operation.
+ */
+struct lttcomm_consumer_msg {
+       uint32_t cmd_type;      /* enum lttng_consumer_command */
+       union {
+               struct {
+                       uint64_t channel_key;
+                       uint64_t session_id;
+                       /* ID of the session's current trace chunk. */
+                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED chunk_id;
+                       char pathname[PATH_MAX];
+                       uint64_t relayd_id;
+                       /* nb_init_streams is the number of streams open initially. */
+                       uint32_t nb_init_streams;
+                       char name[LTTNG_SYMBOL_NAME_LEN];
+                       /* Use splice or mmap to consume this fd */
+                       enum lttng_event_output output;
+                       int type; /* Per cpu or metadata. */
+                       uint64_t tracefile_size; /* bytes */
+                       uint32_t tracefile_count; /* number of tracefiles */
+                       /* If the channel's streams have to be monitored or not. */
+                       uint32_t monitor;
+                       /* timer to check the streams usage in live mode (usec). */
+                       unsigned int live_timer_interval;
+                       /* is part of a live session */
+                       uint8_t is_live;
+                       /* timer to sample a channel's positions (usec). */
+                       unsigned int monitor_timer_interval;
+               } LTTNG_PACKED channel; /* Only used by Kernel. */
+               struct {
+                       uint64_t stream_key;
+                       uint64_t channel_key;
+                       int32_t cpu;    /* On which CPU this stream is assigned. */
+                       /* Tells the consumer if the stream should be or not monitored. */
+                       uint32_t no_monitor;
+               } LTTNG_PACKED stream;  /* Only used by Kernel. */
+               struct {
+                       uint64_t net_index;
+                       enum lttng_stream_type type;
+                       /* Open socket to the relayd */
+                       struct lttcomm_relayd_sock sock;
+                       /* Tracing session id associated to the relayd. */
+                       uint64_t session_id;
+                       /* Relayd session id, only used with control socket. */
+                       uint64_t relayd_session_id;
+               } LTTNG_PACKED relayd_sock;
+               struct {
+                       uint64_t net_seq_idx;
+               } LTTNG_PACKED destroy_relayd;
+               struct {
+                       uint64_t session_id;
+               } LTTNG_PACKED data_pending;
+               struct {
+                       uint64_t subbuf_size;                   /* bytes */
+                       uint64_t num_subbuf;                    /* power of 2 */
+                       int32_t overwrite;                      /* 1: overwrite, 0: discard */
+                       uint32_t switch_timer_interval;         /* usec */
+                       uint32_t read_timer_interval;           /* usec */
+                       unsigned int live_timer_interval;       /* usec */
+                       uint8_t is_live;                        /* is part of a live session */
+                       uint32_t monitor_timer_interval;        /* usec */
+                       int32_t output;                         /* splice, mmap */
+                       int32_t type;                           /* metadata or per_cpu */
+                       uint64_t session_id;                    /* Tracing session id */
+                       char pathname[PATH_MAX];                /* Channel file path. */
+                       char name[LTTNG_SYMBOL_NAME_LEN];       /* Channel name. */
+                       /* Credentials used to open the UST buffer shared mappings. */
+                       struct {
+                               uint32_t uid;
+                               uint32_t gid;
+                       } LTTNG_PACKED buffer_credentials;
+                       uint64_t relayd_id;                     /* Relayd id if apply. */
+                       uint64_t key;                           /* Unique channel key. */
+                       /* ID of the session's current trace chunk. */
+                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED chunk_id;
+                       unsigned char uuid[LTTNG_UUID_LEN];     /* uuid for ust tracer. */
+                       uint32_t chan_id;                       /* Channel ID on the tracer side. */
+                       uint64_t tracefile_size;        /* bytes */
+                       uint32_t tracefile_count;       /* number of tracefiles */
+                       uint64_t session_id_per_pid;    /* Per-pid session ID. */
+                       /* Tells the consumer if the stream should be or not monitored. */
+                       uint32_t monitor;
+                       /*
+                        * For UST per UID buffers, this is the application UID of the
+                        * channel.  This can be different from the user UID requesting the
+                        * channel creation and used for the rights on the stream file
+                        * because the application can be in the tracing for instance.
+                        */
+                       uint32_t ust_app_uid;
+                       int64_t blocking_timeout;
+                       char root_shm_path[PATH_MAX];
+                       char shm_path[PATH_MAX];
+               } LTTNG_PACKED ask_channel;
+               struct {
+                       uint64_t key;
+               } LTTNG_PACKED get_channel;
+               struct {
+                       uint64_t key;
+               } LTTNG_PACKED destroy_channel;
+               struct {
+                       uint64_t key;   /* Metadata channel key. */
+                       uint64_t target_offset; /* Offset in the consumer */
+                       uint64_t len;   /* Length of metadata to be received. */
+                       uint64_t version; /* Version of the metadata. */
+               } LTTNG_PACKED push_metadata;
+               struct {
+                       uint64_t key;   /* Metadata channel key. */
+               } LTTNG_PACKED close_metadata;
+               struct {
+                       uint64_t key;   /* Metadata channel key. */
+               } LTTNG_PACKED setup_metadata;
+               struct {
+                       uint64_t key;   /* Channel key. */
+               } LTTNG_PACKED flush_channel;
+               struct {
+                       uint64_t key;   /* Channel key. */
+               } LTTNG_PACKED clear_quiescent_channel;
+               struct {
+                       char pathname[PATH_MAX];
+                       /* Indicate if the snapshot goes on the relayd or locally. */
+                       uint32_t use_relayd;
+                       uint32_t metadata;              /* This a metadata snapshot. */
+                       uint64_t relayd_id;             /* Relayd id if apply. */
+                       uint64_t key;
+                       uint64_t nb_packets_per_stream;
+               } LTTNG_PACKED snapshot_channel;
+               struct {
+                       uint64_t channel_key;
+                       uint64_t net_seq_idx;
+               } LTTNG_PACKED sent_streams;
+               struct {
+                       uint64_t session_id;
+                       uint64_t channel_key;
+               } LTTNG_PACKED discarded_events;
+               struct {
+                       uint64_t session_id;
+                       uint64_t channel_key;
+               } LTTNG_PACKED lost_packets;
+               struct {
+                       uint64_t session_id;
+               } LTTNG_PACKED regenerate_metadata;
+               struct {
+                       uint32_t metadata; /* This is a metadata channel. */
+                       uint64_t relayd_id; /* Relayd id if apply. */
+                       uint64_t key;
+               } LTTNG_PACKED rotate_channel;
+               struct {
+                       uint64_t session_id;
+                       uint64_t chunk_id;
+               } LTTNG_PACKED check_rotation_pending_local;
+               struct {
+                       uint64_t relayd_id;
+                       uint64_t session_id;
+                       uint64_t chunk_id;
+               } LTTNG_PACKED check_rotation_pending_relay;
+               struct {
+                       /*
+                        * Relayd id, if applicable (remote).
+                        *
+                        * A directory file descriptor referring to the chunk's
+                        * output folder is transmitted if the chunk is local
+                        * (relayd_id unset).
+                        *
+                        * `override_name` is left NULL (all-zeroes) if the
+                        * chunk's name is not overridden.
+                        */
+                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED relayd_id;
+                       char override_name[LTTNG_NAME_MAX];
+                       uint64_t session_id;
+                       uint64_t chunk_id;
+                       uint64_t creation_timestamp;
+                       LTTNG_OPTIONAL_COMM(struct {
+                               uint32_t uid;
+                               uint32_t gid;
+                       } LTTNG_PACKED ) LTTNG_PACKED credentials;
+               } LTTNG_PACKED create_trace_chunk;
+               struct {
+                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED relayd_id;
+                       uint64_t session_id;
+                       uint64_t chunk_id;
+                       uint64_t close_timestamp;
+                       /* enum lttng_trace_chunk_command_type */
+                       LTTNG_OPTIONAL_COMM(uint32_t) LTTNG_PACKED close_command;
+               } LTTNG_PACKED close_trace_chunk;
+               struct {
+                       LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED relayd_id;
+                       uint64_t session_id;
+                       uint64_t chunk_id;
+               } LTTNG_PACKED trace_chunk_exists;
+               struct {
+                       lttng_uuid sessiond_uuid;
+               } LTTNG_PACKED init;
+               struct {
+                       uint64_t key;
+               } LTTNG_PACKED clear_channel;
+               struct {
+                       uint64_t key;
+               } LTTNG_PACKED open_channel_packets;
+       } u;
+} LTTNG_PACKED;
+
+/*
+ * Channel monitoring message returned to the session daemon on every
+ * monitor timer expiration.
+ */
+struct lttcomm_consumer_channel_monitor_msg {
+       /* Key of the sampled channel. */
+       uint64_t key;
+       /*
+        * Lowest and highest usage (bytes) at the moment the sample was taken.
+        */
+       uint64_t lowest, highest;
+       /*
+        * Sum of all the consumed positions for a channel.
+        */
+       uint64_t total_consumed;
+} LTTNG_PACKED;
+
+/*
+ * Status message returned to the sessiond after a received command.
+ */
+struct lttcomm_consumer_status_msg {
+       enum lttcomm_return_code ret_code;
+} LTTNG_PACKED;
+
+struct lttcomm_consumer_status_channel {
+       enum lttcomm_return_code ret_code;
+       uint64_t key;
+       unsigned int stream_count;
+} LTTNG_PACKED;
+
+struct lttcomm_consumer_close_trace_chunk_reply {
+       enum lttcomm_return_code ret_code;
+       uint32_t path_length;
+       char path[];
+};
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+#include <lttng/ust-abi.h>
+
+/*
+ * Data structure for the commands sent from sessiond to UST.
+ */
+struct lttcomm_ust_msg {
+       uint32_t handle;
+       uint32_t cmd;
+       union {
+               struct lttng_ust_abi_channel channel;
+               struct lttng_ust_abi_stream stream;
+               struct lttng_ust_abi_event event;
+               struct lttng_ust_abi_context context;
+               struct lttng_ust_abi_tracer_version version;
+       } u;
+} LTTNG_PACKED;
+
+/*
+ * Data structure for the response from UST to the session daemon.
+ * cmd_type is sent back in the reply for validation.
+ */
+struct lttcomm_ust_reply {
+       uint32_t handle;
+       uint32_t cmd;
+       uint32_t ret_code;      /* enum lttcomm_return_code */
+       uint32_t ret_val;       /* return value */
+       union {
+               struct {
+                       uint64_t memory_map_size;
+               } LTTNG_PACKED channel;
+               struct {
+                       uint64_t memory_map_size;
+               } LTTNG_PACKED stream;
+               struct lttng_ust_abi_tracer_version version;
+       } u;
+} LTTNG_PACKED;
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+const char *lttcomm_get_readable_code(enum lttcomm_return_code code);
+
+int lttcomm_init_inet_sockaddr(struct lttcomm_sockaddr *sockaddr,
+               const char *ip, unsigned int port);
+int lttcomm_init_inet6_sockaddr(struct lttcomm_sockaddr *sockaddr,
+               const char *ip, unsigned int port);
+
+struct lttcomm_sock *lttcomm_alloc_sock(enum lttcomm_sock_proto proto);
+int lttcomm_create_sock(struct lttcomm_sock *sock);
+struct lttcomm_sock *lttcomm_alloc_sock_from_uri(struct lttng_uri *uri);
+void lttcomm_destroy_sock(struct lttcomm_sock *sock);
+struct lttcomm_sock *lttcomm_alloc_copy_sock(struct lttcomm_sock *src);
+void lttcomm_copy_sock(struct lttcomm_sock *dst,
+               struct lttcomm_sock *src);
+
+/* Relayd socket object. */
+struct lttcomm_relayd_sock *lttcomm_alloc_relayd_sock(
+               struct lttng_uri *uri, uint32_t major, uint32_t minor);
+
+int lttcomm_setsockopt_rcv_timeout(int sock, unsigned int msec);
+int lttcomm_setsockopt_snd_timeout(int sock, unsigned int msec);
+
+int lttcomm_sock_get_port(const struct lttcomm_sock *sock,
+               uint16_t *port);
+/*
+ * Set a port to an lttcomm_sock. This will have no effect is the socket is
+ * already bound.
+ */
+int lttcomm_sock_set_port(struct lttcomm_sock *sock, uint16_t port);
+
+void lttcomm_init(void);
+/* Get network timeout, in milliseconds */
+unsigned long lttcomm_get_network_timeout(void);
+
+#endif /* _LTTNG_SESSIOND_COMM_H */
index 99535c468a836698cdc0b250090dc0d201ecc496..10fd02d2afeae87a54538ef9c7abebacb844593c 100644 (file)
@@ -16,9 +16,9 @@
 #include <unistd.h>
 #include <urcu.h>
 
-#include <common/error.h>
+#include <common/error.hpp>
 
-#include "shm.h"
+#include "shm.hpp"
 
 /*
  * Using fork to set umask in the child process (not multi-thread safe). We
diff --git a/src/common/shm.h b/src/common/shm.h
deleted file mode 100644 (file)
index d714506..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTT_SHM_H
-#define _LTT_SHM_H
-
-char *shm_ust_get_mmap(char *shm_path, int global);
-
-int shm_create_anonymous(const char *owner_name);
-
-#endif /* _LTT_SHM_H */
diff --git a/src/common/shm.hpp b/src/common/shm.hpp
new file mode 100644 (file)
index 0000000..d714506
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTT_SHM_H
+#define _LTT_SHM_H
+
+char *shm_ust_get_mmap(char *shm_path, int global);
+
+int shm_create_anonymous(const char *owner_name);
+
+#endif /* _LTT_SHM_H */
index 960240b2c4a1144830109a97fe5389473c19fe43..2955f5792bc75f5b2deb22a172d56f98d81a8211 100644 (file)
@@ -5,12 +5,12 @@
  *
  */
 
-#include <common/error.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/snapshot.h>
-#include <lttng/snapshot-internal.h>
+#include <common/error.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/snapshot.hpp>
+#include <lttng/snapshot-internal.hpp>
 #include <lttng/snapshot.h>
 
 #include <stdlib.h>
diff --git a/src/common/snapshot.h b/src/common/snapshot.h
deleted file mode 100644 (file)
index 7395c04..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 Simon Marchi <simon.marchi@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef COMMON_SNAPSHOT_H
-#define COMMON_SNAPSHOT_H
-
-#include <common/macros.h>
-
-#include <stdbool.h>
-#include <sys/types.h>
-
-struct lttng_payload_view;
-struct lttng_payload;
-struct lttng_snapshot_output;
-struct mi_writer;
-
-bool lttng_snapshot_output_validate(const struct lttng_snapshot_output *output);
-
-bool lttng_snapshot_output_is_equal(
-               const struct lttng_snapshot_output *a,
-               const struct lttng_snapshot_output *b);
-
-int lttng_snapshot_output_serialize(
-               const struct lttng_snapshot_output *output,
-               struct lttng_payload *payload);
-
-ssize_t lttng_snapshot_output_create_from_payload(
-               struct lttng_payload_view *view,
-               struct lttng_snapshot_output **output_p);
-
-enum lttng_error_code lttng_snapshot_output_mi_serialize(
-               const struct lttng_snapshot_output *output,
-               struct mi_writer *writer);
-
-#endif /* COMMON_SNAPSHOT_H */
diff --git a/src/common/snapshot.hpp b/src/common/snapshot.hpp
new file mode 100644 (file)
index 0000000..4d78219
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef COMMON_SNAPSHOT_H
+#define COMMON_SNAPSHOT_H
+
+#include <common/macros.hpp>
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+struct lttng_payload_view;
+struct lttng_payload;
+struct lttng_snapshot_output;
+struct mi_writer;
+
+bool lttng_snapshot_output_validate(const struct lttng_snapshot_output *output);
+
+bool lttng_snapshot_output_is_equal(
+               const struct lttng_snapshot_output *a,
+               const struct lttng_snapshot_output *b);
+
+int lttng_snapshot_output_serialize(
+               const struct lttng_snapshot_output *output,
+               struct lttng_payload *payload);
+
+ssize_t lttng_snapshot_output_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_snapshot_output **output_p);
+
+enum lttng_error_code lttng_snapshot_output_mi_serialize(
+               const struct lttng_snapshot_output *output,
+               struct mi_writer *writer);
+
+#endif /* COMMON_SNAPSHOT_H */
index bcbc229a2f2760e83b2fe27fbe34193a50d16910..f886e620576228ce979b792c635f05691e439c5a 100644 (file)
 
 #include <lttng/constant.h>
 
-#include <common/compat/errno.h>
-#include "error.h"
-#include "macros.h"
-#include "spawn-viewer.h"
+#include <common/compat/errno.hpp>
+#include "error.hpp"
+#include "macros.hpp"
+#include "spawn-viewer.hpp"
 
 
 static const char *babeltrace_bin = CONFIG_BABELTRACE_BIN;
diff --git a/src/common/spawn-viewer.h b/src/common/spawn-viewer.h
deleted file mode 100644 (file)
index 1221c5b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef LTTNG_SPAWN_VIEWER_H
-#define LTTNG_SPAWN_VIEWER_H
-
-/*
- * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include <lttng/lttng-export.h>
-#include <stdbool.h>
-
-/*
- * Read the trace by `exec()ing` the provided viewer program if any. If
- * `opt_viewer` is NULL, try to read the trace with the default trace reader.
- * On success, this function doesn't return.
- * Returns -1 if the `opt_viewer` string or the default trace viewer can't be
- * `exec()`.
- *
- * This symbol was mistakenly made public before the 2.12 release. It can't
- * be removed (but it can be stubbed-out if necessary).
- */
-extern "C" LTTNG_EXPORT
-int spawn_viewer(const char *trace_path, char *opt_viewer, bool opt_live_mode);
-
-#endif /* ifndef LTTNG_SPAWN_VIEWER_H */
diff --git a/src/common/spawn-viewer.hpp b/src/common/spawn-viewer.hpp
new file mode 100644 (file)
index 0000000..1221c5b
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef LTTNG_SPAWN_VIEWER_H
+#define LTTNG_SPAWN_VIEWER_H
+
+/*
+ * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include <lttng/lttng-export.h>
+#include <stdbool.h>
+
+/*
+ * Read the trace by `exec()ing` the provided viewer program if any. If
+ * `opt_viewer` is NULL, try to read the trace with the default trace reader.
+ * On success, this function doesn't return.
+ * Returns -1 if the `opt_viewer` string or the default trace viewer can't be
+ * `exec()`.
+ *
+ * This symbol was mistakenly made public before the 2.12 release. It can't
+ * be removed (but it can be stubbed-out if necessary).
+ */
+extern "C" LTTNG_EXPORT
+int spawn_viewer(const char *trace_path, char *opt_viewer, bool opt_live_mode);
+
+#endif /* ifndef LTTNG_SPAWN_VIEWER_H */
diff --git a/src/common/string-utils/Makefile.am b/src/common/string-utils/Makefile.am
deleted file mode 100644 (file)
index 212b3d5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libstring-utils.la
-
-libstring_utils_la_SOURCES = \
-       format.h \
-       string-utils.cpp \
-       string-utils.h
diff --git a/src/common/string-utils/format.h b/src/common/string-utils/format.h
deleted file mode 100644 (file)
index 2446523..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef _STRING_UTILS_FORMAT_H
-#define _STRING_UTILS_FORMAT_H
-
-/*
- * Maximal length of `val` when formatted in decimal.
- *
- * Note that this is an upper bound that can exceed the length
- * required to hold the largest textual value of `val`. Note that this length
- * assumes that no grouping/locale-aware formatting is performed (i.e. using
- * the `'` specifier in POSIX formatting functions).
- */
-#define MAX_INT_DEC_LEN(val)       ((3 * sizeof(val)) + 2)
-
-#endif /* _STRING_UTILS_FORMAT_H */
diff --git a/src/common/string-utils/format.hpp b/src/common/string-utils/format.hpp
new file mode 100644 (file)
index 0000000..2446523
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef _STRING_UTILS_FORMAT_H
+#define _STRING_UTILS_FORMAT_H
+
+/*
+ * Maximal length of `val` when formatted in decimal.
+ *
+ * Note that this is an upper bound that can exceed the length
+ * required to hold the largest textual value of `val`. Note that this length
+ * assumes that no grouping/locale-aware formatting is performed (i.e. using
+ * the `'` specifier in POSIX formatting functions).
+ */
+#define MAX_INT_DEC_LEN(val)       ((3 * sizeof(val)) + 2)
+
+#endif /* _STRING_UTILS_FORMAT_H */
index d23cf794cb34b0edb7da097f4393b4bced4fb8bb..8faeabb44c899c4a62aebe4d2b6e0998dafcd894 100644 (file)
@@ -15,8 +15,8 @@
 #include <errno.h>
 #include <stdarg.h>
 
-#include "string-utils.h"
-#include "../macros.h"
+#include "string-utils.hpp"
+#include "../macros.hpp"
 
 enum star_glob_pattern_type_flags {
        STAR_GLOB_PATTERN_TYPE_FLAG_NONE = 0,
diff --git a/src/common/string-utils/string-utils.h b/src/common/string-utils/string-utils.h
deleted file mode 100644 (file)
index 57cf4ec..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _STRING_UTILS_H
-#define _STRING_UTILS_H
-
-#include <stdbool.h>
-#include <common/macros.h>
-#include <common/dynamic-array.h>
-
-void strutils_normalize_star_glob_pattern(char *pattern);
-
-bool strutils_is_star_glob_pattern(const char *pattern);
-
-bool strutils_is_star_at_the_end_only_glob_pattern(const char *pattern);
-
-char *strutils_unescape_string(const char *input, char only_char);
-
-int strutils_split(const char *input, char delim, bool escape_delim,
-               struct lttng_dynamic_pointer_array *out_strings);
-
-void strutils_free_null_terminated_array_of_strings(char **array);
-
-size_t strutils_array_of_strings_len(char * const *array);
-
-/*
- * Append `append` to the malloc-end string `str`.
- *
- * On success, `str` is free'd (if not NULL) and assigned a new malloc-ed
- * string.  On failure, `str` is not modified.
- *
- * Return 0 on success, -ENOMEM on failure.
- */
-C_LINKAGE int strutils_append_str(char **str, const char *append);
-
-/*
- * Like `strutils_append_str`, but the appended string is formatted using
- * `fmt` and the following arguments.
- */
-C_LINKAGE ATTR_FORMAT_PRINTF(2, 3)
-int strutils_appendf(char **s, const char *fmt, ...);
-
-#endif /* _STRING_UTILS_H */
diff --git a/src/common/string-utils/string-utils.hpp b/src/common/string-utils/string-utils.hpp
new file mode 100644 (file)
index 0000000..26cc5de
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _STRING_UTILS_H
+#define _STRING_UTILS_H
+
+#include <stdbool.h>
+#include <common/macros.hpp>
+#include <common/dynamic-array.hpp>
+
+void strutils_normalize_star_glob_pattern(char *pattern);
+
+bool strutils_is_star_glob_pattern(const char *pattern);
+
+bool strutils_is_star_at_the_end_only_glob_pattern(const char *pattern);
+
+char *strutils_unescape_string(const char *input, char only_char);
+
+int strutils_split(const char *input, char delim, bool escape_delim,
+               struct lttng_dynamic_pointer_array *out_strings);
+
+void strutils_free_null_terminated_array_of_strings(char **array);
+
+size_t strutils_array_of_strings_len(char * const *array);
+
+/*
+ * Append `append` to the malloc-end string `str`.
+ *
+ * On success, `str` is free'd (if not NULL) and assigned a new malloc-ed
+ * string.  On failure, `str` is not modified.
+ *
+ * Return 0 on success, -ENOMEM on failure.
+ */
+C_LINKAGE int strutils_append_str(char **str, const char *append);
+
+/*
+ * Like `strutils_append_str`, but the appended string is formatted using
+ * `fmt` and the following arguments.
+ */
+C_LINKAGE ATTR_FORMAT_PRINTF(2, 3)
+int strutils_appendf(char **s, const char *fmt, ...);
+
+#endif /* _STRING_UTILS_H */
diff --git a/src/common/testpoint/Makefile.am b/src/common/testpoint/Makefile.am
deleted file mode 100644 (file)
index 7fd8ed7..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-noinst_LTLIBRARIES = libtestpoint.la
-
-libtestpoint_la_SOURCES = \
-       testpoint.cpp \
-       testpoint.h
-libtestpoint_la_LIBADD = $(DL_LIBS)
index c70245894e347dc27f9a9b20128d655db4f663f4..4dfeadd81eb9aad643d31b5200f0d59e38e5e921 100644 (file)
@@ -12,7 +12,7 @@
 #include <stdlib.h> /* for getenv  */
 #include <string.h> /* for strncmp */
 
-#include "testpoint.h"
+#include "testpoint.hpp"
 
 /* Environment variable used to enable the testpoints facilities. */
 static const char *lttng_testpoint_env_var = "LTTNG_TESTPOINT_ENABLE";
diff --git a/src/common/testpoint/testpoint.h b/src/common/testpoint/testpoint.h
deleted file mode 100644 (file)
index 33cb9aa..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2012 Christian Babeux <christian.babeux@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifdef NTESTPOINT
-
-#define testpoint(name)
-#define TESTPOINT_DECL(name)
-
-#else /* NTESTPOINT */
-
-#include <urcu.h> /* for caa_likely/unlikely */
-
-extern int lttng_testpoint_activated;
-
-void *lttng_testpoint_lookup(const char *name);
-
-/*
- * Testpoint is only active if the global lttng_testpoint_activated flag is
- * set.
- * Return a non-zero error code to indicate failure.
- */
-#define testpoint(name)                                \
-       ((caa_unlikely(lttng_testpoint_activated))      \
-       ? __testpoint_##name##_wrapper() : 0)
-
-/*
- * One wrapper per testpoint is generated. This is to keep track of the symbol
- * lookup status and the corresponding function pointer, if any.
- */
-#define _TESTPOINT_DECL(_name)                                         \
-       static inline int __testpoint_##_name##_wrapper(void)           \
-       {                                                               \
-               int ret = 0;                                            \
-               static int (*tp)(void);                                 \
-               static int found;                                       \
-               const char *tp_name = "__testpoint_" #_name;            \
-                                                                       \
-               if (tp) {                                               \
-                       ret = tp();                                     \
-               } else {                                                \
-                       if (!found) {                                   \
-                               tp = (int (*)(void)) lttng_testpoint_lookup(tp_name);   \
-                               if (tp) {                               \
-                                       found = 1;                      \
-                                       ret = tp();                     \
-                               } else {                                \
-                                       found = -1;                     \
-                               }                                       \
-                       }                                               \
-               }                                                       \
-               return ret;                                             \
-       }
-
-/* Testpoint declaration */
-#define TESTPOINT_DECL(name)   \
-       _TESTPOINT_DECL(name)
-
-#endif /* NTESTPOINT */
diff --git a/src/common/testpoint/testpoint.hpp b/src/common/testpoint/testpoint.hpp
new file mode 100644 (file)
index 0000000..33cb9aa
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 Christian Babeux <christian.babeux@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifdef NTESTPOINT
+
+#define testpoint(name)
+#define TESTPOINT_DECL(name)
+
+#else /* NTESTPOINT */
+
+#include <urcu.h> /* for caa_likely/unlikely */
+
+extern int lttng_testpoint_activated;
+
+void *lttng_testpoint_lookup(const char *name);
+
+/*
+ * Testpoint is only active if the global lttng_testpoint_activated flag is
+ * set.
+ * Return a non-zero error code to indicate failure.
+ */
+#define testpoint(name)                                \
+       ((caa_unlikely(lttng_testpoint_activated))      \
+       ? __testpoint_##name##_wrapper() : 0)
+
+/*
+ * One wrapper per testpoint is generated. This is to keep track of the symbol
+ * lookup status and the corresponding function pointer, if any.
+ */
+#define _TESTPOINT_DECL(_name)                                         \
+       static inline int __testpoint_##_name##_wrapper(void)           \
+       {                                                               \
+               int ret = 0;                                            \
+               static int (*tp)(void);                                 \
+               static int found;                                       \
+               const char *tp_name = "__testpoint_" #_name;            \
+                                                                       \
+               if (tp) {                                               \
+                       ret = tp();                                     \
+               } else {                                                \
+                       if (!found) {                                   \
+                               tp = (int (*)(void)) lttng_testpoint_lookup(tp_name);   \
+                               if (tp) {                               \
+                                       found = 1;                      \
+                                       ret = tp();                     \
+                               } else {                                \
+                                       found = -1;                     \
+                               }                                       \
+                       }                                               \
+               }                                                       \
+               return ret;                                             \
+       }
+
+/* Testpoint declaration */
+#define TESTPOINT_DECL(name)   \
+       _TESTPOINT_DECL(name)
+
+#endif /* NTESTPOINT */
index 34a620679d258a1e72035416f67ed85310473ba4..fecc0064dbca83358dd65dfb559a1d8cca2e16bf 100644 (file)
@@ -7,8 +7,8 @@
 
 #include <string.h>
 
-#include <common/compat/pthread.h>
-#include "thread.h"
+#include <common/compat/pthread.hpp>
+#include "thread.hpp"
 
 
 int lttng_thread_setname(const char *name)
diff --git a/src/common/thread.h b/src/common/thread.h
deleted file mode 100644 (file)
index 3caa9dd..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2020 Michael Jeanson <mjeanson@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_THREAD_H
-#define LTTNG_THREAD_H
-
-#include <common/macros.h>
-
-/*
- * Set the current thread name on platforms that support it. The name can
- * be of arbitrary length and will be truncated to the platform limit,
- * usually 16.
- */
-int lttng_thread_setname(const char *name);
-
-#endif /* LTTNG_THREAD_H */
diff --git a/src/common/thread.hpp b/src/common/thread.hpp
new file mode 100644 (file)
index 0000000..3d4e7bd
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_THREAD_H
+#define LTTNG_THREAD_H
+
+#include <common/macros.hpp>
+
+/*
+ * Set the current thread name on platforms that support it. The name can
+ * be of arbitrary length and will be truncated to the platform limit,
+ * usually 16.
+ */
+int lttng_thread_setname(const char *name);
+
+#endif /* LTTNG_THREAD_H */
index a08358ffc66562507b7a199cadddfcc096e8b140..cce1b86a1eaf0cf541a3c8f27235506c1d0c5a2d 100644 (file)
@@ -5,11 +5,11 @@
  *
  */
 
-#include <common/time.h>
-#include <common/error.h>
-#include <common/macros.h>
-#include <common/error.h>
-#include <common/compat/errno.h>
+#include <common/time.hpp>
+#include <common/error.hpp>
+#include <common/macros.hpp>
+#include <common/error.hpp>
+#include <common/compat/errno.hpp>
 #include <stddef.h>
 #include <stdint.h>
 #include <limits.h>
diff --git a/src/common/time.h b/src/common/time.h
deleted file mode 100644 (file)
index 87adf17..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-or-later
- *
- */
-
-#ifndef LTTNG_TIME_H
-#define LTTNG_TIME_H
-
-#include <time.h>
-#include <stdbool.h>
-#include <common/macros.h>
-#include <common/compat/time.h>
-
-#define MSEC_PER_SEC    1000ULL
-#define NSEC_PER_SEC    1000000000ULL
-#define NSEC_PER_MSEC   1000000ULL
-#define NSEC_PER_USEC   1000ULL
-#define USEC_PER_SEC    1000000ULL
-#define USEC_PER_MSEC   1000ULL
-
-#define SEC_PER_MINUTE  60ULL
-#define MINUTE_PER_HOUR 60ULL
-
-#define USEC_PER_MINUTE (USEC_PER_SEC * SEC_PER_MINUTE)
-#define USEC_PER_HOURS  (USEC_PER_MINUTE * MINUTE_PER_HOUR)
-
-#define ISO8601_STR_LEN sizeof("YYYYmmddTHHMMSS+HHMM")
-#define DATETIME_STR_LEN sizeof("YYYYmmdd-HHMMSS")
-
-bool locale_supports_utf8(void);
-
-#define NSEC_UNIT       "ns"
-#define USEC_UNIT       (locale_supports_utf8() ? "µs" : "us")
-#define MSEC_UNIT       "ms"
-#define SEC_UNIT        "s"
-#define MIN_UNIT        "m"
-#define HR_UNIT         "h"
-
-/*
- * timespec_to_ms: Convert timespec to milliseconds.
- *
- * Returns 0 on success, else -1 on error. errno is set to EOVERFLOW if
- * input would overflow the output in milliseconds.
- */
-int timespec_to_ms(struct timespec ts, unsigned long *ms);
-
-/*
- * timespec_abs_diff: Absolute difference between timespec.
- */
-struct timespec timespec_abs_diff(struct timespec ts_a, struct timespec ts_b);
-
-/*
- * Format a Unix timestamp to an ISO 8601 compatible timestamp of
- * the form "YYYYmmddTHHMMSS+HHMM" in local time. `len` must >= to
- * ISO8601_STR_LEN.
- *
- * Returns 0 on success, else -1 on error.
- */
-int time_to_iso8601_str(time_t time, char *str, size_t len);
-
-int time_to_datetime_str(time_t time, char *str, size_t len);
-
-#endif /* LTTNG_TIME_H */
diff --git a/src/common/time.hpp b/src/common/time.hpp
new file mode 100644 (file)
index 0000000..724b202
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ */
+
+#ifndef LTTNG_TIME_H
+#define LTTNG_TIME_H
+
+#include <time.h>
+#include <stdbool.h>
+#include <common/macros.hpp>
+#include <common/compat/time.hpp>
+
+#define MSEC_PER_SEC    1000ULL
+#define NSEC_PER_SEC    1000000000ULL
+#define NSEC_PER_MSEC   1000000ULL
+#define NSEC_PER_USEC   1000ULL
+#define USEC_PER_SEC    1000000ULL
+#define USEC_PER_MSEC   1000ULL
+
+#define SEC_PER_MINUTE  60ULL
+#define MINUTE_PER_HOUR 60ULL
+
+#define USEC_PER_MINUTE (USEC_PER_SEC * SEC_PER_MINUTE)
+#define USEC_PER_HOURS  (USEC_PER_MINUTE * MINUTE_PER_HOUR)
+
+#define ISO8601_STR_LEN sizeof("YYYYmmddTHHMMSS+HHMM")
+#define DATETIME_STR_LEN sizeof("YYYYmmdd-HHMMSS")
+
+bool locale_supports_utf8(void);
+
+#define NSEC_UNIT       "ns"
+#define USEC_UNIT       (locale_supports_utf8() ? "µs" : "us")
+#define MSEC_UNIT       "ms"
+#define SEC_UNIT        "s"
+#define MIN_UNIT        "m"
+#define HR_UNIT         "h"
+
+/*
+ * timespec_to_ms: Convert timespec to milliseconds.
+ *
+ * Returns 0 on success, else -1 on error. errno is set to EOVERFLOW if
+ * input would overflow the output in milliseconds.
+ */
+int timespec_to_ms(struct timespec ts, unsigned long *ms);
+
+/*
+ * timespec_abs_diff: Absolute difference between timespec.
+ */
+struct timespec timespec_abs_diff(struct timespec ts_a, struct timespec ts_b);
+
+/*
+ * Format a Unix timestamp to an ISO 8601 compatible timestamp of
+ * the form "YYYYmmddTHHMMSS+HHMM" in local time. `len` must >= to
+ * ISO8601_STR_LEN.
+ *
+ * Returns 0 on success, else -1 on error.
+ */
+int time_to_iso8601_str(time_t time, char *str, size_t len);
+
+int time_to_datetime_str(time_t time, char *str, size_t len);
+
+#endif /* LTTNG_TIME_H */
diff --git a/src/common/trace-chunk-registry.h b/src/common/trace-chunk-registry.h
deleted file mode 100644 (file)
index 0eee0c2..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_TRACE_CHUNK_REGISTRY_H
-#define LTTNG_TRACE_CHUNK_REGISTRY_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <common/macros.h>
-#include <common/trace-chunk.h>
-
-struct lttng_trace_chunk_registry;
-
-/*
- * Create an lttng_trace_chunk registry.
- *
- * A trace chunk registry maintains an association between a
- * (session_id, chunk_id) tuple and a trace chunk object. The chunk_id can
- * be "unset" in the case of an anonymous trace chunk.
- *
- * Note that a trace chunk registry holds no ownership of its trace
- * chunks. Trace chunks are unpublished when their last reference is released.
- * See the documentation of lttng_trace_chunk.
- *
- * Returns a trace chunk registry on success, NULL on error.
- *
- * Note that a trace chunk registry may only be accessed by an RCU thread.
- */
-struct lttng_trace_chunk_registry *lttng_trace_chunk_registry_create(void);
-
-/*
- * Destroy an lttng trace chunk registry. The registry must be emptied
- * (i.e. all references to the trace chunks it contains must be released) before
- * it is destroyed.
- */
-void lttng_trace_chunk_registry_destroy(
-               struct lttng_trace_chunk_registry *registry);
-
-/*
- * Publish a trace chunk for a given session id.
- * A reference is acquired on behalf of the caller.
- *
- * The trace chunk that is returned is the published version of the trace
- * chunk. The chunk provided should be discarded on success and it's
- * published version used in its place.
- *
- * See the documentation of lttng_trace_chunk for more information on
- * the usage of the various parameters.
- *
- * Returns an lttng_trace_chunk on success, NULL on error.
- */
-struct lttng_trace_chunk *lttng_trace_chunk_registry_publish_chunk(
-               struct lttng_trace_chunk_registry *registry,
-               uint64_t session_id, struct lttng_trace_chunk *chunk);
-
-/*
- * Look-up a trace chunk by session_id and chunk_id.
- * A reference is acquired on behalf of the caller.
- *
- * Returns an lttng_trace_chunk on success, NULL if the chunk does not exist.
- */
-struct lttng_trace_chunk *
-lttng_trace_chunk_registry_find_chunk(
-               const struct lttng_trace_chunk_registry *registry,
-               uint64_t session_id, uint64_t chunk_id);
-
-/*
- * Query the existence of a trace chunk by session_id and chunk_id.
- *
- * Returns 0 on success, a negative value on error.
- */
-int lttng_trace_chunk_registry_chunk_exists(
-               const struct lttng_trace_chunk_registry *registry,
-               uint64_t session_id, uint64_t chunk_id, bool *chunk_exists);
-
-/*
- * Look-up an anonymous trace chunk by session_id.
- * A reference is acquired on behalf of the caller.
- *
- * Returns an lttng_trace_chunk on success, NULL if the chunk does not exist.
- */
-struct lttng_trace_chunk *
-lttng_trace_chunk_registry_find_anonymous_chunk(
-               const struct lttng_trace_chunk_registry *registry,
-               uint64_t session_id);
-
-unsigned int lttng_trace_chunk_registry_put_each_chunk(
-               const struct lttng_trace_chunk_registry *registry);
-
-#endif /* LTTNG_TRACE_CHUNK_REGISTRY_H */
diff --git a/src/common/trace-chunk-registry.hpp b/src/common/trace-chunk-registry.hpp
new file mode 100644 (file)
index 0000000..b5d9433
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_TRACE_CHUNK_REGISTRY_H
+#define LTTNG_TRACE_CHUNK_REGISTRY_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <common/macros.hpp>
+#include <common/trace-chunk.hpp>
+
+struct lttng_trace_chunk_registry;
+
+/*
+ * Create an lttng_trace_chunk registry.
+ *
+ * A trace chunk registry maintains an association between a
+ * (session_id, chunk_id) tuple and a trace chunk object. The chunk_id can
+ * be "unset" in the case of an anonymous trace chunk.
+ *
+ * Note that a trace chunk registry holds no ownership of its trace
+ * chunks. Trace chunks are unpublished when their last reference is released.
+ * See the documentation of lttng_trace_chunk.
+ *
+ * Returns a trace chunk registry on success, NULL on error.
+ *
+ * Note that a trace chunk registry may only be accessed by an RCU thread.
+ */
+struct lttng_trace_chunk_registry *lttng_trace_chunk_registry_create(void);
+
+/*
+ * Destroy an lttng trace chunk registry. The registry must be emptied
+ * (i.e. all references to the trace chunks it contains must be released) before
+ * it is destroyed.
+ */
+void lttng_trace_chunk_registry_destroy(
+               struct lttng_trace_chunk_registry *registry);
+
+/*
+ * Publish a trace chunk for a given session id.
+ * A reference is acquired on behalf of the caller.
+ *
+ * The trace chunk that is returned is the published version of the trace
+ * chunk. The chunk provided should be discarded on success and it's
+ * published version used in its place.
+ *
+ * See the documentation of lttng_trace_chunk for more information on
+ * the usage of the various parameters.
+ *
+ * Returns an lttng_trace_chunk on success, NULL on error.
+ */
+struct lttng_trace_chunk *lttng_trace_chunk_registry_publish_chunk(
+               struct lttng_trace_chunk_registry *registry,
+               uint64_t session_id, struct lttng_trace_chunk *chunk);
+
+/*
+ * Look-up a trace chunk by session_id and chunk_id.
+ * A reference is acquired on behalf of the caller.
+ *
+ * Returns an lttng_trace_chunk on success, NULL if the chunk does not exist.
+ */
+struct lttng_trace_chunk *
+lttng_trace_chunk_registry_find_chunk(
+               const struct lttng_trace_chunk_registry *registry,
+               uint64_t session_id, uint64_t chunk_id);
+
+/*
+ * Query the existence of a trace chunk by session_id and chunk_id.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+int lttng_trace_chunk_registry_chunk_exists(
+               const struct lttng_trace_chunk_registry *registry,
+               uint64_t session_id, uint64_t chunk_id, bool *chunk_exists);
+
+/*
+ * Look-up an anonymous trace chunk by session_id.
+ * A reference is acquired on behalf of the caller.
+ *
+ * Returns an lttng_trace_chunk on success, NULL if the chunk does not exist.
+ */
+struct lttng_trace_chunk *
+lttng_trace_chunk_registry_find_anonymous_chunk(
+               const struct lttng_trace_chunk_registry *registry,
+               uint64_t session_id);
+
+unsigned int lttng_trace_chunk_registry_put_each_chunk(
+               const struct lttng_trace_chunk_registry *registry);
+
+#endif /* LTTNG_TRACE_CHUNK_REGISTRY_H */
index eed3d558b0181d269501fb485e7ec63298a8f8d5..74ce91cb7ad006ee8e4ad4290be00dc350e3b2ed 100644 (file)
@@ -5,23 +5,23 @@
  *
  */
 
-#include <common/compat/directory-handle.h>
-#include <common/credentials.h>
-#include <common/defaults.h>
-#include <common/dynamic-array.h>
-#include <common/error.h>
-#include <common/fd-tracker/fd-tracker.h>
-#include <common/fd-tracker/utils.h>
-#include <common/fs-handle.h>
-#include <common/fs-handle-internal.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/optional.h>
-#include <common/string-utils/format.h>
-#include <common/time.h>
-#include <common/trace-chunk-registry.h>
-#include <common/trace-chunk.h>
-#include <common/utils.h>
+#include <common/compat/directory-handle.hpp>
+#include <common/credentials.hpp>
+#include <common/defaults.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/error.hpp>
+#include <common/fd-tracker/fd-tracker.hpp>
+#include <common/fd-tracker/utils.hpp>
+#include <common/fs-handle.hpp>
+#include <common/fs-handle-internal.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/optional.hpp>
+#include <common/string-utils/format.hpp>
+#include <common/time.hpp>
+#include <common/trace-chunk-registry.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/utils.hpp>
 #include <lttng/constant.h>
 
 #include <inttypes.h>
diff --git a/src/common/trace-chunk.h b/src/common/trace-chunk.h
deleted file mode 100644 (file)
index 4e4440b..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_TRACE_CHUNK_H
-#define LTTNG_TRACE_CHUNK_H
-
-#include <common/compat/directory-handle.h>
-#include <common/credentials.h>
-#include <common/fd-tracker/fd-tracker.h>
-#include <common/macros.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-/*
- * A trace chunk is a group of directories and files forming a (or a set of)
- * complete and independant trace(s). For instance, a trace archive chunk,
- * a snapshot, or a regular LTTng trace are all instances of a trace archive.
- *
- * A trace chunk is always contained within a session output directory.
- *
- * This facility is used by the session daemon, consumer daemon(s), and relay
- * daemon to:
- *   - Control file (data stream, metadata, and index) creation relative to
- *     a given output directory,
- *   - Track the use of an output directory by other objects in order to
- *     know if/when an output directory can be safely consumed, renamed,
- *     deleted, etc.
- *
- *
- * OWNER VS USER
- * ---
- *
- * A trace chunk can either be a owner or a user of its
- * "chunk output directory".
- *
- * A "user" trace chunk is provided with a handle to the chunk output directory
- * which can then be used to create subdirectories and files.
- *
- * An "owner" chunk, on top of being able to perform the operations of a "user"
- * chunk can perform operations on its chunk output directory, such as renaming
- * or deleting it.
- *
- * A trace chunk becomes an "owner" or "user" chunk based on which of
- * 'lttng_trace_chunk_set_as_owner()' or 'lttng_trace_chunk_set_as_user()' is
- * used. These methods are _exclusive_ and must only be used once on a
- * trace chunk.
- */
-
-struct lttng_trace_chunk;
-struct fd_tracker;
-
-enum lttng_trace_chunk_status {
-       LTTNG_TRACE_CHUNK_STATUS_OK,
-       LTTNG_TRACE_CHUNK_STATUS_NONE,
-       LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT,
-       LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION,
-       LTTNG_TRACE_CHUNK_STATUS_ERROR,
-       LTTNG_TRACE_CHUNK_STATUS_NO_FILE,
-};
-
-enum lttng_trace_chunk_command_type {
-       LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED = 0,
-       LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION = 1,
-       LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE = 2,
-       LTTNG_TRACE_CHUNK_COMMAND_TYPE_MAX,
-};
-
-struct lttng_trace_chunk *lttng_trace_chunk_create_anonymous(void);
-
-struct lttng_trace_chunk *lttng_trace_chunk_create(
-               uint64_t chunk_id,
-               time_t chunk_creation_time,
-               const char *path);
-
-void lttng_trace_chunk_set_fd_tracker(struct lttng_trace_chunk *chunk,
-               struct fd_tracker *fd_tracker);
-
-/*
- * Copy a trace chunk. The copy that is returned is always a _user_
- * mode chunk even if the source chunk was an _owner_ as there can never be
- * two _owners_ of the same trace output.
- */
-struct lttng_trace_chunk *lttng_trace_chunk_copy(
-               struct lttng_trace_chunk *source_chunk);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_id(
-               struct lttng_trace_chunk *chunk, uint64_t *id);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_creation_timestamp(
-               struct lttng_trace_chunk *chunk, time_t *creation_ts);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_close_timestamp(
-               struct lttng_trace_chunk *chunk, time_t *close_ts);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_close_timestamp(
-               struct lttng_trace_chunk *chunk, time_t close_ts);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_name(
-               struct lttng_trace_chunk *chunk, const char **name,
-               bool *name_overridden);
-
-bool lttng_trace_chunk_get_name_overridden(struct lttng_trace_chunk *chunk);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_override_name(
-               struct lttng_trace_chunk *chunk, const char *name);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_rename_path(
-               struct lttng_trace_chunk *chunk, const char *path);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials(
-               struct lttng_trace_chunk *chunk,
-               struct lttng_credentials *credentials);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials(
-               struct lttng_trace_chunk *chunk,
-               const struct lttng_credentials *credentials);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials_current_user(
-               struct lttng_trace_chunk *chunk);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner(
-               struct lttng_trace_chunk *chunk,
-               struct lttng_directory_handle *session_output_directory);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_as_user(
-               struct lttng_trace_chunk *chunk,
-               struct lttng_directory_handle *chunk_directory);
-
-enum lttng_trace_chunk_status
-lttng_trace_chunk_get_session_output_directory_handle(
-               struct lttng_trace_chunk *chunk,
-               struct lttng_directory_handle **handle);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_borrow_chunk_directory_handle(
-               struct lttng_trace_chunk *chunk,
-               const struct lttng_directory_handle **handle);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_create_subdirectory(
-               struct lttng_trace_chunk *chunk,
-               const char *subdirectory_path);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_open_file(
-               struct lttng_trace_chunk *chunk,
-               const char *filename,
-               int flags,
-               mode_t mode,
-               int *out_fd,
-               bool expect_no_file);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_open_fs_handle(
-               struct lttng_trace_chunk *chunk,
-               const char *filename,
-               int flags,
-               mode_t mode,
-               struct fs_handle **out_handle,
-               bool expect_no_file);
-
-int lttng_trace_chunk_unlink_file(struct lttng_trace_chunk *chunk,
-               const char *filename);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_close_command(
-               struct lttng_trace_chunk *chunk,
-               enum lttng_trace_chunk_command_type *command_type);
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command(
-               struct lttng_trace_chunk *chunk,
-               enum lttng_trace_chunk_command_type command_type);
-
-const char *lttng_trace_chunk_command_type_get_name(
-               enum lttng_trace_chunk_command_type command);
-
-bool lttng_trace_chunk_ids_equal(const struct lttng_trace_chunk *chunk_a,
-               const struct lttng_trace_chunk *chunk_b);
-
-/* Returns true on success. */
-bool lttng_trace_chunk_get(struct lttng_trace_chunk *chunk);
-
-void lttng_trace_chunk_put(struct lttng_trace_chunk *chunk);
-
-#endif /* LTTNG_TRACE_CHUNK_H */
diff --git a/src/common/trace-chunk.hpp b/src/common/trace-chunk.hpp
new file mode 100644 (file)
index 0000000..cf038b9
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_TRACE_CHUNK_H
+#define LTTNG_TRACE_CHUNK_H
+
+#include <common/compat/directory-handle.hpp>
+#include <common/credentials.hpp>
+#include <common/fd-tracker/fd-tracker.hpp>
+#include <common/macros.hpp>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * A trace chunk is a group of directories and files forming a (or a set of)
+ * complete and independant trace(s). For instance, a trace archive chunk,
+ * a snapshot, or a regular LTTng trace are all instances of a trace archive.
+ *
+ * A trace chunk is always contained within a session output directory.
+ *
+ * This facility is used by the session daemon, consumer daemon(s), and relay
+ * daemon to:
+ *   - Control file (data stream, metadata, and index) creation relative to
+ *     a given output directory,
+ *   - Track the use of an output directory by other objects in order to
+ *     know if/when an output directory can be safely consumed, renamed,
+ *     deleted, etc.
+ *
+ *
+ * OWNER VS USER
+ * ---
+ *
+ * A trace chunk can either be a owner or a user of its
+ * "chunk output directory".
+ *
+ * A "user" trace chunk is provided with a handle to the chunk output directory
+ * which can then be used to create subdirectories and files.
+ *
+ * An "owner" chunk, on top of being able to perform the operations of a "user"
+ * chunk can perform operations on its chunk output directory, such as renaming
+ * or deleting it.
+ *
+ * A trace chunk becomes an "owner" or "user" chunk based on which of
+ * 'lttng_trace_chunk_set_as_owner()' or 'lttng_trace_chunk_set_as_user()' is
+ * used. These methods are _exclusive_ and must only be used once on a
+ * trace chunk.
+ */
+
+struct lttng_trace_chunk;
+struct fd_tracker;
+
+enum lttng_trace_chunk_status {
+       LTTNG_TRACE_CHUNK_STATUS_OK,
+       LTTNG_TRACE_CHUNK_STATUS_NONE,
+       LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT,
+       LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION,
+       LTTNG_TRACE_CHUNK_STATUS_ERROR,
+       LTTNG_TRACE_CHUNK_STATUS_NO_FILE,
+};
+
+enum lttng_trace_chunk_command_type {
+       LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED = 0,
+       LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION = 1,
+       LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE = 2,
+       LTTNG_TRACE_CHUNK_COMMAND_TYPE_MAX,
+};
+
+struct lttng_trace_chunk *lttng_trace_chunk_create_anonymous(void);
+
+struct lttng_trace_chunk *lttng_trace_chunk_create(
+               uint64_t chunk_id,
+               time_t chunk_creation_time,
+               const char *path);
+
+void lttng_trace_chunk_set_fd_tracker(struct lttng_trace_chunk *chunk,
+               struct fd_tracker *fd_tracker);
+
+/*
+ * Copy a trace chunk. The copy that is returned is always a _user_
+ * mode chunk even if the source chunk was an _owner_ as there can never be
+ * two _owners_ of the same trace output.
+ */
+struct lttng_trace_chunk *lttng_trace_chunk_copy(
+               struct lttng_trace_chunk *source_chunk);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_get_id(
+               struct lttng_trace_chunk *chunk, uint64_t *id);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_get_creation_timestamp(
+               struct lttng_trace_chunk *chunk, time_t *creation_ts);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_get_close_timestamp(
+               struct lttng_trace_chunk *chunk, time_t *close_ts);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_set_close_timestamp(
+               struct lttng_trace_chunk *chunk, time_t close_ts);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_get_name(
+               struct lttng_trace_chunk *chunk, const char **name,
+               bool *name_overridden);
+
+bool lttng_trace_chunk_get_name_overridden(struct lttng_trace_chunk *chunk);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_override_name(
+               struct lttng_trace_chunk *chunk, const char *name);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_rename_path(
+               struct lttng_trace_chunk *chunk, const char *path);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials(
+               struct lttng_trace_chunk *chunk,
+               struct lttng_credentials *credentials);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials(
+               struct lttng_trace_chunk *chunk,
+               const struct lttng_credentials *credentials);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials_current_user(
+               struct lttng_trace_chunk *chunk);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner(
+               struct lttng_trace_chunk *chunk,
+               struct lttng_directory_handle *session_output_directory);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_set_as_user(
+               struct lttng_trace_chunk *chunk,
+               struct lttng_directory_handle *chunk_directory);
+
+enum lttng_trace_chunk_status
+lttng_trace_chunk_get_session_output_directory_handle(
+               struct lttng_trace_chunk *chunk,
+               struct lttng_directory_handle **handle);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_borrow_chunk_directory_handle(
+               struct lttng_trace_chunk *chunk,
+               const struct lttng_directory_handle **handle);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_create_subdirectory(
+               struct lttng_trace_chunk *chunk,
+               const char *subdirectory_path);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_open_file(
+               struct lttng_trace_chunk *chunk,
+               const char *filename,
+               int flags,
+               mode_t mode,
+               int *out_fd,
+               bool expect_no_file);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_open_fs_handle(
+               struct lttng_trace_chunk *chunk,
+               const char *filename,
+               int flags,
+               mode_t mode,
+               struct fs_handle **out_handle,
+               bool expect_no_file);
+
+int lttng_trace_chunk_unlink_file(struct lttng_trace_chunk *chunk,
+               const char *filename);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_get_close_command(
+               struct lttng_trace_chunk *chunk,
+               enum lttng_trace_chunk_command_type *command_type);
+
+enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command(
+               struct lttng_trace_chunk *chunk,
+               enum lttng_trace_chunk_command_type command_type);
+
+const char *lttng_trace_chunk_command_type_get_name(
+               enum lttng_trace_chunk_command_type command);
+
+bool lttng_trace_chunk_ids_equal(const struct lttng_trace_chunk *chunk_a,
+               const struct lttng_trace_chunk *chunk_b);
+
+/* Returns true on success. */
+bool lttng_trace_chunk_get(struct lttng_trace_chunk *chunk);
+
+void lttng_trace_chunk_put(struct lttng_trace_chunk *chunk);
+
+#endif /* LTTNG_TRACE_CHUNK_H */
index 84b6c6b8f11c33f31039f711ddb0061f5d6ae568..38ffb695bbdae85c1bd38a179400629ad9d75064 100644 (file)
 #include <lttng/lttng-error.h>
 #include <lttng/tracker.h>
 
-#include <common/dynamic-array.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/tracker.h>
+#include <common/dynamic-array.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/tracker.hpp>
 
 #include <stdbool.h>
+#include <type_traits>
 
 struct process_attr_tracker_values_comm_header {
        uint32_t count;
@@ -33,16 +34,16 @@ struct process_attr_tracker_value_comm {
 };
 
 #define GET_INTEGRAL_COMM_VALUE(value_ptr, as_type)              \
-       ((as_type)(is_signed(as_type) ? (value_ptr)->u._signed : \
-                                       (value_ptr)->u._unsigned))
+       ((as_type)(std::is_signed<as_type>::value ?              \
+                       (value_ptr)->u._signed : (value_ptr)->u._unsigned))
 
-#define SET_INTEGRAL_COMM_VALUE(comm_value, value)                         \
-       if (is_signed(typeof(value))) {                                    \
+#define SET_INTEGRAL_COMM_VALUE(comm_value, from_value)                         \
+       if (std::is_signed<decltype(from_value)>::value) {                      \
                (comm_value)->u._signed =                                  \
-                               (typeof((comm_value)->u._signed)) value;   \
+                               (typeof((comm_value)->u._signed)) from_value;   \
        } else {                                                           \
                (comm_value)->u._unsigned =                                \
-                               (typeof((comm_value)->u._unsigned)) value; \
+                               (typeof((comm_value)->u._unsigned)) from_value; \
        }
 
 static inline bool is_virtual_process_attr(enum lttng_process_attr process_attr)
diff --git a/src/common/tracker.h b/src/common/tracker.h
deleted file mode 100644 (file)
index 8b37940..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
- * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_COMMON_TRACKER_H
-#define LTTNG_COMMON_TRACKER_H
-
-#include <lttng/lttng-error.h>
-#include <lttng/tracker.h>
-
-#include <common/buffer-view.h>
-#include <common/dynamic-array.h>
-#include <common/macros.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-
-struct process_attr_value {
-       enum lttng_process_attr_value_type type;
-       union value {
-               pid_t pid;
-               uid_t uid;
-               char *user_name;
-               gid_t gid;
-               char *group_name;
-       } value;
-};
-
-struct lttng_process_attr_values {
-       /* Array of struct process_attr_tracker_value. */
-       struct lttng_dynamic_pointer_array array;
-};
-
-const char *lttng_process_attr_to_string(enum lttng_process_attr process_attr);
-
-struct lttng_process_attr_values *lttng_process_attr_values_create(void);
-
-/* Prefixed with '_' since the name conflicts with a public API. */
-unsigned int _lttng_process_attr_values_get_count(
-               const struct lttng_process_attr_values *values);
-
-const struct process_attr_value *lttng_process_attr_tracker_values_get_at_index(
-               const struct lttng_process_attr_values *values,
-               unsigned int index);
-
-int lttng_process_attr_values_serialize(
-               const struct lttng_process_attr_values *values,
-               struct lttng_dynamic_buffer *buffer);
-
-ssize_t lttng_process_attr_values_create_from_buffer(
-               enum lttng_domain_type domain,
-               enum lttng_process_attr process_attr,
-               const struct lttng_buffer_view *buffer_view,
-               struct lttng_process_attr_values **_values);
-
-void lttng_process_attr_values_destroy(
-               struct lttng_process_attr_values *values);
-
-struct process_attr_value *process_attr_value_copy(
-               const struct process_attr_value *value);
-
-unsigned long process_attr_value_hash(const struct process_attr_value *a);
-
-bool process_attr_tracker_value_equal(const struct process_attr_value *a,
-               const struct process_attr_value *b);
-
-void process_attr_value_destroy(struct process_attr_value *value);
-
-enum lttng_error_code process_attr_value_from_comm(
-               enum lttng_domain_type domain,
-               enum lttng_process_attr process_attr,
-               enum lttng_process_attr_value_type value_type,
-               const struct process_attr_integral_value_comm *integral_value,
-               const struct lttng_buffer_view *value_view,
-               struct process_attr_value **value);
-
-#endif /* LTTNG_COMMON_TRACKER_H */
diff --git a/src/common/tracker.hpp b/src/common/tracker.hpp
new file mode 100644 (file)
index 0000000..7f4702a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_COMMON_TRACKER_H
+#define LTTNG_COMMON_TRACKER_H
+
+#include <lttng/lttng-error.h>
+#include <lttng/tracker.h>
+
+#include <common/buffer-view.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/macros.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+
+struct process_attr_value {
+       enum lttng_process_attr_value_type type;
+       union value {
+               pid_t pid;
+               uid_t uid;
+               char *user_name;
+               gid_t gid;
+               char *group_name;
+       } value;
+};
+
+struct lttng_process_attr_values {
+       /* Array of struct process_attr_tracker_value. */
+       struct lttng_dynamic_pointer_array array;
+};
+
+const char *lttng_process_attr_to_string(enum lttng_process_attr process_attr);
+
+struct lttng_process_attr_values *lttng_process_attr_values_create(void);
+
+/* Prefixed with '_' since the name conflicts with a public API. */
+unsigned int _lttng_process_attr_values_get_count(
+               const struct lttng_process_attr_values *values);
+
+const struct process_attr_value *lttng_process_attr_tracker_values_get_at_index(
+               const struct lttng_process_attr_values *values,
+               unsigned int index);
+
+int lttng_process_attr_values_serialize(
+               const struct lttng_process_attr_values *values,
+               struct lttng_dynamic_buffer *buffer);
+
+ssize_t lttng_process_attr_values_create_from_buffer(
+               enum lttng_domain_type domain,
+               enum lttng_process_attr process_attr,
+               const struct lttng_buffer_view *buffer_view,
+               struct lttng_process_attr_values **_values);
+
+void lttng_process_attr_values_destroy(
+               struct lttng_process_attr_values *values);
+
+struct process_attr_value *process_attr_value_copy(
+               const struct process_attr_value *value);
+
+unsigned long process_attr_value_hash(const struct process_attr_value *a);
+
+bool process_attr_tracker_value_equal(const struct process_attr_value *a,
+               const struct process_attr_value *b);
+
+void process_attr_value_destroy(struct process_attr_value *value);
+
+enum lttng_error_code process_attr_value_from_comm(
+               enum lttng_domain_type domain,
+               enum lttng_process_attr process_attr,
+               enum lttng_process_attr_value_type value_type,
+               const struct process_attr_integral_value_comm *integral_value,
+               const struct lttng_buffer_view *value_view,
+               struct process_attr_value **value);
+
+#endif /* LTTNG_COMMON_TRACKER_H */
index 3782f49cad19c901d709d4531d7ca5e4db679d8a..64fd15d5308a43d0e8fc46ca5984bc953b2b2656 100644 (file)
@@ -5,24 +5,24 @@
  *
  */
 
-#include <common/credentials.h>
-#include <common/dynamic-array.h>
-#include <common/error.h>
-#include <common/mi-lttng.h>
-#include <common/optional.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
+#include <common/credentials.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/error.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/optional.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
 #include <inttypes.h>
-#include <lttng/action/action-internal.h>
+#include <lttng/action/action-internal.hpp>
 #include <lttng/condition/buffer-usage.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/condition/condition-internal.hpp>
+#include <lttng/condition/event-rule-matches-internal.hpp>
 #include <lttng/condition/event-rule-matches.h>
 #include <lttng/domain.h>
-#include <lttng/error-query-internal.h>
-#include <lttng/event-expr-internal.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/trigger/trigger-internal.h>
+#include <lttng/error-query-internal.hpp>
+#include <lttng/event-expr-internal.hpp>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/trigger/trigger-internal.hpp>
 #include <pthread.h>
 
 bool lttng_trigger_validate(const struct lttng_trigger *trigger)
index 504970ea8ace30b19457aef27801bdbf91390b60..b50b8ecda6c8186853ef2abc15a8296cb3349eb3 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/common.h>
-#include <common/compat/errno.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/fd-handle.h>
+#include <common/common.hpp>
+#include <common/compat/errno.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/fd-handle.hpp>
 
-#include "unix.h"
+#include "unix.hpp"
 
 /*
  * Connect to unix socket using the path name.
diff --git a/src/common/unix.h b/src/common/unix.h
deleted file mode 100644 (file)
index 820dff0..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTCOMM_UNIX_H
-#define _LTTCOMM_UNIX_H
-
-#include <limits.h>
-#include <sys/un.h>
-
-#include <common/compat/socket.h>
-#include <common/macros.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
-
-int lttcomm_create_unix_sock(const char *pathname);
-int lttcomm_create_anon_unix_socketpair(int *fds);
-int lttcomm_connect_unix_sock(const char *pathname);
-int lttcomm_accept_unix_sock(int sock);
-int lttcomm_listen_unix_sock(int sock);
-int lttcomm_close_unix_sock(int sock);
-
-/* Send a message accompanied by fd(s) over a unix socket. */
-ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd);
-ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock,
-               struct lttng_payload_view *view);
-ssize_t lttcomm_send_fds_unix_sock_non_block(
-               int sock, const int *fds, size_t nb_fd);
-ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock,
-               struct lttng_payload_view *view);
-
-/* Recv a message accompanied by fd(s) from a unix socket */
-ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd);
-ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
-               struct lttng_payload *payload);
-ssize_t lttcomm_recv_fds_unix_sock_non_block(int sock, int *fds, size_t nb_fd);
-ssize_t lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd,
-               struct lttng_payload *payload);
-
-ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len);
-ssize_t lttcomm_recv_unix_sock_non_block(int sock, void *buf, size_t len);
-ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len);
-ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len);
-
-ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len);
-ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len,
-               lttng_sock_cred *creds);
-
-int lttcomm_setsockopt_creds_unix_sock(int sock);
-
-#endif /* _LTTCOMM_UNIX_H */
diff --git a/src/common/unix.hpp b/src/common/unix.hpp
new file mode 100644 (file)
index 0000000..b662160
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTCOMM_UNIX_H
+#define _LTTCOMM_UNIX_H
+
+#include <limits.h>
+#include <sys/un.h>
+
+#include <common/compat/socket.hpp>
+#include <common/macros.hpp>
+#include <common/payload.hpp>
+#include <common/payload-view.hpp>
+
+int lttcomm_create_unix_sock(const char *pathname);
+int lttcomm_create_anon_unix_socketpair(int *fds);
+int lttcomm_connect_unix_sock(const char *pathname);
+int lttcomm_accept_unix_sock(int sock);
+int lttcomm_listen_unix_sock(int sock);
+int lttcomm_close_unix_sock(int sock);
+
+/* Send a message accompanied by fd(s) over a unix socket. */
+ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd);
+ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock,
+               struct lttng_payload_view *view);
+ssize_t lttcomm_send_fds_unix_sock_non_block(
+               int sock, const int *fds, size_t nb_fd);
+ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock,
+               struct lttng_payload_view *view);
+
+/* Recv a message accompanied by fd(s) from a unix socket */
+ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd);
+ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
+               struct lttng_payload *payload);
+ssize_t lttcomm_recv_fds_unix_sock_non_block(int sock, int *fds, size_t nb_fd);
+ssize_t lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd,
+               struct lttng_payload *payload);
+
+ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len);
+ssize_t lttcomm_recv_unix_sock_non_block(int sock, void *buf, size_t len);
+ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len);
+ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len);
+
+ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len);
+ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len,
+               lttng_sock_cred *creds);
+
+int lttcomm_setsockopt_creds_unix_sock(int sock);
+
+#endif /* _LTTCOMM_UNIX_H */
index b1c2c63d09bcc28475445cfd5f998076bfc0d245..d522231673e022a158f5a71b5ac7872a51a7bf67 100644 (file)
@@ -7,16 +7,16 @@
 
 #define _LGPL_SOURCE
 #include <arpa/inet.h>
-#include <common/compat/netdb.h>
+#include <common/compat/netdb.hpp>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
 
-#include <common/common.h>
-#include <common/defaults.h>
-#include <common/utils.h>
+#include <common/common.hpp>
+#include <common/defaults.hpp>
+#include <common/utils.hpp>
 
-#include "uri.h"
+#include "uri.hpp"
 
 #define LOOPBACK_ADDR_IPV4 "127.0.0.1"
 #define LOOPBACK_ADDR_IPV6 "::1"
diff --git a/src/common/uri.h b/src/common/uri.h
deleted file mode 100644 (file)
index b0af032..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef URI_H
-#define URI_H
-
-#include <netinet/in.h>
-#include <lttng/lttng.h>
-#include <common/macros.h>
-
-/* Destination type of lttng URI */
-enum lttng_dst_type {
-       LTTNG_DST_IPV4                        = 1,
-       LTTNG_DST_IPV6                        = 2,
-       LTTNG_DST_PATH                        = 3,
-};
-
-/* Type of lttng URI where it is a final destination or a hop */
-enum lttng_uri_type {
-       LTTNG_URI_DST,  /* The URI is a final destination */
-       /*
-        * Hops are not supported yet but planned for a future release.
-        *
-        LTTNG_URI_HOP,
-        */
-};
-
-/* Communication stream type of a lttng URI */
-enum lttng_stream_type {
-       LTTNG_STREAM_CONTROL,
-       LTTNG_STREAM_DATA,
-};
-
-/*
- * Protocol type of a lttng URI. The value 0 indicate that the proto_type field
- * should be ignored.
- */
-enum lttng_proto_type {
-       LTTNG_PROTO_TYPE_NONE                 = 0,
-       LTTNG_TCP                             = 1,
-       /*
-        * UDP protocol is not supported for now.
-        *
-        LTTNG_UDP                             = 2,
-        */
-};
-
-/*
- * Structure representing an URI supported by lttng.
- */
-struct lttng_uri {
-       enum lttng_dst_type dtype;
-       enum lttng_uri_type utype;
-       enum lttng_stream_type stype;
-       enum lttng_proto_type proto;
-       uint16_t port;
-       char subdir[LTTNG_PATH_MAX];
-       union {
-               char ipv4[INET_ADDRSTRLEN];
-               char ipv6[INET6_ADDRSTRLEN];
-               char path[LTTNG_PATH_MAX];
-       } dst;
-} LTTNG_PACKED;
-
-int uri_compare(struct lttng_uri *uri1, struct lttng_uri *uri2);
-void uri_free(struct lttng_uri *uri);
-ssize_t uri_parse(const char *str_uri, struct lttng_uri **uris);
-ssize_t uri_parse_str_urls(const char *ctrl_url, const char *data_url,
-               struct lttng_uri **uris);
-int uri_to_str_url(struct lttng_uri *uri, char *dst, size_t size);
-
-#endif /* _LTT_URI_H */
diff --git a/src/common/uri.hpp b/src/common/uri.hpp
new file mode 100644 (file)
index 0000000..9b569b4
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef URI_H
+#define URI_H
+
+#include <netinet/in.h>
+#include <lttng/lttng.h>
+#include <common/macros.hpp>
+
+/* Destination type of lttng URI */
+enum lttng_dst_type {
+       LTTNG_DST_IPV4                        = 1,
+       LTTNG_DST_IPV6                        = 2,
+       LTTNG_DST_PATH                        = 3,
+};
+
+/* Type of lttng URI where it is a final destination or a hop */
+enum lttng_uri_type {
+       LTTNG_URI_DST,  /* The URI is a final destination */
+       /*
+        * Hops are not supported yet but planned for a future release.
+        *
+        LTTNG_URI_HOP,
+        */
+};
+
+/* Communication stream type of a lttng URI */
+enum lttng_stream_type {
+       LTTNG_STREAM_CONTROL,
+       LTTNG_STREAM_DATA,
+};
+
+/*
+ * Protocol type of a lttng URI. The value 0 indicate that the proto_type field
+ * should be ignored.
+ */
+enum lttng_proto_type {
+       LTTNG_PROTO_TYPE_NONE                 = 0,
+       LTTNG_TCP                             = 1,
+       /*
+        * UDP protocol is not supported for now.
+        *
+        LTTNG_UDP                             = 2,
+        */
+};
+
+/*
+ * Structure representing an URI supported by lttng.
+ */
+struct lttng_uri {
+       enum lttng_dst_type dtype;
+       enum lttng_uri_type utype;
+       enum lttng_stream_type stype;
+       enum lttng_proto_type proto;
+       uint16_t port;
+       char subdir[LTTNG_PATH_MAX];
+       union {
+               char ipv4[INET_ADDRSTRLEN];
+               char ipv6[INET6_ADDRSTRLEN];
+               char path[LTTNG_PATH_MAX];
+       } dst;
+} LTTNG_PACKED;
+
+int uri_compare(struct lttng_uri *uri1, struct lttng_uri *uri2);
+void uri_free(struct lttng_uri *uri);
+ssize_t uri_parse(const char *str_uri, struct lttng_uri **uris);
+ssize_t uri_parse_str_urls(const char *ctrl_url, const char *data_url,
+               struct lttng_uri **uris);
+int uri_to_str_url(struct lttng_uri *uri, char *dst, size_t size);
+
+#endif /* _LTT_URI_H */
index 4ade5d84fcb93df2ec7971574770b0dfe811c02c..7eb4a6d91117e4632eea619090582a08000705c4 100644 (file)
@@ -6,18 +6,18 @@
  */
 
 #include "lttng/lttng-error.h"
-#include <common/compat/string.h>
-#include <common/align.h>
-#include <common/error.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/macros.h>
-#include <common/mi-lttng.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
+#include <common/compat/string.hpp>
+#include <common/align.hpp>
+#include <common/error.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/macros.hpp>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
 #include <fcntl.h>
 #include <lttng/constant.h>
-#include <lttng/userspace-probe-internal.h>
+#include <lttng/userspace-probe-internal.hpp>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
diff --git a/src/common/ust-consumer/Makefile.am b/src/common/ust-consumer/Makefile.am
deleted file mode 100644 (file)
index 26f1667..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-if HAVE_LIBLTTNG_UST_CTL
-
-noinst_LTLIBRARIES = libust-consumer.la
-
-libust_consumer_la_SOURCES = \
-       ust-consumer.cpp \
-       ust-consumer.h
-
-libust_consumer_la_LIBADD = \
-                       $(UST_CTL_LIBS) \
-                       $(top_builddir)/src/common/relayd/librelayd.la
-
-endif
index fb40f844ed34370ce262594af15115ed8c9a8d76..051b4a7684c767d0caaae9eaf001b985023ff1c5 100644 (file)
 #include <stdbool.h>
 #include <stdint.h>
 
-#include <bin/lttng-consumerd/health-consumerd.h>
-#include <common/common.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/relayd/relayd.h>
-#include <common/compat/fcntl.h>
-#include <common/compat/endian.h>
-#include <common/consumer/consumer-metadata-cache.h>
-#include <common/consumer/consumer-stream.h>
-#include <common/consumer/consumer-timer.h>
-#include <common/utils.h>
-#include <common/index/index.h>
-#include <common/consumer/consumer.h>
-#include <common/shm.h>
-#include <common/optional.h>
-
-#include "ust-consumer.h"
+#include <bin/lttng-consumerd/health-consumerd.hpp>
+#include <common/common.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/relayd/relayd.hpp>
+#include <common/compat/fcntl.hpp>
+#include <common/compat/endian.hpp>
+#include <common/consumer/consumer-metadata-cache.hpp>
+#include <common/consumer/consumer-stream.hpp>
+#include <common/consumer/consumer-timer.hpp>
+#include <common/utils.hpp>
+#include <common/index/index.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/shm.hpp>
+#include <common/optional.hpp>
+
+#include "ust-consumer.hpp"
 
 #define INT_MAX_STR_LEN 12     /* includes \0 */
 
@@ -3087,13 +3087,13 @@ static int lttng_ustconsumer_set_stream_ops(
                                extract_metadata_subbuffer_info;
                stream->read_subbuffer_ops.reset_metadata =
                                metadata_stream_reset_cache_consumed_position;
+               ret = consumer_stream_enable_metadata_bucketization(
+                               stream);
+               if (ret) {
+                       goto end;
+               }
                if (stream->chan->is_live) {
                        stream->read_subbuffer_ops.on_sleep = signal_metadata;
-                       ret = consumer_stream_enable_metadata_bucketization(
-                                       stream);
-                       if (ret) {
-                               goto end;
-                       }
                }
        } else {
                stream->read_subbuffer_ops.get_next_subbuffer =
diff --git a/src/common/ust-consumer/ust-consumer.h b/src/common/ust-consumer/ust-consumer.h
deleted file mode 100644 (file)
index e2507a7..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _LTTNG_USTCONSUMER_H
-#define _LTTNG_USTCONSUMER_H
-
-#include <common/compat/errno.h>
-#include <common/consumer/consumer.h>
-#include <stdbool.h>
-
-#ifdef HAVE_LIBLTTNG_UST_CTL
-
-int lttng_ustconsumer_take_snapshot(struct lttng_consumer_stream *stream);
-int lttng_ustconsumer_sample_snapshot_positions(
-               struct lttng_consumer_stream *stream);
-
-int lttng_ustconsumer_get_produced_snapshot(
-               struct lttng_consumer_stream *stream, unsigned long *pos);
-int lttng_ustconsumer_get_consumed_snapshot(
-               struct lttng_consumer_stream *stream, unsigned long *pos);
-
-int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
-               int sock, struct pollfd *consumer_sockpoll);
-
-extern int lttng_ustconsumer_allocate_channel(struct lttng_consumer_channel *chan);
-extern void lttng_ustconsumer_del_channel(struct lttng_consumer_channel *chan);
-extern void lttng_ustconsumer_free_channel(struct lttng_consumer_channel *chan);
-extern int lttng_ustconsumer_add_stream(struct lttng_consumer_stream *stream);
-extern void lttng_ustconsumer_del_stream(struct lttng_consumer_stream *stream);
-
-int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
-               struct lttng_consumer_local_data *ctx);
-int lttng_ustconsumer_on_recv_stream(struct lttng_consumer_stream *stream);
-
-void lttng_ustconsumer_on_stream_hangup(struct lttng_consumer_stream *stream);
-
-int lttng_ust_flush_buffer(struct lttng_consumer_stream *stream,
-               int producer_active);
-int lttng_ustconsumer_get_stream_id(struct lttng_consumer_stream *stream,
-               uint64_t *stream_id);
-int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream);
-void lttng_ustconsumer_close_all_metadata(struct lttng_ht *ht);
-void lttng_ustconsumer_close_metadata(struct lttng_consumer_channel *metadata);
-void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream);
-int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
-               uint64_t len, uint64_t version,
-               struct lttng_consumer_channel *channel, int timer, int wait);
-int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_channel *channel, int timer, int wait);
-enum sync_metadata_status lttng_ustconsumer_sync_metadata(
-               struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_stream *metadata);
-int lttng_ustconsumer_flush_buffer(struct lttng_consumer_stream *stream,
-               int producer);
-int lttng_ustconsumer_clear_buffer(struct lttng_consumer_stream *stream);
-int lttng_ustconsumer_get_current_timestamp(
-               struct lttng_consumer_stream *stream, uint64_t *ts);
-int lttng_ustconsumer_get_sequence_number(
-               struct lttng_consumer_stream *stream, uint64_t *seq);
-void lttng_ustconsumer_sigbus_handle(void *addr);
-
-#else /* HAVE_LIBLTTNG_UST_CTL */
-
-static inline
-ssize_t lttng_ustconsumer_on_read_subbuffer_mmap(
-               struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_stream *stream, unsigned long len,
-               unsigned long padding)
-{
-       return -ENOSYS;
-}
-
-static inline
-ssize_t lttng_ustconsumer_on_read_subbuffer_splice(
-               struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_stream *uststream, unsigned long len,
-               unsigned long padding)
-{
-       return -ENOSYS;
-}
-
-static inline
-int lttng_ustconsumer_take_snapshot(struct lttng_consumer_stream *stream)
-{
-       return -ENOSYS;
-}
-
-static inline
-int lttng_ustconsumer_sample_snapshot_positions(
-               struct lttng_consumer_stream *stream)
-{
-       return -ENOSYS;
-}
-
-static inline
-int lttng_ustconsumer_get_produced_snapshot(
-               struct lttng_consumer_stream *stream, unsigned long *pos)
-{
-       return -ENOSYS;
-}
-
-static inline
-int lttng_ustconsumer_get_consumed_snapshot(
-               struct lttng_consumer_stream *stream, unsigned long *pos)
-{
-       return -ENOSYS;
-}
-
-static inline
-int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
-               int sock, struct pollfd *consumer_sockpoll)
-{
-       return -ENOSYS;
-}
-
-static inline
-int lttng_ustconsumer_allocate_channel(struct lttng_consumer_channel *chan)
-{
-       return -ENOSYS;
-}
-
-static inline
-void lttng_ustconsumer_del_channel(struct lttng_consumer_channel *chan)
-{
-}
-
-static inline
-void lttng_ustconsumer_free_channel(struct lttng_consumer_channel *chan)
-{
-}
-
-static inline
-int lttng_ustconsumer_add_stream(struct lttng_consumer_stream *stream)
-{
-       return -ENOSYS;
-}
-
-static inline
-void lttng_ustconsumer_del_stream(struct lttng_consumer_stream *stream)
-{
-}
-
-static inline
-int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
-               struct lttng_consumer_local_data *ctx)
-{
-       return -ENOSYS;
-}
-
-static inline
-int lttng_ustconsumer_on_recv_stream(struct lttng_consumer_stream *stream)
-{
-       return -ENOSYS;
-}
-
-static inline
-void lttng_ustconsumer_on_stream_hangup(struct lttng_consumer_stream *stream)
-{
-}
-
-static inline
-int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream)
-{
-       return -ENOSYS;
-}
-static inline
-int lttng_ust_flush_buffer(struct lttng_consumer_stream *stream,
-               int producer_active)
-{
-       return -ENOSYS;
-}
-static inline
-void lttng_ustconsumer_close_all_metadata(struct lttng_ht *ht)
-{
-}
-static inline
-void lttng_ustconsumer_close_metadata(struct lttng_consumer_channel *metadata)
-{
-}
-static inline
-void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream)
-{
-}
-static inline
-int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
-               uint64_t len, uint64_t version,
-               struct lttng_consumer_channel *channel, int timer)
-{
-       return -ENOSYS;
-}
-static inline
-int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_channel *channel, int timer, int wait)
-{
-       return -ENOSYS;
-}
-static inline
-enum sync_metadata_status lttng_ustconsumer_sync_metadata(struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_stream *metadata)
-{
-       return SYNC_METADATA_STATUS_ERROR;
-}
-static inline
-int lttng_ustconsumer_flush_buffer(struct lttng_consumer_stream *stream,
-               int producer)
-{
-       return -ENOSYS;
-}
-static inline
-int lttng_ustconsumer_clear_buffer(struct lttng_consumer_stream *stream)
-{
-       return -ENOSYS;
-}
-static inline
-int lttng_ustconsumer_get_current_timestamp(
-               struct lttng_consumer_stream *stream, uint64_t *ts)
-{
-       return -ENOSYS;
-}
-static inline
-int lttng_ustconsumer_get_sequence_number(
-               struct lttng_consumer_stream *stream, uint64_t *seq)
-{
-       return -ENOSYS;
-}
-static inline
-int lttng_ustconsumer_get_stream_id(struct lttng_consumer_stream *stream,
-               uint64_t *stream_id)
-{
-       return -ENOSYS;
-}
-static inline
-void lttng_ustconsumer_sigbus_handle(void *addr)
-{
-}
-#endif /* HAVE_LIBLTTNG_UST_CTL */
-
-#endif /* _LTTNG_USTCONSUMER_H */
diff --git a/src/common/ust-consumer/ust-consumer.hpp b/src/common/ust-consumer/ust-consumer.hpp
new file mode 100644 (file)
index 0000000..18ea4fd
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _LTTNG_USTCONSUMER_H
+#define _LTTNG_USTCONSUMER_H
+
+#include <common/compat/errno.hpp>
+#include <common/consumer/consumer.hpp>
+#include <stdbool.h>
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+int lttng_ustconsumer_take_snapshot(struct lttng_consumer_stream *stream);
+int lttng_ustconsumer_sample_snapshot_positions(
+               struct lttng_consumer_stream *stream);
+
+int lttng_ustconsumer_get_produced_snapshot(
+               struct lttng_consumer_stream *stream, unsigned long *pos);
+int lttng_ustconsumer_get_consumed_snapshot(
+               struct lttng_consumer_stream *stream, unsigned long *pos);
+
+int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
+               int sock, struct pollfd *consumer_sockpoll);
+
+extern int lttng_ustconsumer_allocate_channel(struct lttng_consumer_channel *chan);
+extern void lttng_ustconsumer_del_channel(struct lttng_consumer_channel *chan);
+extern void lttng_ustconsumer_free_channel(struct lttng_consumer_channel *chan);
+extern int lttng_ustconsumer_add_stream(struct lttng_consumer_stream *stream);
+extern void lttng_ustconsumer_del_stream(struct lttng_consumer_stream *stream);
+
+int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
+               struct lttng_consumer_local_data *ctx);
+int lttng_ustconsumer_on_recv_stream(struct lttng_consumer_stream *stream);
+
+void lttng_ustconsumer_on_stream_hangup(struct lttng_consumer_stream *stream);
+
+int lttng_ust_flush_buffer(struct lttng_consumer_stream *stream,
+               int producer_active);
+int lttng_ustconsumer_get_stream_id(struct lttng_consumer_stream *stream,
+               uint64_t *stream_id);
+int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream);
+void lttng_ustconsumer_close_all_metadata(struct lttng_ht *ht);
+void lttng_ustconsumer_close_metadata(struct lttng_consumer_channel *metadata);
+void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream);
+int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
+               uint64_t len, uint64_t version,
+               struct lttng_consumer_channel *channel, int timer, int wait);
+int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_channel *channel, int timer, int wait);
+enum sync_metadata_status lttng_ustconsumer_sync_metadata(
+               struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_stream *metadata);
+int lttng_ustconsumer_flush_buffer(struct lttng_consumer_stream *stream,
+               int producer);
+int lttng_ustconsumer_clear_buffer(struct lttng_consumer_stream *stream);
+int lttng_ustconsumer_get_current_timestamp(
+               struct lttng_consumer_stream *stream, uint64_t *ts);
+int lttng_ustconsumer_get_sequence_number(
+               struct lttng_consumer_stream *stream, uint64_t *seq);
+void lttng_ustconsumer_sigbus_handle(void *addr);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+static inline
+ssize_t lttng_ustconsumer_on_read_subbuffer_mmap(
+               struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_stream *stream, unsigned long len,
+               unsigned long padding)
+{
+       return -ENOSYS;
+}
+
+static inline
+ssize_t lttng_ustconsumer_on_read_subbuffer_splice(
+               struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_stream *uststream, unsigned long len,
+               unsigned long padding)
+{
+       return -ENOSYS;
+}
+
+static inline
+int lttng_ustconsumer_take_snapshot(struct lttng_consumer_stream *stream)
+{
+       return -ENOSYS;
+}
+
+static inline
+int lttng_ustconsumer_sample_snapshot_positions(
+               struct lttng_consumer_stream *stream)
+{
+       return -ENOSYS;
+}
+
+static inline
+int lttng_ustconsumer_get_produced_snapshot(
+               struct lttng_consumer_stream *stream, unsigned long *pos)
+{
+       return -ENOSYS;
+}
+
+static inline
+int lttng_ustconsumer_get_consumed_snapshot(
+               struct lttng_consumer_stream *stream, unsigned long *pos)
+{
+       return -ENOSYS;
+}
+
+static inline
+int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
+               int sock, struct pollfd *consumer_sockpoll)
+{
+       return -ENOSYS;
+}
+
+static inline
+int lttng_ustconsumer_allocate_channel(struct lttng_consumer_channel *chan)
+{
+       return -ENOSYS;
+}
+
+static inline
+void lttng_ustconsumer_del_channel(struct lttng_consumer_channel *chan)
+{
+}
+
+static inline
+void lttng_ustconsumer_free_channel(struct lttng_consumer_channel *chan)
+{
+}
+
+static inline
+int lttng_ustconsumer_add_stream(struct lttng_consumer_stream *stream)
+{
+       return -ENOSYS;
+}
+
+static inline
+void lttng_ustconsumer_del_stream(struct lttng_consumer_stream *stream)
+{
+}
+
+static inline
+int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
+               struct lttng_consumer_local_data *ctx)
+{
+       return -ENOSYS;
+}
+
+static inline
+int lttng_ustconsumer_on_recv_stream(struct lttng_consumer_stream *stream)
+{
+       return -ENOSYS;
+}
+
+static inline
+void lttng_ustconsumer_on_stream_hangup(struct lttng_consumer_stream *stream)
+{
+}
+
+static inline
+int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream)
+{
+       return -ENOSYS;
+}
+static inline
+int lttng_ust_flush_buffer(struct lttng_consumer_stream *stream,
+               int producer_active)
+{
+       return -ENOSYS;
+}
+static inline
+void lttng_ustconsumer_close_all_metadata(struct lttng_ht *ht)
+{
+}
+static inline
+void lttng_ustconsumer_close_metadata(struct lttng_consumer_channel *metadata)
+{
+}
+static inline
+void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream)
+{
+}
+static inline
+int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
+               uint64_t len, uint64_t version,
+               struct lttng_consumer_channel *channel, int timer)
+{
+       return -ENOSYS;
+}
+static inline
+int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_channel *channel, int timer, int wait)
+{
+       return -ENOSYS;
+}
+static inline
+enum sync_metadata_status lttng_ustconsumer_sync_metadata(struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_stream *metadata)
+{
+       return SYNC_METADATA_STATUS_ERROR;
+}
+static inline
+int lttng_ustconsumer_flush_buffer(struct lttng_consumer_stream *stream,
+               int producer)
+{
+       return -ENOSYS;
+}
+static inline
+int lttng_ustconsumer_clear_buffer(struct lttng_consumer_stream *stream)
+{
+       return -ENOSYS;
+}
+static inline
+int lttng_ustconsumer_get_current_timestamp(
+               struct lttng_consumer_stream *stream, uint64_t *ts)
+{
+       return -ENOSYS;
+}
+static inline
+int lttng_ustconsumer_get_sequence_number(
+               struct lttng_consumer_stream *stream, uint64_t *seq)
+{
+       return -ENOSYS;
+}
+static inline
+int lttng_ustconsumer_get_stream_id(struct lttng_consumer_stream *stream,
+               uint64_t *stream_id)
+{
+       return -ENOSYS;
+}
+static inline
+void lttng_ustconsumer_sigbus_handle(void *addr)
+{
+}
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* _LTTNG_USTCONSUMER_H */
index 93014627fe5162bf8d49c4813074debe3edf1ca7..780e39938cb0f8eed7cc5788b04b54ebea5c91cf 100644 (file)
@@ -7,7 +7,7 @@
  *
  */
 
-#include "common/macros.h"
+#include "common/macros.hpp"
 #define _LGPL_SOURCE
 #include <ctype.h>
 #include <fcntl.h>
 #include <sys/file.h>
 #include <unistd.h>
 
-#include <common/common.h>
-#include <common/readwrite.h>
-#include <common/runas.h>
-#include <common/compat/getenv.h>
-#include <common/compat/string.h>
-#include <common/compat/dirent.h>
-#include <common/compat/directory-handle.h>
-#include <common/dynamic-buffer.h>
-#include <common/string-utils/format.h>
+#include <common/common.hpp>
+#include <common/readwrite.hpp>
+#include <common/runas.hpp>
+#include <common/compat/getenv.hpp>
+#include <common/compat/string.hpp>
+#include <common/compat/dirent.hpp>
+#include <common/compat/directory-handle.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/string-utils/format.hpp>
 #include <lttng/constant.h>
 
-#include "utils.h"
-#include "defaults.h"
-#include "time.h"
+#include "utils.hpp"
+#include "defaults.hpp"
+#include "time.hpp"
 
 #define PROC_MEMINFO_PATH               "/proc/meminfo"
 #define PROC_MEMINFO_MEMAVAILABLE_LINE  "MemAvailable:"
diff --git a/src/common/utils.h b/src/common/utils.h
deleted file mode 100644 (file)
index beca1fb..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#ifndef _COMMON_UTILS_H
-#define _COMMON_UTILS_H
-
-#include <getopt.h>
-#include <lttng/lttng-error.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <common/compat/directory-handle.h>
-
-#define KIBI_LOG2 10
-#define MEBI_LOG2 20
-#define GIBI_LOG2 30
-
-char *utils_expand_path(const char *path);
-char *utils_expand_path_keep_symlink(const char *path);
-int utils_create_pipe(int *dst);
-int utils_create_pipe_cloexec(int *dst);
-int utils_create_pipe_cloexec_nonblock(int *dst);
-void utils_close_pipe(int *src);
-char *utils_strdupdelim(const char *begin, const char *end);
-int utils_set_fd_cloexec(int fd);
-int utils_create_pid_file(pid_t pid, const char *filepath);
-int utils_mkdir(const char *path, mode_t mode, int uid, int gid);
-int utils_mkdir_recursive(const char *path, mode_t mode, int uid, int gid);
-int utils_stream_file_path(const char *path_name, const char *file_name,
-               uint64_t size, uint64_t count, const char *suffix,
-               char *out_stream_path, size_t stream_path_len);
-int utils_parse_size_suffix(char const * const str, uint64_t * const size);
-int utils_parse_time_suffix(char const * const str, uint64_t * const time_us);
-int utils_get_count_order_u32(uint32_t x);
-int utils_get_count_order_u64(uint64_t x);
-const char *utils_get_home_dir(void);
-char *utils_get_user_home_dir(uid_t uid);
-
-size_t utils_get_current_time_str(const char *format, char *dst, size_t len)
-       ATTR_FORMAT_STRFTIME(1);
-
-int utils_get_group_id(const char *name, bool warn, gid_t *gid);
-char *utils_generate_optstring(const struct option *long_options,
-               size_t opt_count);
-int utils_create_lock_file(const char *filepath);
-int utils_recursive_rmdir(const char *path);
-int utils_truncate_stream_file(int fd, off_t length);
-int utils_show_help(int section, const char *page_name, const char *help_msg);
-int utils_get_memory_available(size_t *value);
-int utils_get_memory_total(size_t *value);
-int utils_change_working_directory(const char *path);
-enum lttng_error_code utils_user_id_from_name(
-               const char *user_name, uid_t *user_id);
-enum lttng_error_code utils_group_id_from_name(
-               const char *group_name, gid_t *group_id);
-
-/*
- * Parse `str` as an unsigned long long value.
- *
- * Return 0 on success.  Return -1 on failure which can be because:
- *
- * - `str` is zero length
- * - `str` contains invalid
- */
-int utils_parse_unsigned_long_long(const char *str,
-               unsigned long long *value);
-
-#endif /* _COMMON_UTILS_H */
diff --git a/src/common/utils.hpp b/src/common/utils.hpp
new file mode 100644 (file)
index 0000000..2d6b5bf
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef _COMMON_UTILS_H
+#define _COMMON_UTILS_H
+
+#include <getopt.h>
+#include <lttng/lttng-error.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <common/compat/directory-handle.hpp>
+
+#define KIBI_LOG2 10
+#define MEBI_LOG2 20
+#define GIBI_LOG2 30
+
+char *utils_expand_path(const char *path);
+char *utils_expand_path_keep_symlink(const char *path);
+int utils_create_pipe(int *dst);
+int utils_create_pipe_cloexec(int *dst);
+int utils_create_pipe_cloexec_nonblock(int *dst);
+void utils_close_pipe(int *src);
+char *utils_strdupdelim(const char *begin, const char *end);
+int utils_set_fd_cloexec(int fd);
+int utils_create_pid_file(pid_t pid, const char *filepath);
+int utils_mkdir(const char *path, mode_t mode, int uid, int gid);
+int utils_mkdir_recursive(const char *path, mode_t mode, int uid, int gid);
+int utils_stream_file_path(const char *path_name, const char *file_name,
+               uint64_t size, uint64_t count, const char *suffix,
+               char *out_stream_path, size_t stream_path_len);
+int utils_parse_size_suffix(char const * const str, uint64_t * const size);
+int utils_parse_time_suffix(char const * const str, uint64_t * const time_us);
+int utils_get_count_order_u32(uint32_t x);
+int utils_get_count_order_u64(uint64_t x);
+const char *utils_get_home_dir(void);
+char *utils_get_user_home_dir(uid_t uid);
+
+size_t utils_get_current_time_str(const char *format, char *dst, size_t len)
+       ATTR_FORMAT_STRFTIME(1);
+
+int utils_get_group_id(const char *name, bool warn, gid_t *gid);
+char *utils_generate_optstring(const struct option *long_options,
+               size_t opt_count);
+int utils_create_lock_file(const char *filepath);
+int utils_recursive_rmdir(const char *path);
+int utils_truncate_stream_file(int fd, off_t length);
+int utils_show_help(int section, const char *page_name, const char *help_msg);
+int utils_get_memory_available(size_t *value);
+int utils_get_memory_total(size_t *value);
+int utils_change_working_directory(const char *path);
+enum lttng_error_code utils_user_id_from_name(
+               const char *user_name, uid_t *user_id);
+enum lttng_error_code utils_group_id_from_name(
+               const char *group_name, gid_t *group_id);
+
+/*
+ * Parse `str` as an unsigned long long value.
+ *
+ * Return 0 on success.  Return -1 on failure which can be because:
+ *
+ * - `str` is zero length
+ * - `str` contains invalid
+ */
+int utils_parse_unsigned_long_long(const char *str,
+               unsigned long long *value);
+
+#endif /* _COMMON_UTILS_H */
index 77b9a767bececffe3210255c9d8c11f1dc9a086d..558110fc0e9e7e46b6d75f44978dfad0944c7454 100644 (file)
@@ -6,7 +6,7 @@
  *
  */
 
-#include <common/compat/string.h>
+#include <common/compat/string.hpp>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -14,7 +14,7 @@
 #include <string.h>
 #include <time.h>
 
-#include "uuid.h"
+#include "uuid.hpp"
 
 static const lttng_uuid nil_uuid = { 0 };
 static bool lttng_uuid_is_init;
diff --git a/src/common/uuid.h b/src/common/uuid.h
deleted file mode 100644 (file)
index 0d3e79a..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: MIT
- *
- */
-
-#ifndef LTTNG_UUID_H
-#define LTTNG_UUID_H
-
-#include <common/macros.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <inttypes.h>
-
-/*
- * Includes final \0.
- */
-#define LTTNG_UUID_STR_LEN     37
-#define LTTNG_UUID_LEN         16
-#define LTTNG_UUID_VER         4
-
-#define LTTNG_UUID_FMT \
-       "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "-%02" SCNx8 \
-       "%02" SCNx8 "-%02" SCNx8 "%02" SCNx8 "-%02" SCNx8 "%02" SCNx8 \
-       "-%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 \
-       "%02" SCNx8
-
-#define LTTNG_UUID_FMT_VALUES(uuid) \
-       (uuid)[0], (uuid)[1], (uuid)[2], (uuid)[3], (uuid)[4], (uuid)[5], \
-       (uuid)[6], (uuid)[7], (uuid)[8], (uuid)[9], (uuid)[10], (uuid)[11], \
-       (uuid)[12], (uuid)[13], (uuid)[14], (uuid)[15]
-
-#define LTTNG_UUID_SCAN_VALUES(uuid) \
-       &(uuid)[0], &(uuid)[1], &(uuid)[2], &(uuid)[3], &(uuid)[4], &(uuid)[5], \
-       &(uuid)[6], &(uuid)[7], &(uuid)[8], &(uuid)[9], &(uuid)[10], &(uuid)[11], \
-       &(uuid)[12], &(uuid)[13], &(uuid)[14], &(uuid)[15]
-
-typedef uint8_t lttng_uuid[LTTNG_UUID_LEN];
-
-int lttng_uuid_from_str(const char *str_in, lttng_uuid uuid_out);
-
-/*
- * Convert a UUID to a human-readable, NULL-terminated, string of the form
- * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
- *
- * Assumes uuid_str is at least LTTNG_UUID_STR_LEN byte long.
- */
-void lttng_uuid_to_str(const lttng_uuid uuid, char *uuid_str);
-
-bool lttng_uuid_is_equal(const lttng_uuid a, const lttng_uuid b);
-
-bool lttng_uuid_is_nil(const lttng_uuid uuid);
-
-void lttng_uuid_copy(lttng_uuid dst, const lttng_uuid src);
-
-/*
- * Generate a random UUID according to RFC4122, section 4.4.
- */
-int lttng_uuid_generate(lttng_uuid uuid_out);
-
-#endif /* LTTNG_UUID_H */
diff --git a/src/common/uuid.hpp b/src/common/uuid.hpp
new file mode 100644 (file)
index 0000000..181d343
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef LTTNG_UUID_H
+#define LTTNG_UUID_H
+
+#include <array>
+#include <common/macros.hpp>
+#include <stdbool.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+/*
+ * Includes final \0.
+ */
+#define LTTNG_UUID_STR_LEN     37
+#define LTTNG_UUID_LEN         16
+#define LTTNG_UUID_VER         4
+
+#define LTTNG_UUID_FMT \
+       "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "-%02" SCNx8 \
+       "%02" SCNx8 "-%02" SCNx8 "%02" SCNx8 "-%02" SCNx8 "%02" SCNx8 \
+       "-%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 \
+       "%02" SCNx8
+
+#define LTTNG_UUID_FMT_VALUES(uuid) \
+       (uuid)[0], (uuid)[1], (uuid)[2], (uuid)[3], (uuid)[4], (uuid)[5], \
+       (uuid)[6], (uuid)[7], (uuid)[8], (uuid)[9], (uuid)[10], (uuid)[11], \
+       (uuid)[12], (uuid)[13], (uuid)[14], (uuid)[15]
+
+#define LTTNG_UUID_SCAN_VALUES(uuid) \
+       &(uuid)[0], &(uuid)[1], &(uuid)[2], &(uuid)[3], &(uuid)[4], &(uuid)[5], \
+       &(uuid)[6], &(uuid)[7], &(uuid)[8], &(uuid)[9], &(uuid)[10], &(uuid)[11], \
+       &(uuid)[12], &(uuid)[13], &(uuid)[14], &(uuid)[15]
+
+typedef uint8_t lttng_uuid[LTTNG_UUID_LEN];
+
+int lttng_uuid_from_str(const char *str_in, lttng_uuid uuid_out);
+
+/*
+ * Convert a UUID to a human-readable, NULL-terminated, string of the form
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
+ *
+ * Assumes uuid_str is at least LTTNG_UUID_STR_LEN byte long.
+ */
+void lttng_uuid_to_str(const lttng_uuid uuid, char *uuid_str);
+
+bool lttng_uuid_is_equal(const lttng_uuid a, const lttng_uuid b);
+
+bool lttng_uuid_is_nil(const lttng_uuid uuid);
+
+void lttng_uuid_copy(lttng_uuid dst, const lttng_uuid src);
+
+/*
+ * Generate a random UUID according to RFC4122, section 4.4.
+ */
+int lttng_uuid_generate(lttng_uuid uuid_out);
+
+#endif /* LTTNG_UUID_H */
index aca88eb4db75ade4fa28b971d4616be68bd92742..3ddb68feb7c76dd91f09bec9d7664c02224627a2 100644 (file)
@@ -6,10 +6,10 @@
  *
  */
 
-#include "waiter.h"
+#include "waiter.hpp"
 #include <urcu/uatomic.h>
 #include <urcu/futex.h>
-#include "error.h"
+#include "error.hpp"
 #include <poll.h>
 
 /*
diff --git a/src/common/waiter.h b/src/common/waiter.h
deleted file mode 100644 (file)
index ed870ae..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- * This code is originally adapted from userspace-rcu's urcu-wait.h
- */
-
-#ifndef LTTNG_WAITER_H
-#define LTTNG_WAITER_H
-
-#define _LGPL_SOURCE
-
-#include <stdint.h>
-#include <urcu/wfstack.h>
-#include <stdbool.h>
-#include "macros.h"
-
-struct lttng_waiter {
-       struct cds_wfs_node wait_queue_node;
-       int32_t state;
-};
-
-void lttng_waiter_init(struct lttng_waiter *waiter);
-
-void lttng_waiter_wait(struct lttng_waiter *waiter);
-
-/*
- * lttng_waiter_wake_up must only be called by a single waker.
- * It is invalid for multiple "wake" operations to be invoked
- * on a single waiter without re-initializing it before.
- */
-void lttng_waiter_wake_up(struct lttng_waiter *waiter);
-
-#endif /* LTTNG_WAITER_H */
diff --git a/src/common/waiter.hpp b/src/common/waiter.hpp
new file mode 100644 (file)
index 0000000..75c9ac4
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * This code is originally adapted from userspace-rcu's urcu-wait.h
+ */
+
+#ifndef LTTNG_WAITER_H
+#define LTTNG_WAITER_H
+
+#define _LGPL_SOURCE
+
+#include <stdint.h>
+#include <urcu/wfstack.h>
+#include <stdbool.h>
+#include "macros.hpp"
+
+struct lttng_waiter {
+       struct cds_wfs_node wait_queue_node;
+       int32_t state;
+};
+
+void lttng_waiter_init(struct lttng_waiter *waiter);
+
+void lttng_waiter_wait(struct lttng_waiter *waiter);
+
+/*
+ * lttng_waiter_wake_up must only be called by a single waker.
+ * It is invalid for multiple "wake" operations to be invoked
+ * on a single waiter without re-initializing it before.
+ */
+void lttng_waiter_wake_up(struct lttng_waiter *waiter);
+
+#endif /* LTTNG_WAITER_H */
index b31e5bd6f819e79f6b45caa10a659bfe37de4a8a..3645cbb16863a229611e5bec6d5c38fde64621d0 100644 (file)
@@ -15,7 +15,7 @@ liblttng_ctl_la_SOURCES = \
                load.cpp \
                lttng-ctl.cpp \
                lttng-ctl-health.cpp \
-               lttng-ctl-helper.h \
+               lttng-ctl-helper.hpp \
                rotate.cpp \
                save.cpp \
                snapshot.cpp \
@@ -30,7 +30,7 @@ EXTRA_liblttng_ctl_la_DEPENDENCIES = liblttng-ctl.sym
 EXTRA_DIST = liblttng-ctl.sym
 
 liblttng_ctl_la_LIBADD = \
-               $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \
+               $(top_builddir)/src/common/libsessiond-comm.la \
                $(top_builddir)/src/common/libcommon.la
 
 pkgconfigdir = $(libdir)/pkgconfig
index e7b044ac05aafad89f3ff9af02e611619b8b8b3c..b8fae9b1bdee58cdf02d4f23682b3146e8fce9fd 100644 (file)
@@ -5,20 +5,20 @@
  *
  */
 
-#include <lttng/notification/notification-internal.h>
-#include <lttng/notification/channel-internal.h>
-#include <lttng/condition/condition-internal.h>
+#include <lttng/notification/notification-internal.hpp>
+#include <lttng/notification/channel-internal.hpp>
+#include <lttng/condition/condition-internal.hpp>
 #include <lttng/endpoint.h>
-#include <common/defaults.h>
-#include <common/error.h>
-#include <common/dynamic-buffer.h>
-#include <common/utils.h>
-#include <common/defaults.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
-#include <common/unix.h>
-#include "lttng-ctl-helper.h"
-#include <common/compat/poll.h>
+#include <common/defaults.hpp>
+#include <common/error.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/utils.hpp>
+#include <common/defaults.hpp>
+#include <common/payload.hpp>
+#include <common/payload-view.hpp>
+#include <common/unix.hpp>
+#include "lttng-ctl-helper.hpp"
+#include <common/compat/poll.hpp>
 
 static
 int handshake(struct lttng_notification_channel *channel);
index 0eaf97364ce9c14f8c02fdd4b48e945b7d1ab81b..8595b2040b0928adfa5335125c2e431e66856dd7 100644 (file)
 #include <lttng/lttng-error.h>
 #include <lttng/clear.h>
 #include <lttng/clear-handle.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/macros.h>
-#include <common/compat/poll.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <common/optional.h>
-
-#include "lttng-ctl-helper.h"
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/macros.hpp>
+#include <common/compat/poll.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/buffer-view.hpp>
+#include <common/optional.hpp>
+
+#include "lttng-ctl-helper.hpp"
 
 enum communication_state {
        COMMUNICATION_STATE_RECEIVE_LTTNG_MSG,
index 35a1c358225376de7c7a3fa5de1614a93e8c9312..4d48c88bef24bddcd02fccceddfb24f06b886105 100644 (file)
@@ -8,16 +8,16 @@
 #include <lttng/destruction-handle.h>
 #include <lttng/rotation.h>
 
-#include <common/optional.h>
-#include <common/compat/poll.h>
-#include <common/compat/time.h>
-#include <common/macros.h>
-#include <common/compat/poll.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/location-internal.h>
-#include "lttng-ctl-helper.h"
+#include <common/optional.hpp>
+#include <common/compat/poll.hpp>
+#include <common/compat/time.hpp>
+#include <common/macros.hpp>
+#include <common/compat/poll.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/buffer-view.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <lttng/location-internal.hpp>
+#include "lttng-ctl-helper.hpp"
 
 #include <algorithm>
 #include <stdbool.h>
index 3a6bf22b2ec90987014acd5f085230d04fdf638e..e89aae4829464d4fed25d70354c41b64df40365d 100644 (file)
 #define _LGPL_SOURCE
 #include <stddef.h>
 
-#include <common/error.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/event-internal.h>
+#include <common/error.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <lttng/event-internal.hpp>
 #include <lttng/event.h>
 #include <lttng/lttng-error.h>
-#include <lttng/userspace-probe-internal.h>
+#include <lttng/userspace-probe-internal.hpp>
 
 struct lttng_event *lttng_event_create(void)
 {
index 0032df5697fd0ae2b591096800450ce7f31987c9..4a07f4212a463439ec80a1986b1fc9ea720c0ff6 100644 (file)
 
 #include <lttng/lttng-error.h>
 #include <lttng/load.h>
-#include <lttng/load-internal.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/config/session-config.h>
-#include <common/uri.h>
-#include <common/macros.h>
-#include <common/compat/string.h>
-
-#include "lttng-ctl-helper.h"
+#include <lttng/load-internal.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/config/session-config.hpp>
+#include <common/uri.hpp>
+#include <common/macros.hpp>
+#include <common/compat/string.hpp>
+
+#include "lttng-ctl-helper.hpp"
 
 struct lttng_load_session_attr *lttng_load_session_attr_create(void)
 {
index 8a703b019e14b04a8536aa26dc9d35c28c98fb66..1ec83fb234802fd026e921b60b9bd752de30aaa4 100644 (file)
 #include <stdint.h>
 #include <limits.h>
 #include <string.h>
-#include <lttng/health-internal.h>
+#include <lttng/health-internal.hpp>
 
-#include <bin/lttng-sessiond/health-sessiond.h>
-#include <bin/lttng-consumerd/health-consumerd.h>
-#include <bin/lttng-relayd/health-relayd.h>
-#include <common/defaults.h>
-#include <common/utils.h>
-#include <common/compat/errno.h>
+#include <bin/lttng-sessiond/health-sessiond.hpp>
+#include <bin/lttng-consumerd/health-consumerd.hpp>
+#include <bin/lttng-relayd/health-relayd.hpp>
+#include <common/defaults.hpp>
+#include <common/utils.hpp>
+#include <common/compat/errno.hpp>
 
-#include "lttng-ctl-helper.h"
+#include "lttng-ctl-helper.hpp"
 
 enum health_component {
        HEALTH_COMPONENT_SESSIOND,
diff --git a/src/lib/lttng-ctl/lttng-ctl-helper.h b/src/lib/lttng-ctl/lttng-ctl-helper.h
deleted file mode 100644 (file)
index 64e659d..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_CTL_HELPER_H
-#define LTTNG_CTL_HELPER_H
-
-#include <stdio.h>
-
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/lttng.h>
-
-/* Copy helper functions. */
-void lttng_ctl_copy_lttng_domain(struct lttng_domain *dst,
-               struct lttng_domain *src);
-
-/*
- * Sends the lttcomm message to the session daemon and fills buf if the
- * returned data is not NULL.
- *
- * Return the size of the received data on success or else a negative lttng
- * error code. If buf is NULL, 0 is returned on success.
- */
-int lttng_ctl_ask_sessiond_fds_varlen(struct lttcomm_session_msg *lsm,
-               const int *fds, size_t nb_fd,
-               const void *vardata, size_t vardata_len,
-               void **user_payload_buf, void **user_cmd_header_buf,
-               size_t *user_cmd_header_len);
-
-/*
- * Sends the lttcomm message to the session daemon and fills the reply payload.
- *
- * Return the size of the received data on success or else a negative lttng
- * error code.
- */
-int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
-               struct lttng_payload *reply);
-
-/*
- * Calls lttng_ctl_ask_sessiond_fds_varlen() with no expected command header.
- */
-static inline int lttng_ctl_ask_sessiond_varlen_no_cmd_header(
-               struct lttcomm_session_msg *lsm,
-               const void *vardata,
-               size_t vardata_len,
-               void **user_payload_buf)
-{
-       return lttng_ctl_ask_sessiond_fds_varlen(lsm, NULL, 0, vardata,
-               vardata_len, user_payload_buf, NULL, NULL);
-}
-
-/*
- * Calls lttng_ctl_ask_sessiond_fds_varlen() with fds and no expected command header.
- */
-static inline
-int lttng_ctl_ask_sessiond_fds_no_cmd_header(struct lttcomm_session_msg *lsm,
-               const int *fds, size_t nb_fd, void **buf)
-{
-       return lttng_ctl_ask_sessiond_fds_varlen(lsm, fds, nb_fd, NULL,
-               0, NULL, NULL, NULL);
-}
-/*
- * Use this if no variable length data needs to be sent.
- */
-static inline
-int lttng_ctl_ask_sessiond(struct lttcomm_session_msg *lsm, void **buf)
-{
-       return lttng_ctl_ask_sessiond_varlen_no_cmd_header(lsm, NULL, 0, buf);
-}
-
-int lttng_check_tracing_group(void);
-
-int connect_sessiond(void);
-
-#endif /* LTTNG_CTL_HELPER_H */
diff --git a/src/lib/lttng-ctl/lttng-ctl-helper.hpp b/src/lib/lttng-ctl/lttng-ctl-helper.hpp
new file mode 100644 (file)
index 0000000..eb0cb97
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CTL_HELPER_H
+#define LTTNG_CTL_HELPER_H
+
+#include <stdio.h>
+
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <lttng/lttng.h>
+
+/* Copy helper functions. */
+void lttng_ctl_copy_lttng_domain(struct lttng_domain *dst,
+               struct lttng_domain *src);
+
+/*
+ * Sends the lttcomm message to the session daemon and fills buf if the
+ * returned data is not NULL.
+ *
+ * Return the size of the received data on success or else a negative lttng
+ * error code. If buf is NULL, 0 is returned on success.
+ */
+int lttng_ctl_ask_sessiond_fds_varlen(struct lttcomm_session_msg *lsm,
+               const int *fds, size_t nb_fd,
+               const void *vardata, size_t vardata_len,
+               void **user_payload_buf, void **user_cmd_header_buf,
+               size_t *user_cmd_header_len);
+
+/*
+ * Sends the lttcomm message to the session daemon and fills the reply payload.
+ *
+ * Return the size of the received data on success or else a negative lttng
+ * error code.
+ */
+int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
+               struct lttng_payload *reply);
+
+/*
+ * Calls lttng_ctl_ask_sessiond_fds_varlen() with no expected command header.
+ */
+static inline int lttng_ctl_ask_sessiond_varlen_no_cmd_header(
+               struct lttcomm_session_msg *lsm,
+               const void *vardata,
+               size_t vardata_len,
+               void **user_payload_buf)
+{
+       return lttng_ctl_ask_sessiond_fds_varlen(lsm, NULL, 0, vardata,
+               vardata_len, user_payload_buf, NULL, NULL);
+}
+
+/*
+ * Calls lttng_ctl_ask_sessiond_fds_varlen() with fds and no expected command header.
+ */
+static inline
+int lttng_ctl_ask_sessiond_fds_no_cmd_header(struct lttcomm_session_msg *lsm,
+               const int *fds, size_t nb_fd, void **buf)
+{
+       return lttng_ctl_ask_sessiond_fds_varlen(lsm, fds, nb_fd, NULL,
+               0, NULL, NULL, NULL);
+}
+/*
+ * Use this if no variable length data needs to be sent.
+ */
+static inline
+int lttng_ctl_ask_sessiond(struct lttcomm_session_msg *lsm, void **buf)
+{
+       return lttng_ctl_ask_sessiond_varlen_no_cmd_header(lsm, NULL, 0, buf);
+}
+
+int lttng_check_tracing_group(void);
+
+int connect_sessiond(void);
+
+#endif /* LTTNG_CTL_HELPER_H */
index b7eaee2602bc10540fd5d9902f0781888de0c33a..fab222d6a125f382c0b85829c4d79979f2ea9545 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
-#include <common/bytecode/bytecode.h>
-#include <common/align.h>
-#include <common/common.h>
-#include <common/compat/errno.h>
-#include <common/compat/string.h>
-#include <common/defaults.h>
-#include <common/dynamic-array.h>
-#include <common/dynamic-buffer.h>
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/tracker.h>
-#include <common/unix.h>
-#include <common/uri.h>
-#include <common/utils.h>
-#include <lttng/channel-internal.h>
+#include <common/bytecode/bytecode.hpp>
+#include <common/align.hpp>
+#include <common/common.hpp>
+#include <common/compat/errno.hpp>
+#include <common/compat/string.hpp>
+#include <common/defaults.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/dynamic-buffer.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/tracker.hpp>
+#include <common/unix.hpp>
+#include <common/uri.hpp>
+#include <common/utils.hpp>
+#include <lttng/channel-internal.hpp>
 #include <lttng/destruction-handle.h>
 #include <lttng/endpoint.h>
-#include <lttng/error-query-internal.h>
-#include <lttng/event-internal.h>
-#include <lttng/health-internal.h>
+#include <lttng/error-query-internal.hpp>
+#include <lttng/event-internal.hpp>
+#include <lttng/health-internal.hpp>
 #include <lttng/lttng-error.h>
 #include <lttng/lttng.h>
-#include <lttng/session-descriptor-internal.h>
-#include <lttng/session-internal.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/userspace-probe-internal.h>
+#include <lttng/session-descriptor-internal.hpp>
+#include <lttng/session-internal.hpp>
+#include <lttng/trigger/trigger-internal.hpp>
+#include <lttng/userspace-probe-internal.hpp>
 
-#include "lttng-ctl-helper.h"
-#include <common/filter/filter-ast.h>
+#include "lttng-ctl-helper.hpp"
+#include <common/filter/filter-ast.hpp>
 #include <common/filter/filter-parser.hpp>
-#include <common/filter/memstream.h>
+#include <common/filter/memstream.hpp>
 
 #define COPY_DOMAIN_PACKED(dst, src)                           \
 do {                                                           \
index 6a003a18ec101f1b0a3aa13eaaf5027c8df2c987..66534d472fc02181018b618bce0bf09520f0af06 100644 (file)
 
 #include <lttng/lttng-error.h>
 #include <lttng/rotation.h>
-#include <lttng/location-internal.h>
-#include <lttng/rotate-internal.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/macros.h>
+#include <lttng/location-internal.hpp>
+#include <lttng/rotate-internal.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/macros.hpp>
 
-#include "lttng-ctl-helper.h"
+#include "lttng-ctl-helper.hpp"
 
 static
 enum lttng_rotation_status ask_rotation_info(
index 45894277a04c15f47b480ac2a9c13fa69e0fee0a..7843df300699afded1d46ed8da083f60d8fc4c49 100644 (file)
 
 #include <lttng/lttng-error.h>
 #include <lttng/save.h>
-#include <lttng/save-internal.h>
-#include <common/sessiond-comm/sessiond-comm.h>
+#include <lttng/save-internal.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
 
-#include "lttng-ctl-helper.h"
+#include "lttng-ctl-helper.hpp"
 
 struct lttng_save_session_attr *lttng_save_session_attr_create(void)
 {
index 543861d676d4639bb52cf9ac494f263d7317592e..8d0a1fee0e5b27aff94841ff5ddbf01e92e57bbd 100644 (file)
@@ -8,12 +8,12 @@
 #define _LGPL_SOURCE
 #include <string.h>
 
-#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
 #include <lttng/lttng-error.h>
 #include <lttng/snapshot.h>
-#include <lttng/snapshot-internal.h>
+#include <lttng/snapshot-internal.hpp>
 
-#include "lttng-ctl-helper.h"
+#include "lttng-ctl-helper.hpp"
 
 /*
  * Add an output object to a session identified by name.
index b9c8ed8c38d63195bdb0693dfeff28bc41ce42e0..12d1f7787439abd1af57f473b759730959a83c0f 100644 (file)
@@ -5,12 +5,13 @@
  *
  */
 
-#include "lttng-ctl-helper.h"
+#include "lttng-ctl-helper.hpp"
 #include "lttng/domain.h"
 #include "lttng/lttng-error.h"
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/tracker.h>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/tracker.hpp>
 #include <lttng/tracker.h>
+#include <type_traits>
 
 struct lttng_process_attr_tracker_handle {
        char *session_name;
@@ -217,7 +218,7 @@ end:
                                .value_type = (uint32_t)                                                             \
                                LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum;                                     \
                                                                                                                      \
-               if (is_signed(value_type_c)) {                                                                       \
+               if (std::is_signed<value_type_c>::value) {                                                           \
                        lsm.u.process_attr_tracker_add_remove_include_value                                          \
                                        .integral_value.u._signed = value;                                           \
                } else {                                                                                             \
index 073bf8da591bde77777bd95b88646265780d1567..0a8c27008e11c46322d77ad5e431347674fc2d17 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef MSGPACK_LTTNG_CONFIG_H
 #define MSGPACK_LTTNG_CONFIG_H
 
-#include <common/compat/endian.h>
+#include <common/compat/endian.hpp>
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define MSGPACK_ENDIAN_LITTLE_BYTE 1
diff --git a/src/vendor/nlohmann/json.hpp b/src/vendor/nlohmann/json.hpp
new file mode 100644 (file)
index 0000000..5800976
--- /dev/null
@@ -0,0 +1,26750 @@
+/*
+    __ _____ _____ _____
+ __|  |   __|     |   | |  JSON for Modern C++
+|  |  |__   |  |  | | | |  version 3.10.4
+|_____|_____|_____|_|___|  https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
+Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
+
+Permission is hereby  granted, free of charge, to any  person obtaining a copy
+of this software and associated  documentation files (the "Software"), to deal
+in the Software  without restriction, including without  limitation the rights
+to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
+copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
+IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
+FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
+AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
+LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef INCLUDE_NLOHMANN_JSON_HPP_
+#define INCLUDE_NLOHMANN_JSON_HPP_
+
+#define NLOHMANN_JSON_VERSION_MAJOR 3
+#define NLOHMANN_JSON_VERSION_MINOR 10
+#define NLOHMANN_JSON_VERSION_PATCH 4
+
+#include <algorithm> // all_of, find, for_each
+#include <cstddef> // nullptr_t, ptrdiff_t, size_t
+#include <functional> // hash, less
+#include <initializer_list> // initializer_list
+#ifndef JSON_NO_IO
+    #include <iosfwd> // istream, ostream
+#endif  // JSON_NO_IO
+#include <iterator> // random_access_iterator_tag
+#include <memory> // unique_ptr
+#include <numeric> // accumulate
+#include <string> // string, stoi, to_string
+#include <utility> // declval, forward, move, pair, swap
+#include <vector> // vector
+
+// #include <nlohmann/adl_serializer.hpp>
+
+
+#include <type_traits>
+#include <utility>
+
+// #include <nlohmann/detail/conversions/from_json.hpp>
+
+
+#include <algorithm> // transform
+#include <array> // array
+#include <forward_list> // forward_list
+#include <iterator> // inserter, front_inserter, end
+#include <map> // map
+#include <string> // string
+#include <tuple> // tuple, make_tuple
+#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
+#include <unordered_map> // unordered_map
+#include <utility> // pair, declval
+#include <valarray> // valarray
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+
+#include <exception> // exception
+#include <stdexcept> // runtime_error
+#include <string> // to_string
+#include <vector> // vector
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+#include <array> // array
+#include <cstddef> // size_t
+#include <cstdint> // uint8_t
+#include <string> // string
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////////////
+// JSON type enumeration //
+///////////////////////////
+
+/*!
+@brief the JSON type enumeration
+
+This enumeration collects the different JSON types. It is internally used to
+distinguish the stored values, and the functions @ref basic_json::is_null(),
+@ref basic_json::is_object(), @ref basic_json::is_array(),
+@ref basic_json::is_string(), @ref basic_json::is_boolean(),
+@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
+@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
+@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
+@ref basic_json::is_structured() rely on it.
+
+@note There are three enumeration entries (number_integer, number_unsigned, and
+number_float), because the library distinguishes these three types for numbers:
+@ref basic_json::number_unsigned_t is used for unsigned integers,
+@ref basic_json::number_integer_t is used for signed integers, and
+@ref basic_json::number_float_t is used for floating-point numbers or to
+approximate integers which do not fit in the limits of their respective type.
+
+@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
+value with the default value for a given type
+
+@since version 1.0.0
+*/
+enum class value_t : std::uint8_t
+{
+    null,             ///< null value
+    object,           ///< object (unordered set of name/value pairs)
+    array,            ///< array (ordered collection of values)
+    string,           ///< string value
+    boolean,          ///< boolean value
+    number_integer,   ///< number value (signed integer)
+    number_unsigned,  ///< number value (unsigned integer)
+    number_float,     ///< number value (floating-point)
+    binary,           ///< binary array (ordered collection of bytes)
+    discarded         ///< discarded by the parser callback function
+};
+
+/*!
+@brief comparison operator for JSON types
+
+Returns an ordering that is similar to Python:
+- order: null < boolean < number < object < array < string < binary
+- furthermore, each type is not smaller than itself
+- discarded values are not comparable
+- binary is represented as a b"" string in python and directly comparable to a
+  string; however, making a binary array directly comparable with a string would
+  be surprising behavior in a JSON file.
+
+@since version 1.0.0
+*/
+inline bool operator<(const value_t lhs, const value_t rhs) noexcept
+{
+    static constexpr std::array<std::uint8_t, 9> order = {{
+            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
+            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
+            6 /* binary */
+        }
+    };
+
+    const auto l_index = static_cast<std::size_t>(lhs);
+    const auto r_index = static_cast<std::size_t>(rhs);
+    return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
+}
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/string_escape.hpp>
+
+
+#include <string>
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+#include <utility> // declval, pair
+// #include <nlohmann/thirdparty/hedley/hedley.hpp>
+
+
+/* Hedley - https://nemequ.github.io/hedley
+ * Created by Evan Nemerson <evan@nemerson.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to
+ * the public domain worldwide. This software is distributed without
+ * any warranty.
+ *
+ * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
+#if defined(JSON_HEDLEY_VERSION)
+    #undef JSON_HEDLEY_VERSION
+#endif
+#define JSON_HEDLEY_VERSION 15
+
+#if defined(JSON_HEDLEY_STRINGIFY_EX)
+    #undef JSON_HEDLEY_STRINGIFY_EX
+#endif
+#define JSON_HEDLEY_STRINGIFY_EX(x) #x
+
+#if defined(JSON_HEDLEY_STRINGIFY)
+    #undef JSON_HEDLEY_STRINGIFY
+#endif
+#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
+
+#if defined(JSON_HEDLEY_CONCAT_EX)
+    #undef JSON_HEDLEY_CONCAT_EX
+#endif
+#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
+
+#if defined(JSON_HEDLEY_CONCAT)
+    #undef JSON_HEDLEY_CONCAT
+#endif
+#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
+
+#if defined(JSON_HEDLEY_CONCAT3_EX)
+    #undef JSON_HEDLEY_CONCAT3_EX
+#endif
+#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
+
+#if defined(JSON_HEDLEY_CONCAT3)
+    #undef JSON_HEDLEY_CONCAT3
+#endif
+#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
+
+#if defined(JSON_HEDLEY_VERSION_ENCODE)
+    #undef JSON_HEDLEY_VERSION_ENCODE
+#endif
+#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
+    #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
+    #undef JSON_HEDLEY_VERSION_DECODE_MINOR
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
+    #undef JSON_HEDLEY_VERSION_DECODE_REVISION
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
+
+#if defined(JSON_HEDLEY_GNUC_VERSION)
+    #undef JSON_HEDLEY_GNUC_VERSION
+#endif
+#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
+    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#elif defined(__GNUC__)
+    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
+    #undef JSON_HEDLEY_GNUC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_GNUC_VERSION)
+    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_MSVC_VERSION)
+    #undef JSON_HEDLEY_MSVC_VERSION
+#endif
+#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
+#elif defined(_MSC_FULL_VER) && !defined(__ICL)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
+#elif defined(_MSC_VER) && !defined(__ICL)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
+    #undef JSON_HEDLEY_MSVC_VERSION_CHECK
+#endif
+#if !defined(JSON_HEDLEY_MSVC_VERSION)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
+#else
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_VERSION)
+    #undef JSON_HEDLEY_INTEL_VERSION
+#endif
+#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
+    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
+#elif defined(__INTEL_COMPILER) && !defined(__ICL)
+    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
+    #undef JSON_HEDLEY_INTEL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_INTEL_VERSION)
+    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
+    #undef JSON_HEDLEY_INTEL_CL_VERSION
+#endif
+#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
+    #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
+    #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
+    #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_PGI_VERSION)
+    #undef JSON_HEDLEY_PGI_VERSION
+#endif
+#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
+    #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
+#endif
+
+#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
+    #undef JSON_HEDLEY_PGI_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_PGI_VERSION)
+    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_SUNPRO_VERSION)
+    #undef JSON_HEDLEY_SUNPRO_VERSION
+#endif
+#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
+#elif defined(__SUNPRO_C)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
+#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
+#elif defined(__SUNPRO_CC)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
+#endif
+
+#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
+    #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_SUNPRO_VERSION)
+    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
+    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
+#endif
+#if defined(__EMSCRIPTEN__)
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
+#endif
+
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
+    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_ARM_VERSION)
+    #undef JSON_HEDLEY_ARM_VERSION
+#endif
+#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
+#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
+#endif
+
+#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
+    #undef JSON_HEDLEY_ARM_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_ARM_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_IBM_VERSION)
+    #undef JSON_HEDLEY_IBM_VERSION
+#endif
+#if defined(__ibmxl__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
+#elif defined(__xlC__) && defined(__xlC_ver__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
+#elif defined(__xlC__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
+#endif
+
+#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
+    #undef JSON_HEDLEY_IBM_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_IBM_VERSION)
+    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_VERSION)
+    #undef JSON_HEDLEY_TI_VERSION
+#endif
+#if \
+    defined(__TI_COMPILER_VERSION__) && \
+    ( \
+      defined(__TMS470__) || defined(__TI_ARM__) || \
+      defined(__MSP430__) || \
+      defined(__TMS320C2000__) \
+    )
+#if (__TI_COMPILER_VERSION__ >= 16000000)
+    #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+#endif
+
+#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_VERSION)
+    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
+    #undef JSON_HEDLEY_TI_CL2000_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
+    #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
+    #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL430_VERSION)
+    #undef JSON_HEDLEY_TI_CL430_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
+    #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL430_VERSION)
+    #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
+    #undef JSON_HEDLEY_TI_ARMCL_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
+    #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
+    #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
+    #undef JSON_HEDLEY_TI_CL6X_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
+    #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
+    #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
+    #undef JSON_HEDLEY_TI_CL7X_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
+    #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
+    #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
+    #undef JSON_HEDLEY_TI_CLPRU_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
+    #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
+    #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_CRAY_VERSION)
+    #undef JSON_HEDLEY_CRAY_VERSION
+#endif
+#if defined(_CRAYC)
+    #if defined(_RELEASE_PATCHLEVEL)
+        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
+    #else
+        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
+    #endif
+#endif
+
+#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
+    #undef JSON_HEDLEY_CRAY_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_CRAY_VERSION)
+    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_IAR_VERSION)
+    #undef JSON_HEDLEY_IAR_VERSION
+#endif
+#if defined(__IAR_SYSTEMS_ICC__)
+    #if __VER__ > 1000
+        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
+    #else
+        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
+    #endif
+#endif
+
+#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
+    #undef JSON_HEDLEY_IAR_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_IAR_VERSION)
+    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TINYC_VERSION)
+    #undef JSON_HEDLEY_TINYC_VERSION
+#endif
+#if defined(__TINYC__)
+    #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
+#endif
+
+#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
+    #undef JSON_HEDLEY_TINYC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TINYC_VERSION)
+    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_DMC_VERSION)
+    #undef JSON_HEDLEY_DMC_VERSION
+#endif
+#if defined(__DMC__)
+    #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
+#endif
+
+#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
+    #undef JSON_HEDLEY_DMC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_DMC_VERSION)
+    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_COMPCERT_VERSION)
+    #undef JSON_HEDLEY_COMPCERT_VERSION
+#endif
+#if defined(__COMPCERT_VERSION__)
+    #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
+#endif
+
+#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
+    #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_COMPCERT_VERSION)
+    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_PELLES_VERSION)
+    #undef JSON_HEDLEY_PELLES_VERSION
+#endif
+#if defined(__POCC__)
+    #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
+    #undef JSON_HEDLEY_PELLES_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_PELLES_VERSION)
+    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
+    #undef JSON_HEDLEY_MCST_LCC_VERSION
+#endif
+#if defined(__LCC__) && defined(__LCC_MINOR__)
+    #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
+#endif
+
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
+    #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
+    #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_VERSION)
+    #undef JSON_HEDLEY_GCC_VERSION
+#endif
+#if \
+    defined(JSON_HEDLEY_GNUC_VERSION) && \
+    !defined(__clang__) && \
+    !defined(JSON_HEDLEY_INTEL_VERSION) && \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    !defined(JSON_HEDLEY_ARM_VERSION) && \
+    !defined(JSON_HEDLEY_CRAY_VERSION) && \
+    !defined(JSON_HEDLEY_TI_VERSION) && \
+    !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
+    !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
+    !defined(__COMPCERT__) && \
+    !defined(JSON_HEDLEY_MCST_LCC_VERSION)
+    #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
+#endif
+
+#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
+    #undef JSON_HEDLEY_GCC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_GCC_VERSION)
+    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_ATTRIBUTE
+#endif
+#if \
+  defined(__has_attribute) && \
+  ( \
+    (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
+  )
+#  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
+#else
+#  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
+#endif
+#if \
+    defined(__has_cpp_attribute) && \
+    defined(__cplusplus) && \
+    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
+    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
+#endif
+#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
+#elif \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    !defined(JSON_HEDLEY_IAR_VERSION) && \
+    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
+    (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
+#else
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
+#endif
+#if defined(__has_cpp_attribute) && defined(__cplusplus)
+    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
+#endif
+#if defined(__has_cpp_attribute) && defined(__cplusplus)
+    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_BUILTIN)
+    #undef JSON_HEDLEY_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
+    #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
+    #undef JSON_HEDLEY_GCC_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_FEATURE)
+    #undef JSON_HEDLEY_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
+    #undef JSON_HEDLEY_GNUC_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
+    #undef JSON_HEDLEY_GCC_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_EXTENSION)
+    #undef JSON_HEDLEY_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
+    #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
+    #undef JSON_HEDLEY_GCC_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_WARNING)
+    #undef JSON_HEDLEY_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_HAS_WARNING(warning) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
+    #undef JSON_HEDLEY_GNUC_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
+    #undef JSON_HEDLEY_GCC_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if \
+    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+    defined(__clang__) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
+    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
+    #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
+#else
+    #define JSON_HEDLEY_PRAGMA(value)
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
+    #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
+#endif
+#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
+    #undef JSON_HEDLEY_DIAGNOSTIC_POP
+#endif
+#if defined(__clang__)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
+    #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
+#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
+#elif \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH
+    #define JSON_HEDLEY_DIAGNOSTIC_POP
+#endif
+
+/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
+   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
+#endif
+#if defined(__cplusplus)
+#  if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
+#    if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
+#      if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
+#        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+    _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
+    _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
+    xpr \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#      else
+#        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+    _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
+    xpr \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#      endif
+#    else
+#      define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+    xpr \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#    endif
+#  endif
+#endif
+#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
+#endif
+
+#if defined(JSON_HEDLEY_CONST_CAST)
+    #undef JSON_HEDLEY_CONST_CAST
+#endif
+#if defined(__cplusplus)
+#  define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
+#elif \
+  JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+#  define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
+        JSON_HEDLEY_DIAGNOSTIC_PUSH \
+        JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
+        ((T) (expr)); \
+        JSON_HEDLEY_DIAGNOSTIC_POP \
+    }))
+#else
+#  define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_REINTERPRET_CAST)
+    #undef JSON_HEDLEY_REINTERPRET_CAST
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
+#else
+    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_STATIC_CAST)
+    #undef JSON_HEDLEY_STATIC_CAST
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
+#else
+    #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_CPP_CAST)
+    #undef JSON_HEDLEY_CPP_CAST
+#endif
+#if defined(__cplusplus)
+#  if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
+#    define JSON_HEDLEY_CPP_CAST(T, expr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
+    ((T) (expr)) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#  elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
+#    define JSON_HEDLEY_CPP_CAST(T, expr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("diag_suppress=Pe137") \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#  else
+#    define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
+#  endif
+#else
+#  define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
+#elif \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
+#elif \
+    JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
+#elif \
+    JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#endif
+
+#if defined(JSON_HEDLEY_DEPRECATED)
+    #undef JSON_HEDLEY_DEPRECATED
+#endif
+#if defined(JSON_HEDLEY_DEPRECATED_FOR)
+    #undef JSON_HEDLEY_DEPRECATED_FOR
+#endif
+#if \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
+#elif \
+    (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
+#elif defined(__cplusplus) && (__cplusplus >= 201402L)
+    #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
+#else
+    #define JSON_HEDLEY_DEPRECATED(since)
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
+#endif
+
+#if defined(JSON_HEDLEY_UNAVAILABLE)
+    #undef JSON_HEDLEY_UNAVAILABLE
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
+#else
+    #define JSON_HEDLEY_UNAVAILABLE(available_since)
+#endif
+
+#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
+    #undef JSON_HEDLEY_WARN_UNUSED_RESULT
+#endif
+#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
+    #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
+#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+#elif defined(_Check_return_) /* SAL */
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
+#else
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
+#endif
+
+#if defined(JSON_HEDLEY_SENTINEL)
+    #undef JSON_HEDLEY_SENTINEL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
+#else
+    #define JSON_HEDLEY_SENTINEL(position)
+#endif
+
+#if defined(JSON_HEDLEY_NO_RETURN)
+    #undef JSON_HEDLEY_NO_RETURN
+#endif
+#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_NO_RETURN __noreturn
+#elif \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+    #define JSON_HEDLEY_NO_RETURN _Noreturn
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+    #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
+#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
+    #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
+    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
+#else
+    #define JSON_HEDLEY_NO_RETURN
+#endif
+
+#if defined(JSON_HEDLEY_NO_ESCAPE)
+    #undef JSON_HEDLEY_NO_ESCAPE
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
+    #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
+#else
+    #define JSON_HEDLEY_NO_ESCAPE
+#endif
+
+#if defined(JSON_HEDLEY_UNREACHABLE)
+    #undef JSON_HEDLEY_UNREACHABLE
+#endif
+#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
+    #undef JSON_HEDLEY_UNREACHABLE_RETURN
+#endif
+#if defined(JSON_HEDLEY_ASSUME)
+    #undef JSON_HEDLEY_ASSUME
+#endif
+#if \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
+#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
+    #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
+#elif \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
+    #if defined(__cplusplus)
+        #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
+    #else
+        #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
+    #endif
+#endif
+#if \
+    (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
+    JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
+#elif defined(JSON_HEDLEY_ASSUME)
+    #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
+#endif
+#if !defined(JSON_HEDLEY_ASSUME)
+    #if defined(JSON_HEDLEY_UNREACHABLE)
+        #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
+    #else
+        #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
+    #endif
+#endif
+#if defined(JSON_HEDLEY_UNREACHABLE)
+    #if  \
+        JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+        JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
+        #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
+    #else
+        #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
+    #endif
+#else
+    #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
+#endif
+#if !defined(JSON_HEDLEY_UNREACHABLE)
+    #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
+#endif
+
+JSON_HEDLEY_DIAGNOSTIC_PUSH
+#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
+    #pragma clang diagnostic ignored "-Wpedantic"
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
+    #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#endif
+#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
+    #if defined(__clang__)
+        #pragma clang diagnostic ignored "-Wvariadic-macros"
+    #elif defined(JSON_HEDLEY_GCC_VERSION)
+        #pragma GCC diagnostic ignored "-Wvariadic-macros"
+    #endif
+#endif
+#if defined(JSON_HEDLEY_NON_NULL)
+    #undef JSON_HEDLEY_NON_NULL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
+    #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
+#else
+    #define JSON_HEDLEY_NON_NULL(...)
+#endif
+JSON_HEDLEY_DIAGNOSTIC_POP
+
+#if defined(JSON_HEDLEY_PRINTF_FORMAT)
+    #undef JSON_HEDLEY_PRINTF_FORMAT
+#endif
+#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
+#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
+#else
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
+#endif
+
+#if defined(JSON_HEDLEY_CONSTEXPR)
+    #undef JSON_HEDLEY_CONSTEXPR
+#endif
+#if defined(__cplusplus)
+    #if __cplusplus >= 201103L
+        #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
+    #endif
+#endif
+#if !defined(JSON_HEDLEY_CONSTEXPR)
+    #define JSON_HEDLEY_CONSTEXPR
+#endif
+
+#if defined(JSON_HEDLEY_PREDICT)
+    #undef JSON_HEDLEY_PREDICT
+#endif
+#if defined(JSON_HEDLEY_LIKELY)
+    #undef JSON_HEDLEY_LIKELY
+#endif
+#if defined(JSON_HEDLEY_UNLIKELY)
+    #undef JSON_HEDLEY_UNLIKELY
+#endif
+#if defined(JSON_HEDLEY_UNPREDICTABLE)
+    #undef JSON_HEDLEY_UNPREDICTABLE
+#endif
+#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
+    #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
+#endif
+#if \
+  (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
+  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+#  define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(  (expr), (value), (probability))
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability)   __builtin_expect_with_probability(!!(expr),    1   , (probability))
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability)  __builtin_expect_with_probability(!!(expr),    0   , (probability))
+#  define JSON_HEDLEY_LIKELY(expr)                      __builtin_expect                 (!!(expr),    1                  )
+#  define JSON_HEDLEY_UNLIKELY(expr)                    __builtin_expect                 (!!(expr),    0                  )
+#elif \
+  (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+  (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
+  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
+  JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
+  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
+  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+  JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
+  JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+#  define JSON_HEDLEY_PREDICT(expr, expected, probability) \
+    (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
+    (__extension__ ({ \
+        double hedley_probability_ = (probability); \
+        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
+    }))
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
+    (__extension__ ({ \
+        double hedley_probability_ = (probability); \
+        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
+    }))
+#  define JSON_HEDLEY_LIKELY(expr)   __builtin_expect(!!(expr), 1)
+#  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
+#else
+#  define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
+#  define JSON_HEDLEY_LIKELY(expr) (!!(expr))
+#  define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
+#endif
+#if !defined(JSON_HEDLEY_UNPREDICTABLE)
+    #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
+#endif
+
+#if defined(JSON_HEDLEY_MALLOC)
+    #undef JSON_HEDLEY_MALLOC
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_MALLOC __declspec(restrict)
+#else
+    #define JSON_HEDLEY_MALLOC
+#endif
+
+#if defined(JSON_HEDLEY_PURE)
+    #undef JSON_HEDLEY_PURE
+#endif
+#if \
+  JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+  JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+  (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+  (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+  (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+  (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+  JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+#  define JSON_HEDLEY_PURE __attribute__((__pure__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+#  define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
+#elif defined(__cplusplus) && \
+    ( \
+      JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
+      JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
+      JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
+    )
+#  define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
+#else
+#  define JSON_HEDLEY_PURE
+#endif
+
+#if defined(JSON_HEDLEY_CONST)
+    #undef JSON_HEDLEY_CONST
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_CONST __attribute__((__const__))
+#elif \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
+#else
+    #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
+#endif
+
+#if defined(JSON_HEDLEY_RESTRICT)
+    #undef JSON_HEDLEY_RESTRICT
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
+    #define JSON_HEDLEY_RESTRICT restrict
+#elif \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
+    defined(__clang__) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_RESTRICT __restrict
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
+    #define JSON_HEDLEY_RESTRICT _Restrict
+#else
+    #define JSON_HEDLEY_RESTRICT
+#endif
+
+#if defined(JSON_HEDLEY_INLINE)
+    #undef JSON_HEDLEY_INLINE
+#endif
+#if \
+    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+    (defined(__cplusplus) && (__cplusplus >= 199711L))
+    #define JSON_HEDLEY_INLINE inline
+#elif \
+    defined(JSON_HEDLEY_GCC_VERSION) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
+    #define JSON_HEDLEY_INLINE __inline__
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_INLINE __inline
+#else
+    #define JSON_HEDLEY_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_ALWAYS_INLINE)
+    #undef JSON_HEDLEY_ALWAYS_INLINE
+#endif
+#if \
+  JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+  JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+  (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+  (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+  (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+  (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+  JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+#  define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
+#elif \
+  JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
+  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+#  define JSON_HEDLEY_ALWAYS_INLINE __forceinline
+#elif defined(__cplusplus) && \
+    ( \
+      JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+      JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+      JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+      JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+      JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+      JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
+    )
+#  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+#  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
+#else
+#  define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_NEVER_INLINE)
+    #undef JSON_HEDLEY_NEVER_INLINE
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+    #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
+#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
+    #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
+    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
+#else
+    #define JSON_HEDLEY_NEVER_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_PRIVATE)
+    #undef JSON_HEDLEY_PRIVATE
+#endif
+#if defined(JSON_HEDLEY_PUBLIC)
+    #undef JSON_HEDLEY_PUBLIC
+#endif
+#if defined(JSON_HEDLEY_IMPORT)
+    #undef JSON_HEDLEY_IMPORT
+#endif
+#if defined(_WIN32) || defined(__CYGWIN__)
+#  define JSON_HEDLEY_PRIVATE
+#  define JSON_HEDLEY_PUBLIC   __declspec(dllexport)
+#  define JSON_HEDLEY_IMPORT   __declspec(dllimport)
+#else
+#  if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+    ( \
+      defined(__TI_EABI__) && \
+      ( \
+        (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+        JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
+      ) \
+    ) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+#    define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
+#    define JSON_HEDLEY_PUBLIC  __attribute__((__visibility__("default")))
+#  else
+#    define JSON_HEDLEY_PRIVATE
+#    define JSON_HEDLEY_PUBLIC
+#  endif
+#  define JSON_HEDLEY_IMPORT    extern
+#endif
+
+#if defined(JSON_HEDLEY_NO_THROW)
+    #undef JSON_HEDLEY_NO_THROW
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
+    #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
+#else
+    #define JSON_HEDLEY_NO_THROW
+#endif
+
+#if defined(JSON_HEDLEY_FALL_THROUGH)
+    #undef JSON_HEDLEY_FALL_THROUGH
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
+    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
+    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
+#elif defined(__fallthrough) /* SAL */
+    #define JSON_HEDLEY_FALL_THROUGH __fallthrough
+#else
+    #define JSON_HEDLEY_FALL_THROUGH
+#endif
+
+#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
+    #undef JSON_HEDLEY_RETURNS_NON_NULL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
+#elif defined(_Ret_notnull_) /* SAL */
+    #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
+#else
+    #define JSON_HEDLEY_RETURNS_NON_NULL
+#endif
+
+#if defined(JSON_HEDLEY_ARRAY_PARAM)
+    #undef JSON_HEDLEY_ARRAY_PARAM
+#endif
+#if \
+    defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+    !defined(__STDC_NO_VLA__) && \
+    !defined(__cplusplus) && \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    !defined(JSON_HEDLEY_TINYC_VERSION)
+    #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
+#else
+    #define JSON_HEDLEY_ARRAY_PARAM(name)
+#endif
+
+#if defined(JSON_HEDLEY_IS_CONSTANT)
+    #undef JSON_HEDLEY_IS_CONSTANT
+#endif
+#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
+    #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
+#endif
+/* JSON_HEDLEY_IS_CONSTEXPR_ is for
+   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
+#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
+    #undef JSON_HEDLEY_IS_CONSTEXPR_
+#endif
+#if \
+    JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
+    JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+    #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
+#endif
+#if !defined(__cplusplus)
+#  if \
+       JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
+       JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+       JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+       JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+       JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+       JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
+       JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
+#if defined(__INTPTR_TYPE__)
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
+#else
+    #include <stdint.h>
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
+#endif
+#  elif \
+       ( \
+          defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
+          !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
+          !defined(JSON_HEDLEY_PGI_VERSION) && \
+          !defined(JSON_HEDLEY_IAR_VERSION)) || \
+       (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
+       JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
+       JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
+       JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
+       JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
+#if defined(__INTPTR_TYPE__)
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
+#else
+    #include <stdint.h>
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
+#endif
+#  elif \
+       defined(JSON_HEDLEY_GCC_VERSION) || \
+       defined(JSON_HEDLEY_INTEL_VERSION) || \
+       defined(JSON_HEDLEY_TINYC_VERSION) || \
+       defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
+       JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
+       defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
+       defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
+       defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
+       defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
+       defined(__clang__)
+#    define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
+        sizeof(void) != \
+        sizeof(*( \
+                  1 ? \
+                  ((void*) ((expr) * 0L) ) : \
+((struct { char v[sizeof(void) * 2]; } *) 1) \
+                ) \
+              ) \
+                                            )
+#  endif
+#endif
+#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
+    #if !defined(JSON_HEDLEY_IS_CONSTANT)
+        #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
+    #endif
+    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
+#else
+    #if !defined(JSON_HEDLEY_IS_CONSTANT)
+        #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
+    #endif
+    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
+#endif
+
+#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
+    #undef JSON_HEDLEY_BEGIN_C_DECLS
+#endif
+#if defined(JSON_HEDLEY_END_C_DECLS)
+    #undef JSON_HEDLEY_END_C_DECLS
+#endif
+#if defined(JSON_HEDLEY_C_DECL)
+    #undef JSON_HEDLEY_C_DECL
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
+    #define JSON_HEDLEY_END_C_DECLS }
+    #define JSON_HEDLEY_C_DECL extern "C"
+#else
+    #define JSON_HEDLEY_BEGIN_C_DECLS
+    #define JSON_HEDLEY_END_C_DECLS
+    #define JSON_HEDLEY_C_DECL
+#endif
+
+#if defined(JSON_HEDLEY_STATIC_ASSERT)
+    #undef JSON_HEDLEY_STATIC_ASSERT
+#endif
+#if \
+  !defined(__cplusplus) && ( \
+      (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
+      (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
+      JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
+      JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+      defined(_Static_assert) \
+    )
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
+#elif \
+  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
+  JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
+  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
+#else
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message)
+#endif
+
+#if defined(JSON_HEDLEY_NULL)
+    #undef JSON_HEDLEY_NULL
+#endif
+#if defined(__cplusplus)
+    #if __cplusplus >= 201103L
+        #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
+    #elif defined(NULL)
+        #define JSON_HEDLEY_NULL NULL
+    #else
+        #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
+    #endif
+#elif defined(NULL)
+    #define JSON_HEDLEY_NULL NULL
+#else
+    #define JSON_HEDLEY_NULL ((void*) 0)
+#endif
+
+#if defined(JSON_HEDLEY_MESSAGE)
+    #undef JSON_HEDLEY_MESSAGE
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+#  define JSON_HEDLEY_MESSAGE(msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
+    JSON_HEDLEY_PRAGMA(message msg) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#elif \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
+#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#else
+#  define JSON_HEDLEY_MESSAGE(msg)
+#endif
+
+#if defined(JSON_HEDLEY_WARNING)
+    #undef JSON_HEDLEY_WARNING
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+#  define JSON_HEDLEY_WARNING(msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
+    JSON_HEDLEY_PRAGMA(clang warning msg) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#elif \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
+  JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
+#elif \
+  JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
+  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#else
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
+#endif
+
+#if defined(JSON_HEDLEY_REQUIRE)
+    #undef JSON_HEDLEY_REQUIRE
+#endif
+#if defined(JSON_HEDLEY_REQUIRE_MSG)
+    #undef JSON_HEDLEY_REQUIRE_MSG
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
+#  if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
+#    define JSON_HEDLEY_REQUIRE(expr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+    __attribute__((diagnose_if(!(expr), #expr, "error"))) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+    __attribute__((diagnose_if(!(expr), msg, "error"))) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#  else
+#    define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
+#    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
+#  endif
+#else
+#  define JSON_HEDLEY_REQUIRE(expr)
+#  define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
+#endif
+
+#if defined(JSON_HEDLEY_FLAGS)
+    #undef JSON_HEDLEY_FLAGS
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
+    #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
+#else
+    #define JSON_HEDLEY_FLAGS
+#endif
+
+#if defined(JSON_HEDLEY_FLAGS_CAST)
+    #undef JSON_HEDLEY_FLAGS_CAST
+#endif
+#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
+#  define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
+        JSON_HEDLEY_DIAGNOSTIC_PUSH \
+        _Pragma("warning(disable:188)") \
+        ((T) (expr)); \
+        JSON_HEDLEY_DIAGNOSTIC_POP \
+    }))
+#else
+#  define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
+#endif
+
+#if defined(JSON_HEDLEY_EMPTY_BASES)
+    #undef JSON_HEDLEY_EMPTY_BASES
+#endif
+#if \
+    (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
+    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+    #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
+#else
+    #define JSON_HEDLEY_EMPTY_BASES
+#endif
+
+/* Remaining macros are deprecated. */
+
+#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
+    #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
+#endif
+#if defined(__clang__)
+    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
+#else
+    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
+    #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
+#endif
+#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
+    #undef JSON_HEDLEY_CLANG_HAS_FEATURE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
+    #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
+#endif
+#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
+    #undef JSON_HEDLEY_CLANG_HAS_WARNING
+#endif
+#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
+
+#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+
+#include <type_traits>
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename ...Ts> struct make_void
+{
+    using type = void;
+};
+template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
+} // namespace detail
+}  // namespace nlohmann
+
+
+// https://en.cppreference.com/w/cpp/experimental/is_detected
+namespace nlohmann
+{
+namespace detail
+{
+struct nonesuch
+{
+    nonesuch() = delete;
+    ~nonesuch() = delete;
+    nonesuch(nonesuch const&) = delete;
+    nonesuch(nonesuch const&&) = delete;
+    void operator=(nonesuch const&) = delete;
+    void operator=(nonesuch&&) = delete;
+};
+
+template<class Default,
+         class AlwaysVoid,
+         template<class...> class Op,
+         class... Args>
+struct detector
+{
+    using value_t = std::false_type;
+    using type = Default;
+};
+
+template<class Default, template<class...> class Op, class... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
+{
+    using value_t = std::true_type;
+    using type = Op<Args...>;
+};
+
+template<template<class...> class Op, class... Args>
+using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
+
+template<template<class...> class Op, class... Args>
+struct is_detected_lazy : is_detected<Op, Args...> { };
+
+template<template<class...> class Op, class... Args>
+using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
+
+template<class Default, template<class...> class Op, class... Args>
+using detected_or = detector<Default, void, Op, Args...>;
+
+template<class Default, template<class...> class Op, class... Args>
+using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+
+template<class Expected, template<class...> class Op, class... Args>
+using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
+
+template<class To, template<class...> class Op, class... Args>
+using is_detected_convertible =
+    std::is_convertible<detected_t<Op, Args...>, To>;
+}  // namespace detail
+}  // namespace nlohmann
+
+
+// This file contains all internal macro definitions
+// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
+
+// exclude unsupported compilers
+#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
+    #if defined(__clang__)
+        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
+            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
+        #endif
+    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
+        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
+            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+        #endif
+    #endif
+#endif
+
+// C++ language standard detection
+// if the user manually specified the used c++ version this is skipped
+#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
+    #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
+        #define JSON_HAS_CPP_20
+        #define JSON_HAS_CPP_17
+        #define JSON_HAS_CPP_14
+    #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
+        #define JSON_HAS_CPP_17
+        #define JSON_HAS_CPP_14
+    #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
+        #define JSON_HAS_CPP_14
+    #endif
+    // the cpp 11 flag is always specified because it is the minimal required version
+    #define JSON_HAS_CPP_11
+#endif
+
+// disable documentation warnings on clang
+#if defined(__clang__)
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wdocumentation"
+    #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
+#endif
+
+// allow to disable exceptions
+#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
+    #define JSON_THROW(exception) throw exception
+    #define JSON_TRY try
+    #define JSON_CATCH(exception) catch(exception)
+    #define JSON_INTERNAL_CATCH(exception) catch(exception)
+#else
+    #include <cstdlib>
+    #define JSON_THROW(exception) std::abort()
+    #define JSON_TRY if(true)
+    #define JSON_CATCH(exception) if(false)
+    #define JSON_INTERNAL_CATCH(exception) if(false)
+#endif
+
+// override exception macros
+#if defined(JSON_THROW_USER)
+    #undef JSON_THROW
+    #define JSON_THROW JSON_THROW_USER
+#endif
+#if defined(JSON_TRY_USER)
+    #undef JSON_TRY
+    #define JSON_TRY JSON_TRY_USER
+#endif
+#if defined(JSON_CATCH_USER)
+    #undef JSON_CATCH
+    #define JSON_CATCH JSON_CATCH_USER
+    #undef JSON_INTERNAL_CATCH
+    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
+#endif
+#if defined(JSON_INTERNAL_CATCH_USER)
+    #undef JSON_INTERNAL_CATCH
+    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
+#endif
+
+// allow to override assert
+#if !defined(JSON_ASSERT)
+    #include <cassert> // assert
+    #define JSON_ASSERT(x) assert(x)
+#endif
+
+// allow to access some private functions (needed by the test suite)
+#if defined(JSON_TESTS_PRIVATE)
+    #define JSON_PRIVATE_UNLESS_TESTED public
+#else
+    #define JSON_PRIVATE_UNLESS_TESTED private
+#endif
+
+/*!
+@brief macro to briefly define a mapping between an enum and JSON
+@def NLOHMANN_JSON_SERIALIZE_ENUM
+@since version 3.4.0
+*/
+#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \
+    template<typename BasicJsonType>                                                            \
+    inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \
+    {                                                                                           \
+        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
+        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
+        auto it = std::find_if(std::begin(m), std::end(m),                                      \
+                               [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \
+        {                                                                                       \
+            return ej_pair.first == e;                                                          \
+        });                                                                                     \
+        j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \
+    }                                                                                           \
+    template<typename BasicJsonType>                                                            \
+    inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \
+    {                                                                                           \
+        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
+        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
+        auto it = std::find_if(std::begin(m), std::end(m),                                      \
+                               [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
+        {                                                                                       \
+            return ej_pair.second == j;                                                         \
+        });                                                                                     \
+        e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \
+    }
+
+// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
+// may be removed in the future once the class is split.
+
+#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
+    template<template<typename, typename, typename...> class ObjectType,   \
+             template<typename, typename...> class ArrayType,              \
+             class StringType, class BooleanType, class NumberIntegerType, \
+             class NumberUnsignedType, class NumberFloatType,              \
+             template<typename> class AllocatorType,                       \
+             template<typename, typename = void> class JSONSerializer,     \
+             class BinaryType>
+
+#define NLOHMANN_BASIC_JSON_TPL                                            \
+    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
+    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
+    AllocatorType, JSONSerializer, BinaryType>
+
+// Macros to simplify conversion from/to types
+
+#define NLOHMANN_JSON_EXPAND( x ) x
+#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
+#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
+        NLOHMANN_JSON_PASTE64, \
+        NLOHMANN_JSON_PASTE63, \
+        NLOHMANN_JSON_PASTE62, \
+        NLOHMANN_JSON_PASTE61, \
+        NLOHMANN_JSON_PASTE60, \
+        NLOHMANN_JSON_PASTE59, \
+        NLOHMANN_JSON_PASTE58, \
+        NLOHMANN_JSON_PASTE57, \
+        NLOHMANN_JSON_PASTE56, \
+        NLOHMANN_JSON_PASTE55, \
+        NLOHMANN_JSON_PASTE54, \
+        NLOHMANN_JSON_PASTE53, \
+        NLOHMANN_JSON_PASTE52, \
+        NLOHMANN_JSON_PASTE51, \
+        NLOHMANN_JSON_PASTE50, \
+        NLOHMANN_JSON_PASTE49, \
+        NLOHMANN_JSON_PASTE48, \
+        NLOHMANN_JSON_PASTE47, \
+        NLOHMANN_JSON_PASTE46, \
+        NLOHMANN_JSON_PASTE45, \
+        NLOHMANN_JSON_PASTE44, \
+        NLOHMANN_JSON_PASTE43, \
+        NLOHMANN_JSON_PASTE42, \
+        NLOHMANN_JSON_PASTE41, \
+        NLOHMANN_JSON_PASTE40, \
+        NLOHMANN_JSON_PASTE39, \
+        NLOHMANN_JSON_PASTE38, \
+        NLOHMANN_JSON_PASTE37, \
+        NLOHMANN_JSON_PASTE36, \
+        NLOHMANN_JSON_PASTE35, \
+        NLOHMANN_JSON_PASTE34, \
+        NLOHMANN_JSON_PASTE33, \
+        NLOHMANN_JSON_PASTE32, \
+        NLOHMANN_JSON_PASTE31, \
+        NLOHMANN_JSON_PASTE30, \
+        NLOHMANN_JSON_PASTE29, \
+        NLOHMANN_JSON_PASTE28, \
+        NLOHMANN_JSON_PASTE27, \
+        NLOHMANN_JSON_PASTE26, \
+        NLOHMANN_JSON_PASTE25, \
+        NLOHMANN_JSON_PASTE24, \
+        NLOHMANN_JSON_PASTE23, \
+        NLOHMANN_JSON_PASTE22, \
+        NLOHMANN_JSON_PASTE21, \
+        NLOHMANN_JSON_PASTE20, \
+        NLOHMANN_JSON_PASTE19, \
+        NLOHMANN_JSON_PASTE18, \
+        NLOHMANN_JSON_PASTE17, \
+        NLOHMANN_JSON_PASTE16, \
+        NLOHMANN_JSON_PASTE15, \
+        NLOHMANN_JSON_PASTE14, \
+        NLOHMANN_JSON_PASTE13, \
+        NLOHMANN_JSON_PASTE12, \
+        NLOHMANN_JSON_PASTE11, \
+        NLOHMANN_JSON_PASTE10, \
+        NLOHMANN_JSON_PASTE9, \
+        NLOHMANN_JSON_PASTE8, \
+        NLOHMANN_JSON_PASTE7, \
+        NLOHMANN_JSON_PASTE6, \
+        NLOHMANN_JSON_PASTE5, \
+        NLOHMANN_JSON_PASTE4, \
+        NLOHMANN_JSON_PASTE3, \
+        NLOHMANN_JSON_PASTE2, \
+        NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
+#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
+#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
+#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
+#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
+#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
+#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
+#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
+#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
+#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
+#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
+#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
+#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
+#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
+#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
+#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
+#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
+#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
+#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
+#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
+#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
+#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
+#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
+#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
+#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
+#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
+#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
+#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
+#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
+#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
+#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
+#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
+#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
+#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
+#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
+#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
+#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
+#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
+#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
+#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
+#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
+#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
+#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
+#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
+#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
+#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
+#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
+#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
+#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
+#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
+#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
+#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
+#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
+#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
+#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
+#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
+#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
+#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
+#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
+#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
+#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
+#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
+#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
+#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
+
+#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
+#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
+
+/*!
+@brief macro
+@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
+@since version 3.9.0
+*/
+#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
+    friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
+    friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
+
+/*!
+@brief macro
+@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
+@since version 3.9.0
+*/
+#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \
+    inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
+    inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
+
+
+// inspired from https://stackoverflow.com/a/26745591
+// allows to call any std function as if (e.g. with begin):
+// using std::begin; begin(x);
+//
+// it allows using the detected idiom to retrieve the return type
+// of such an expression
+#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)                                 \
+    namespace detail {                                                            \
+    using std::std_name;                                                          \
+    \
+    template<typename... T>                                                       \
+    using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
+    }                                                                             \
+    \
+    namespace detail2 {                                                           \
+    struct std_name##_tag                                                         \
+    {                                                                             \
+    };                                                                            \
+    \
+    template<typename... T>                                                       \
+    std_name##_tag std_name(T&&...);                                              \
+    \
+    template<typename... T>                                                       \
+    using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
+    \
+    template<typename... T>                                                       \
+    struct would_call_std_##std_name                                              \
+    {                                                                             \
+        static constexpr auto const value = ::nlohmann::detail::                  \
+                                            is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
+    };                                                                            \
+    } /* namespace detail2 */ \
+    \
+    template<typename... T>                                                       \
+    struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...>   \
+    {                                                                             \
+    }
+
+#ifndef JSON_USE_IMPLICIT_CONVERSIONS
+    #define JSON_USE_IMPLICIT_CONVERSIONS 1
+#endif
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+    #define JSON_EXPLICIT
+#else
+    #define JSON_EXPLICIT explicit
+#endif
+
+#ifndef JSON_DIAGNOSTICS
+    #define JSON_DIAGNOSTICS 0
+#endif
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+/*!
+@brief replace all occurrences of a substring by another string
+
+@param[in,out] s  the string to manipulate; changed so that all
+               occurrences of @a f are replaced with @a t
+@param[in]     f  the substring to replace with @a t
+@param[in]     t  the string to replace @a f
+
+@pre The search string @a f must not be empty. **This precondition is
+enforced with an assertion.**
+
+@since version 2.0.0
+*/
+inline void replace_substring(std::string& s, const std::string& f,
+                              const std::string& t)
+{
+    JSON_ASSERT(!f.empty());
+    for (auto pos = s.find(f);                // find first occurrence of f
+            pos != std::string::npos;         // make sure f was found
+            s.replace(pos, f.size(), t),      // replace with t, and
+            pos = s.find(f, pos + t.size()))  // find next occurrence of f
+    {}
+}
+
+/*!
+ * @brief string escaping as described in RFC 6901 (Sect. 4)
+ * @param[in] s string to escape
+ * @return    escaped string
+ *
+ * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
+ */
+inline std::string escape(std::string s)
+{
+    replace_substring(s, "~", "~0");
+    replace_substring(s, "/", "~1");
+    return s;
+}
+
+/*!
+ * @brief string unescaping as described in RFC 6901 (Sect. 4)
+ * @param[in] s string to unescape
+ * @return    unescaped string
+ *
+ * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
+ */
+static void unescape(std::string& s)
+{
+    replace_substring(s, "~1", "/");
+    replace_substring(s, "~0", "~");
+}
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/input/position_t.hpp>
+
+
+#include <cstddef> // size_t
+
+namespace nlohmann
+{
+namespace detail
+{
+/// struct to capture the start position of the current token
+struct position_t
+{
+    /// the total number of characters read
+    std::size_t chars_read_total = 0;
+    /// the number of characters read in the current line
+    std::size_t chars_read_current_line = 0;
+    /// the number of lines read
+    std::size_t lines_read = 0;
+
+    /// conversion to size_t to preserve SAX interface
+    constexpr operator size_t() const
+    {
+        return chars_read_total;
+    }
+};
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+////////////////
+// exceptions //
+////////////////
+
+/*!
+@brief general exception of the @ref basic_json class
+
+This class is an extension of `std::exception` objects with a member @a id for
+exception ids. It is used as the base class for all exceptions thrown by the
+@ref basic_json class. This class can hence be used as "wildcard" to catch
+exceptions.
+
+Subclasses:
+- @ref parse_error for exceptions indicating a parse error
+- @ref invalid_iterator for exceptions indicating errors with iterators
+- @ref type_error for exceptions indicating executing a member function with
+                  a wrong type
+- @ref out_of_range for exceptions indicating access out of the defined range
+- @ref other_error for exceptions indicating other library errors
+
+@internal
+@note To have nothrow-copy-constructible exceptions, we internally use
+      `std::runtime_error` which can cope with arbitrary-length error messages.
+      Intermediate strings are built with static functions and then passed to
+      the actual constructor.
+@endinternal
+
+@liveexample{The following code shows how arbitrary library exceptions can be
+caught.,exception}
+
+@since version 3.0.0
+*/
+class exception : public std::exception
+{
+  public:
+    /// returns the explanatory string
+    const char* what() const noexcept override
+    {
+        return m.what();
+    }
+
+    /// the id of the exception
+    const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
+
+  protected:
+    JSON_HEDLEY_NON_NULL(3)
+    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
+
+    static std::string name(const std::string& ename, int id_)
+    {
+        return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
+    }
+
+    template<typename BasicJsonType>
+    static std::string diagnostics(const BasicJsonType& leaf_element)
+    {
+#if JSON_DIAGNOSTICS
+        std::vector<std::string> tokens;
+        for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
+        {
+            switch (current->m_parent->type())
+            {
+                case value_t::array:
+                {
+                    for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
+                    {
+                        if (&current->m_parent->m_value.array->operator[](i) == current)
+                        {
+                            tokens.emplace_back(std::to_string(i));
+                            break;
+                        }
+                    }
+                    break;
+                }
+
+                case value_t::object:
+                {
+                    for (const auto& element : *current->m_parent->m_value.object)
+                    {
+                        if (&element.second == current)
+                        {
+                            tokens.emplace_back(element.first.c_str());
+                            break;
+                        }
+                    }
+                    break;
+                }
+
+                case value_t::null: // LCOV_EXCL_LINE
+                case value_t::string: // LCOV_EXCL_LINE
+                case value_t::boolean: // LCOV_EXCL_LINE
+                case value_t::number_integer: // LCOV_EXCL_LINE
+                case value_t::number_unsigned: // LCOV_EXCL_LINE
+                case value_t::number_float: // LCOV_EXCL_LINE
+                case value_t::binary: // LCOV_EXCL_LINE
+                case value_t::discarded: // LCOV_EXCL_LINE
+                default:   // LCOV_EXCL_LINE
+                    break; // LCOV_EXCL_LINE
+            }
+        }
+
+        if (tokens.empty())
+        {
+            return "";
+        }
+
+        return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
+                                     [](const std::string & a, const std::string & b)
+        {
+            return a + "/" + detail::escape(b);
+        }) + ") ";
+#else
+        static_cast<void>(leaf_element);
+        return "";
+#endif
+    }
+
+  private:
+    /// an exception object as storage for error messages
+    std::runtime_error m;
+};
+
+/*!
+@brief exception indicating a parse error
+
+This exception is thrown by the library when a parse error occurs. Parse errors
+can occur during the deserialization of JSON text, CBOR, MessagePack, as well
+as when using JSON Patch.
+
+Member @a byte holds the byte index of the last read character in the input
+file.
+
+Exceptions have ids 1xx.
+
+name / id                      | example message | description
+------------------------------ | --------------- | -------------------------
+json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
+json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
+json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
+json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
+json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
+json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
+json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
+json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
+json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
+json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
+json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
+json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
+json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
+json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed.
+
+@note For an input with n bytes, 1 is the index of the first character and n+1
+      is the index of the terminating null byte or the end of file. This also
+      holds true when reading a byte vector (CBOR or MessagePack).
+
+@liveexample{The following code shows how a `parse_error` exception can be
+caught.,parse_error}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+                    a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class parse_error : public exception
+{
+  public:
+    /*!
+    @brief create a parse error exception
+    @param[in] id_       the id of the exception
+    @param[in] pos       the position where the error occurred (or with
+                         chars_read_total=0 if the position cannot be
+                         determined)
+    @param[in] what_arg  the explanatory string
+    @return parse_error object
+    */
+    template<typename BasicJsonType>
+    static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
+    {
+        std::string w = exception::name("parse_error", id_) + "parse error" +
+                        position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
+        return {id_, pos.chars_read_total, w.c_str()};
+    }
+
+    template<typename BasicJsonType>
+    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
+    {
+        std::string w = exception::name("parse_error", id_) + "parse error" +
+                        (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
+                        ": " + exception::diagnostics(context) + what_arg;
+        return {id_, byte_, w.c_str()};
+    }
+
+    /*!
+    @brief byte index of the parse error
+
+    The byte index of the last read character in the input file.
+
+    @note For an input with n bytes, 1 is the index of the first character and
+          n+1 is the index of the terminating null byte or the end of file.
+          This also holds true when reading a byte vector (CBOR or MessagePack).
+    */
+    const std::size_t byte;
+
+  private:
+    parse_error(int id_, std::size_t byte_, const char* what_arg)
+        : exception(id_, what_arg), byte(byte_) {}
+
+    static std::string position_string(const position_t& pos)
+    {
+        return " at line " + std::to_string(pos.lines_read + 1) +
+               ", column " + std::to_string(pos.chars_read_current_line);
+    }
+};
+
+/*!
+@brief exception indicating errors with iterators
+
+This exception is thrown if iterators passed to a library function do not match
+the expected semantics.
+
+Exceptions have ids 2xx.
+
+name / id                           | example message | description
+----------------------------------- | --------------- | -------------------------
+json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
+json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
+json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
+json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
+json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
+json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
+json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
+json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
+json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
+json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
+json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
+json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
+json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
+json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
+
+@liveexample{The following code shows how an `invalid_iterator` exception can be
+caught.,invalid_iterator}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref type_error for exceptions indicating executing a member function with
+                    a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class invalid_iterator : public exception
+{
+  public:
+    template<typename BasicJsonType>
+    static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
+    {
+        std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
+        return {id_, w.c_str()};
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    invalid_iterator(int id_, const char* what_arg)
+        : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating executing a member function with a wrong type
+
+This exception is thrown in case of a type error; that is, a library function is
+executed on a JSON value whose type does not match the expected semantics.
+
+Exceptions have ids 3xx.
+
+name / id                     | example message | description
+----------------------------- | --------------- | -------------------------
+json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
+json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
+json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
+json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
+json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
+json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
+json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
+json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
+json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
+json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
+json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
+json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
+json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
+json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
+json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
+json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
+json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
+
+@liveexample{The following code shows how a `type_error` exception can be
+caught.,type_error}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class type_error : public exception
+{
+  public:
+    template<typename BasicJsonType>
+    static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
+    {
+        std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
+        return {id_, w.c_str()};
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating access out of the defined range
+
+This exception is thrown in case a library function is called on an input
+parameter that exceeds the expected range, for instance in case of array
+indices or nonexisting object keys.
+
+Exceptions have ids 4xx.
+
+name / id                       | example message | description
+------------------------------- | --------------- | -------------------------
+json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
+json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
+json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
+json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
+json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
+json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
+json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) |
+json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
+json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
+
+@liveexample{The following code shows how an `out_of_range` exception can be
+caught.,out_of_range}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+                    a wrong type
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class out_of_range : public exception
+{
+  public:
+    template<typename BasicJsonType>
+    static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
+    {
+        std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
+        return {id_, w.c_str()};
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating other library errors
+
+This exception is thrown in case of errors that cannot be classified with the
+other exception types.
+
+Exceptions have ids 5xx.
+
+name / id                      | example message | description
+------------------------------ | --------------- | -------------------------
+json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+                    a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+
+@liveexample{The following code shows how an `other_error` exception can be
+caught.,other_error}
+
+@since version 3.0.0
+*/
+class other_error : public exception
+{
+  public:
+    template<typename BasicJsonType>
+    static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
+    {
+        std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
+        return {id_, w.c_str()};
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+
+#include <cstddef> // size_t
+#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
+#include <utility> // index_sequence, make_index_sequence, index_sequence_for
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+template<typename T>
+using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+#ifdef JSON_HAS_CPP_14
+
+// the following utilities are natively available in C++14
+using std::enable_if_t;
+using std::index_sequence;
+using std::make_index_sequence;
+using std::index_sequence_for;
+
+#else
+
+// alias templates to reduce boilerplate
+template<bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
+// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
+
+//// START OF CODE FROM GOOGLE ABSEIL
+
+// integer_sequence
+//
+// Class template representing a compile-time integer sequence. An instantiation
+// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
+// type through its template arguments (which is a common need when
+// working with C++11 variadic templates). `absl::integer_sequence` is designed
+// to be a drop-in replacement for C++14's `std::integer_sequence`.
+//
+// Example:
+//
+//   template< class T, T... Ints >
+//   void user_function(integer_sequence<T, Ints...>);
+//
+//   int main()
+//   {
+//     // user_function's `T` will be deduced to `int` and `Ints...`
+//     // will be deduced to `0, 1, 2, 3, 4`.
+//     user_function(make_integer_sequence<int, 5>());
+//   }
+template <typename T, T... Ints>
+struct integer_sequence
+{
+    using value_type = T;
+    static constexpr std::size_t size() noexcept
+    {
+        return sizeof...(Ints);
+    }
+};
+
+// index_sequence
+//
+// A helper template for an `integer_sequence` of `size_t`,
+// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
+// `std::index_sequence`.
+template <size_t... Ints>
+using index_sequence = integer_sequence<size_t, Ints...>;
+
+namespace utility_internal
+{
+
+template <typename Seq, size_t SeqSize, size_t Rem>
+struct Extend;
+
+// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
+template <typename T, T... Ints, size_t SeqSize>
+struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
+{
+    using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
+};
+
+template <typename T, T... Ints, size_t SeqSize>
+struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
+{
+    using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
+};
+
+// Recursion helper for 'make_integer_sequence<T, N>'.
+// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
+template <typename T, size_t N>
+struct Gen
+{
+    using type =
+        typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
+};
+
+template <typename T>
+struct Gen<T, 0>
+{
+    using type = integer_sequence<T>;
+};
+
+}  // namespace utility_internal
+
+// Compile-time sequences of integers
+
+// make_integer_sequence
+//
+// This template alias is equivalent to
+// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
+// replacement for C++14's `std::make_integer_sequence`.
+template <typename T, T N>
+using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
+
+// make_index_sequence
+//
+// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
+// and is designed to be a drop-in replacement for C++14's
+// `std::make_index_sequence`.
+template <size_t N>
+using make_index_sequence = make_integer_sequence<size_t, N>;
+
+// index_sequence_for
+//
+// Converts a typename pack into an index sequence of the same length, and
+// is designed to be a drop-in replacement for C++14's
+// `std::index_sequence_for()`
+template <typename... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
+//// END OF CODE FROM GOOGLE ABSEIL
+
+#endif
+
+// dispatch utility (taken from ranges-v3)
+template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
+template<> struct priority_tag<0> {};
+
+// taken from ranges-v3
+template<typename T>
+struct static_const
+{
+    static constexpr T value{};
+};
+
+template<typename T>
+constexpr T static_const<T>::value;
+
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/meta/identity_tag.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+// dispatching helper struct
+template <class T> struct identity_tag {};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+#include <limits> // numeric_limits
+#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
+#include <utility> // declval
+#include <tuple> // tuple
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+
+
+#include <iterator> // random_access_iterator_tag
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename It, typename = void>
+struct iterator_types {};
+
+template<typename It>
+struct iterator_types <
+    It,
+    void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
+    typename It::reference, typename It::iterator_category >>
+{
+    using difference_type = typename It::difference_type;
+    using value_type = typename It::value_type;
+    using pointer = typename It::pointer;
+    using reference = typename It::reference;
+    using iterator_category = typename It::iterator_category;
+};
+
+// This is required as some compilers implement std::iterator_traits in a way that
+// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
+template<typename T, typename = void>
+struct iterator_traits
+{
+};
+
+template<typename T>
+struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
+            : iterator_types<T>
+{
+};
+
+template<typename T>
+struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
+{
+    using iterator_category = std::random_access_iterator_tag;
+    using value_type = T;
+    using difference_type = ptrdiff_t;
+    using pointer = T*;
+    using reference = T&;
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/call_std/begin.hpp>
+
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/call_std/end.hpp>
+
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+// #include <nlohmann/json_fwd.hpp>
+#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
+#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+#include <cstdint> // int64_t, uint64_t
+#include <map> // map
+#include <memory> // allocator
+#include <string> // string
+#include <vector> // vector
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+namespace nlohmann
+{
+/*!
+@brief default JSONSerializer template argument
+
+This serializer ignores the template arguments and uses ADL
+([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
+for serialization.
+*/
+template<typename T = void, typename SFINAE = void>
+struct adl_serializer;
+
+template<template<typename U, typename V, typename... Args> class ObjectType =
+         std::map,
+         template<typename U, typename... Args> class ArrayType = std::vector,
+         class StringType = std::string, class BooleanType = bool,
+         class NumberIntegerType = std::int64_t,
+         class NumberUnsignedType = std::uint64_t,
+         class NumberFloatType = double,
+         template<typename U> class AllocatorType = std::allocator,
+         template<typename T, typename SFINAE = void> class JSONSerializer =
+         adl_serializer,
+         class BinaryType = std::vector<std::uint8_t>>
+class basic_json;
+
+/*!
+@brief JSON Pointer
+
+A JSON pointer defines a string syntax for identifying a specific value
+within a JSON document. It can be used with functions `at` and
+`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
+
+@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
+
+@since version 2.0.0
+*/
+template<typename BasicJsonType>
+class json_pointer;
+
+/*!
+@brief default JSON class
+
+This type is the default specialization of the @ref basic_json class which
+uses the standard template types.
+
+@since version 1.0.0
+*/
+using json = basic_json<>;
+
+template<class Key, class T, class IgnoredLess, class Allocator>
+struct ordered_map;
+
+/*!
+@brief ordered JSON class
+
+This type preserves the insertion order of object keys.
+
+@since version 3.9.0
+*/
+using ordered_json = basic_json<nlohmann::ordered_map>;
+
+}  // namespace nlohmann
+
+#endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+
+namespace nlohmann
+{
+/*!
+@brief detail namespace with internal helper functions
+
+This namespace collects functions that should not be exposed,
+implementations of some @ref basic_json methods, and meta-programming helpers.
+
+@since version 2.1.0
+*/
+namespace detail
+{
+/////////////
+// helpers //
+/////////////
+
+// Note to maintainers:
+//
+// Every trait in this file expects a non CV-qualified type.
+// The only exceptions are in the 'aliases for detected' section
+// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
+//
+// In this case, T has to be properly CV-qualified to constraint the function arguments
+// (e.g. to_json(BasicJsonType&, const T&))
+
+template<typename> struct is_basic_json : std::false_type {};
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
+
+//////////////////////
+// json_ref helpers //
+//////////////////////
+
+template<typename>
+class json_ref;
+
+template<typename>
+struct is_json_ref : std::false_type {};
+
+template<typename T>
+struct is_json_ref<json_ref<T>> : std::true_type {};
+
+//////////////////////////
+// aliases for detected //
+//////////////////////////
+
+template<typename T>
+using mapped_type_t = typename T::mapped_type;
+
+template<typename T>
+using key_type_t = typename T::key_type;
+
+template<typename T>
+using value_type_t = typename T::value_type;
+
+template<typename T>
+using difference_type_t = typename T::difference_type;
+
+template<typename T>
+using pointer_t = typename T::pointer;
+
+template<typename T>
+using reference_t = typename T::reference;
+
+template<typename T>
+using iterator_category_t = typename T::iterator_category;
+
+template<typename T, typename... Args>
+using to_json_function = decltype(T::to_json(std::declval<Args>()...));
+
+template<typename T, typename... Args>
+using from_json_function = decltype(T::from_json(std::declval<Args>()...));
+
+template<typename T, typename U>
+using get_template_function = decltype(std::declval<T>().template get<U>());
+
+// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
+template<typename BasicJsonType, typename T, typename = void>
+struct has_from_json : std::false_type {};
+
+// trait checking if j.get<T> is valid
+// use this trait instead of std::is_constructible or std::is_convertible,
+// both rely on, or make use of implicit conversions, and thus fail when T
+// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
+template <typename BasicJsonType, typename T>
+struct is_getable
+{
+    static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
+};
+
+template<typename BasicJsonType, typename T>
+struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<void, from_json_function, serializer,
+        const BasicJsonType&, T&>::value;
+};
+
+// This trait checks if JSONSerializer<T>::from_json(json const&) exists
+// this overload is used for non-default-constructible user-defined-types
+template<typename BasicJsonType, typename T, typename = void>
+struct has_non_default_from_json : std::false_type {};
+
+template<typename BasicJsonType, typename T>
+struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<T, from_json_function, serializer,
+        const BasicJsonType&>::value;
+};
+
+// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
+// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
+template<typename BasicJsonType, typename T, typename = void>
+struct has_to_json : std::false_type {};
+
+template<typename BasicJsonType, typename T>
+struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
+        T>::value;
+};
+
+
+///////////////////
+// is_ functions //
+///////////////////
+
+// https://en.cppreference.com/w/cpp/types/conjunction
+template<class...> struct conjunction : std::true_type { };
+template<class B1> struct conjunction<B1> : B1 { };
+template<class B1, class... Bn>
+struct conjunction<B1, Bn...>
+: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+
+// https://en.cppreference.com/w/cpp/types/negation
+template<class B> struct negation : std::integral_constant < bool, !B::value > { };
+
+// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
+// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
+// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
+template <typename T>
+struct is_default_constructible : std::is_default_constructible<T> {};
+
+template <typename T1, typename T2>
+struct is_default_constructible<std::pair<T1, T2>>
+            : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
+
+template <typename T1, typename T2>
+struct is_default_constructible<const std::pair<T1, T2>>
+            : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
+
+template <typename... Ts>
+struct is_default_constructible<std::tuple<Ts...>>
+            : conjunction<is_default_constructible<Ts>...> {};
+
+template <typename... Ts>
+struct is_default_constructible<const std::tuple<Ts...>>
+            : conjunction<is_default_constructible<Ts>...> {};
+
+
+template <typename T, typename... Args>
+struct is_constructible : std::is_constructible<T, Args...> {};
+
+template <typename T1, typename T2>
+struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
+
+template <typename T1, typename T2>
+struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
+
+template <typename... Ts>
+struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
+
+template <typename... Ts>
+struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
+
+
+template<typename T, typename = void>
+struct is_iterator_traits : std::false_type {};
+
+template<typename T>
+struct is_iterator_traits<iterator_traits<T>>
+{
+  private:
+    using traits = iterator_traits<T>;
+
+  public:
+    static constexpr auto value =
+        is_detected<value_type_t, traits>::value &&
+        is_detected<difference_type_t, traits>::value &&
+        is_detected<pointer_t, traits>::value &&
+        is_detected<iterator_category_t, traits>::value &&
+        is_detected<reference_t, traits>::value;
+};
+
+template<typename T>
+struct is_range
+{
+  private:
+    using t_ref = typename std::add_lvalue_reference<T>::type;
+
+    using iterator = detected_t<result_of_begin, t_ref>;
+    using sentinel = detected_t<result_of_end, t_ref>;
+
+    // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
+    // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
+    // but reimplementing these would be too much work, as a lot of other concepts are used underneath
+    static constexpr auto is_iterator_begin =
+        is_iterator_traits<iterator_traits<iterator>>::value;
+
+  public:
+    static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
+};
+
+template<typename R>
+using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
+
+template<typename T>
+using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
+
+// The following implementation of is_complete_type is taken from
+// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
+// and is written by Xiang Fan who agreed to using it in this library.
+
+template<typename T, typename = void>
+struct is_complete_type : std::false_type {};
+
+template<typename T>
+struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
+
+template<typename BasicJsonType, typename CompatibleObjectType,
+         typename = void>
+struct is_compatible_object_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type_impl <
+    BasicJsonType, CompatibleObjectType,
+    enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
+    is_detected<key_type_t, CompatibleObjectType>::value >>
+{
+    using object_t = typename BasicJsonType::object_t;
+
+    // macOS's is_constructible does not play well with nonesuch...
+    static constexpr bool value =
+        is_constructible<typename object_t::key_type,
+        typename CompatibleObjectType::key_type>::value &&
+        is_constructible<typename object_t::mapped_type,
+        typename CompatibleObjectType::mapped_type>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type
+    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
+
+template<typename BasicJsonType, typename ConstructibleObjectType,
+         typename = void>
+struct is_constructible_object_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename ConstructibleObjectType>
+struct is_constructible_object_type_impl <
+    BasicJsonType, ConstructibleObjectType,
+    enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
+    is_detected<key_type_t, ConstructibleObjectType>::value >>
+{
+    using object_t = typename BasicJsonType::object_t;
+
+    static constexpr bool value =
+        (is_default_constructible<ConstructibleObjectType>::value &&
+         (std::is_move_assignable<ConstructibleObjectType>::value ||
+          std::is_copy_assignable<ConstructibleObjectType>::value) &&
+         (is_constructible<typename ConstructibleObjectType::key_type,
+          typename object_t::key_type>::value &&
+          std::is_same <
+          typename object_t::mapped_type,
+          typename ConstructibleObjectType::mapped_type >::value)) ||
+        (has_from_json<BasicJsonType,
+         typename ConstructibleObjectType::mapped_type>::value ||
+         has_non_default_from_json <
+         BasicJsonType,
+         typename ConstructibleObjectType::mapped_type >::value);
+};
+
+template<typename BasicJsonType, typename ConstructibleObjectType>
+struct is_constructible_object_type
+    : is_constructible_object_type_impl<BasicJsonType,
+      ConstructibleObjectType> {};
+
+template<typename BasicJsonType, typename CompatibleStringType>
+struct is_compatible_string_type
+{
+    static constexpr auto value =
+        is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
+};
+
+template<typename BasicJsonType, typename ConstructibleStringType>
+struct is_constructible_string_type
+{
+    static constexpr auto value =
+        is_constructible<ConstructibleStringType,
+        typename BasicJsonType::string_t>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
+struct is_compatible_array_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type_impl <
+    BasicJsonType, CompatibleArrayType,
+    enable_if_t <
+    is_detected<iterator_t, CompatibleArrayType>::value&&
+    is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
+// special case for types like std::filesystem::path whose iterator's value_type are themselves
+// c.f. https://github.com/nlohmann/json/pull/3073
+    !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
+{
+    static constexpr bool value =
+        is_constructible<BasicJsonType,
+        range_value_t<CompatibleArrayType>>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type
+    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
+struct is_constructible_array_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type_impl <
+    BasicJsonType, ConstructibleArrayType,
+    enable_if_t<std::is_same<ConstructibleArrayType,
+    typename BasicJsonType::value_type>::value >>
+            : std::true_type {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type_impl <
+    BasicJsonType, ConstructibleArrayType,
+    enable_if_t < !std::is_same<ConstructibleArrayType,
+    typename BasicJsonType::value_type>::value&&
+    !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
+    is_default_constructible<ConstructibleArrayType>::value&&
+(std::is_move_assignable<ConstructibleArrayType>::value ||
+ std::is_copy_assignable<ConstructibleArrayType>::value)&&
+is_detected<iterator_t, ConstructibleArrayType>::value&&
+is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
+is_detected<range_value_t, ConstructibleArrayType>::value&&
+// special case for types like std::filesystem::path whose iterator's value_type are themselves
+// c.f. https://github.com/nlohmann/json/pull/3073
+!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
+        is_complete_type <
+        detected_t<range_value_t, ConstructibleArrayType >>::value >>
+{
+    using value_type = range_value_t<ConstructibleArrayType>;
+
+    static constexpr bool value =
+        std::is_same<value_type,
+        typename BasicJsonType::array_t::value_type>::value ||
+        has_from_json<BasicJsonType,
+        value_type>::value ||
+        has_non_default_from_json <
+        BasicJsonType,
+        value_type >::value;
+};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type
+    : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType,
+         typename = void>
+struct is_compatible_integer_type_impl : std::false_type {};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type_impl <
+    RealIntegerType, CompatibleNumberIntegerType,
+    enable_if_t < std::is_integral<RealIntegerType>::value&&
+    std::is_integral<CompatibleNumberIntegerType>::value&&
+    !std::is_same<bool, CompatibleNumberIntegerType>::value >>
+{
+    // is there an assert somewhere on overflows?
+    using RealLimits = std::numeric_limits<RealIntegerType>;
+    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
+
+    static constexpr auto value =
+        is_constructible<RealIntegerType,
+        CompatibleNumberIntegerType>::value &&
+        CompatibleLimits::is_integer &&
+        RealLimits::is_signed == CompatibleLimits::is_signed;
+};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type
+    : is_compatible_integer_type_impl<RealIntegerType,
+      CompatibleNumberIntegerType> {};
+
+template<typename BasicJsonType, typename CompatibleType, typename = void>
+struct is_compatible_type_impl: std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type_impl <
+    BasicJsonType, CompatibleType,
+    enable_if_t<is_complete_type<CompatibleType>::value >>
+{
+    static constexpr bool value =
+        has_to_json<BasicJsonType, CompatibleType>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type
+    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
+
+template<typename T1, typename T2>
+struct is_constructible_tuple : std::false_type {};
+
+template<typename T1, typename... Args>
+struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
+
+// a naive helper to check if a type is an ordered_map (exploits the fact that
+// ordered_map inherits capacity() from std::vector)
+template <typename T>
+struct is_ordered_map
+{
+    using one = char;
+
+    struct two
+    {
+        char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+    };
+
+    template <typename C> static one test( decltype(&C::capacity) ) ;
+    template <typename C> static two test(...);
+
+    enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+};
+
+// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
+template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
+T conditional_static_cast(U value)
+{
+    return static_cast<T>(value);
+}
+
+template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
+T conditional_static_cast(U value)
+{
+    return value;
+}
+
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+#ifdef JSON_HAS_CPP_17
+    #include <filesystem>
+#endif
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
+    {
+        JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
+    }
+    n = nullptr;
+}
+
+// overloads for basic_json template parameters
+template < typename BasicJsonType, typename ArithmeticType,
+           enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
+                         !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+                         int > = 0 >
+void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
+{
+    switch (static_cast<value_t>(j))
+    {
+        case value_t::number_unsigned:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+            break;
+        }
+        case value_t::number_integer:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+            break;
+        }
+        case value_t::number_float:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+            break;
+        }
+
+        case value_t::null:
+        case value_t::object:
+        case value_t::array:
+        case value_t::string:
+        case value_t::boolean:
+        case value_t::binary:
+        case value_t::discarded:
+        default:
+            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
+    }
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
+    {
+        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
+    }
+    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+    {
+        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+    }
+    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template <
+    typename BasicJsonType, typename ConstructibleStringType,
+    enable_if_t <
+        is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
+        !std::is_same<typename BasicJsonType::string_t,
+                      ConstructibleStringType>::value,
+        int > = 0 >
+void from_json(const BasicJsonType& j, ConstructibleStringType& s)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+    {
+        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+    }
+
+    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType, typename EnumType,
+         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+void from_json(const BasicJsonType& j, EnumType& e)
+{
+    typename std::underlying_type<EnumType>::type val;
+    get_arithmetic_value(j, val);
+    e = static_cast<EnumType>(val);
+}
+
+// forward_list doesn't have an insert method
+template<typename BasicJsonType, typename T, typename Allocator,
+         enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
+void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+    }
+    l.clear();
+    std::transform(j.rbegin(), j.rend(),
+                   std::front_inserter(l), [](const BasicJsonType & i)
+    {
+        return i.template get<T>();
+    });
+}
+
+// valarray doesn't have an insert method
+template<typename BasicJsonType, typename T,
+         enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
+void from_json(const BasicJsonType& j, std::valarray<T>& l)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+    }
+    l.resize(j.size());
+    std::transform(j.begin(), j.end(), std::begin(l),
+                   [](const BasicJsonType & elem)
+    {
+        return elem.template get<T>();
+    });
+}
+
+template<typename BasicJsonType, typename T, std::size_t N>
+auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+-> decltype(j.template get<T>(), void())
+{
+    for (std::size_t i = 0; i < N; ++i)
+    {
+        arr[i] = j.at(i).template get<T>();
+    }
+}
+
+template<typename BasicJsonType>
+void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
+{
+    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
+}
+
+template<typename BasicJsonType, typename T, std::size_t N>
+auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
+                          priority_tag<2> /*unused*/)
+-> decltype(j.template get<T>(), void())
+{
+    for (std::size_t i = 0; i < N; ++i)
+    {
+        arr[i] = j.at(i).template get<T>();
+    }
+}
+
+template<typename BasicJsonType, typename ConstructibleArrayType,
+         enable_if_t<
+             std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
+             int> = 0>
+auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
+-> decltype(
+    arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
+    j.template get<typename ConstructibleArrayType::value_type>(),
+    void())
+{
+    using std::end;
+
+    ConstructibleArrayType ret;
+    ret.reserve(j.size());
+    std::transform(j.begin(), j.end(),
+                   std::inserter(ret, end(ret)), [](const BasicJsonType & i)
+    {
+        // get<BasicJsonType>() returns *this, this won't call a from_json
+        // method when value_type is BasicJsonType
+        return i.template get<typename ConstructibleArrayType::value_type>();
+    });
+    arr = std::move(ret);
+}
+
+template<typename BasicJsonType, typename ConstructibleArrayType,
+         enable_if_t<
+             std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
+             int> = 0>
+void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
+                          priority_tag<0> /*unused*/)
+{
+    using std::end;
+
+    ConstructibleArrayType ret;
+    std::transform(
+        j.begin(), j.end(), std::inserter(ret, end(ret)),
+        [](const BasicJsonType & i)
+    {
+        // get<BasicJsonType>() returns *this, this won't call a from_json
+        // method when value_type is BasicJsonType
+        return i.template get<typename ConstructibleArrayType::value_type>();
+    });
+    arr = std::move(ret);
+}
+
+template < typename BasicJsonType, typename ConstructibleArrayType,
+           enable_if_t <
+               is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
+               !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
+               !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
+               !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
+               !is_basic_json<ConstructibleArrayType>::value,
+               int > = 0 >
+auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
+-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
+j.template get<typename ConstructibleArrayType::value_type>(),
+void())
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+    }
+
+    from_json_array_impl(j, arr, priority_tag<3> {});
+}
+
+template < typename BasicJsonType, typename T, std::size_t... Idx >
+std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
+        identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
+{
+    return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
+}
+
+template < typename BasicJsonType, typename T, std::size_t N >
+auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
+-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+    }
+
+    return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
+    {
+        JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
+    }
+
+    bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
+}
+
+template<typename BasicJsonType, typename ConstructibleObjectType,
+         enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
+void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
+    {
+        JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
+    }
+
+    ConstructibleObjectType ret;
+    const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
+    using value_type = typename ConstructibleObjectType::value_type;
+    std::transform(
+        inner_object->begin(), inner_object->end(),
+        std::inserter(ret, ret.begin()),
+        [](typename BasicJsonType::object_t::value_type const & p)
+    {
+        return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
+    });
+    obj = std::move(ret);
+}
+
+// overload for arithmetic types, not chosen for basic_json template arguments
+// (BooleanType, etc..); note: Is it really necessary to provide explicit
+// overloads for boolean_t etc. in case of a custom BooleanType which is not
+// an arithmetic type?
+template < typename BasicJsonType, typename ArithmeticType,
+           enable_if_t <
+               std::is_arithmetic<ArithmeticType>::value&&
+               !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
+               !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
+               !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
+               !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+               int > = 0 >
+void from_json(const BasicJsonType& j, ArithmeticType& val)
+{
+    switch (static_cast<value_t>(j))
+    {
+        case value_t::number_unsigned:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+            break;
+        }
+        case value_t::number_integer:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+            break;
+        }
+        case value_t::number_float:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+            break;
+        }
+        case value_t::boolean:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
+            break;
+        }
+
+        case value_t::null:
+        case value_t::object:
+        case value_t::array:
+        case value_t::string:
+        case value_t::binary:
+        case value_t::discarded:
+        default:
+            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
+    }
+}
+
+template<typename BasicJsonType, typename... Args, std::size_t... Idx>
+std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
+{
+    return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
+}
+
+template < typename BasicJsonType, class A1, class A2 >
+std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
+{
+    return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
+            std::forward<BasicJsonType>(j).at(1).template get<A2>()};
+}
+
+template<typename BasicJsonType, typename A1, typename A2>
+void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
+{
+    p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
+}
+
+template<typename BasicJsonType, typename... Args>
+std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
+{
+    return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
+}
+
+template<typename BasicJsonType, typename... Args>
+void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
+{
+    t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
+}
+
+template<typename BasicJsonType, typename TupleRelated>
+auto from_json(BasicJsonType&& j, TupleRelated&& t)
+-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+    }
+
+    return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
+}
+
+template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
+           typename = enable_if_t < !std::is_constructible <
+                                        typename BasicJsonType::string_t, Key >::value >>
+void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+    }
+    m.clear();
+    for (const auto& p : j)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
+        {
+            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
+        }
+        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+    }
+}
+
+template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
+           typename = enable_if_t < !std::is_constructible <
+                                        typename BasicJsonType::string_t, Key >::value >>
+void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+    }
+    m.clear();
+    for (const auto& p : j)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
+        {
+            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
+        }
+        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+    }
+}
+
+#ifdef JSON_HAS_CPP_17
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, std::filesystem::path& p)
+{
+    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+    {
+        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+    }
+    p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+#endif
+
+struct from_json_fn
+{
+    template<typename BasicJsonType, typename T>
+    auto operator()(const BasicJsonType& j, T&& val) const
+    noexcept(noexcept(from_json(j, std::forward<T>(val))))
+    -> decltype(from_json(j, std::forward<T>(val)))
+    {
+        return from_json(j, std::forward<T>(val));
+    }
+};
+}  // namespace detail
+
+/// namespace to hold default `from_json` function
+/// to see why this is required:
+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
+namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
+{
+constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
+} // namespace
+} // namespace nlohmann
+
+// #include <nlohmann/detail/conversions/to_json.hpp>
+
+
+#include <algorithm> // copy
+#include <iterator> // begin, end
+#include <string> // string
+#include <tuple> // tuple, get
+#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
+#include <utility> // move, forward, declval, pair
+#include <valarray> // valarray
+#include <vector> // vector
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+
+
+#include <cstddef> // size_t
+#include <iterator> // input_iterator_tag
+#include <string> // string, to_string
+#include <tuple> // tuple_size, get, tuple_element
+#include <utility> // move
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename string_type>
+void int_to_string( string_type& target, std::size_t value )
+{
+    // For ADL
+    using std::to_string;
+    target = to_string(value);
+}
+template<typename IteratorType> class iteration_proxy_value
+{
+  public:
+    using difference_type = std::ptrdiff_t;
+    using value_type = iteration_proxy_value;
+    using pointer = value_type * ;
+    using reference = value_type & ;
+    using iterator_category = std::input_iterator_tag;
+    using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
+
+  private:
+    /// the iterator
+    IteratorType anchor;
+    /// an index for arrays (used to create key names)
+    std::size_t array_index = 0;
+    /// last stringified array index
+    mutable std::size_t array_index_last = 0;
+    /// a string representation of the array index
+    mutable string_type array_index_str = "0";
+    /// an empty string (to return a reference for primitive values)
+    const string_type empty_str{};
+
+  public:
+    explicit iteration_proxy_value(IteratorType it) noexcept
+        : anchor(std::move(it))
+    {}
+
+    /// dereference operator (needed for range-based for)
+    iteration_proxy_value& operator*()
+    {
+        return *this;
+    }
+
+    /// increment operator (needed for range-based for)
+    iteration_proxy_value& operator++()
+    {
+        ++anchor;
+        ++array_index;
+
+        return *this;
+    }
+
+    /// equality operator (needed for InputIterator)
+    bool operator==(const iteration_proxy_value& o) const
+    {
+        return anchor == o.anchor;
+    }
+
+    /// inequality operator (needed for range-based for)
+    bool operator!=(const iteration_proxy_value& o) const
+    {
+        return anchor != o.anchor;
+    }
+
+    /// return key of the iterator
+    const string_type& key() const
+    {
+        JSON_ASSERT(anchor.m_object != nullptr);
+
+        switch (anchor.m_object->type())
+        {
+            // use integer array index as key
+            case value_t::array:
+            {
+                if (array_index != array_index_last)
+                {
+                    int_to_string( array_index_str, array_index );
+                    array_index_last = array_index;
+                }
+                return array_index_str;
+            }
+
+            // use key from the object
+            case value_t::object:
+                return anchor.key();
+
+            // use an empty key for all primitive types
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                return empty_str;
+        }
+    }
+
+    /// return value of the iterator
+    typename IteratorType::reference value() const
+    {
+        return anchor.value();
+    }
+};
+
+/// proxy class for the items() function
+template<typename IteratorType> class iteration_proxy
+{
+  private:
+    /// the container to iterate
+    typename IteratorType::reference container;
+
+  public:
+    /// construct iteration proxy from a container
+    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
+        : container(cont) {}
+
+    /// return iterator begin (needed for range-based for)
+    iteration_proxy_value<IteratorType> begin() noexcept
+    {
+        return iteration_proxy_value<IteratorType>(container.begin());
+    }
+
+    /// return iterator end (needed for range-based for)
+    iteration_proxy_value<IteratorType> end() noexcept
+    {
+        return iteration_proxy_value<IteratorType>(container.end());
+    }
+};
+// Structured Bindings Support
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
+auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
+{
+    return i.key();
+}
+// Structured Bindings Support
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
+auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
+{
+    return i.value();
+}
+}  // namespace detail
+}  // namespace nlohmann
+
+// The Addition to the STD Namespace is required to add
+// Structured Bindings Support to the iteration_proxy_value class
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+namespace std
+{
+#if defined(__clang__)
+    // Fix: https://github.com/nlohmann/json/issues/1401
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wmismatched-tags"
+#endif
+template<typename IteratorType>
+class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
+            : public std::integral_constant<std::size_t, 2> {};
+
+template<std::size_t N, typename IteratorType>
+class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
+{
+  public:
+    using type = decltype(
+                     get<N>(std::declval <
+                            ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
+};
+#if defined(__clang__)
+    #pragma clang diagnostic pop
+#endif
+} // namespace std
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+#ifdef JSON_HAS_CPP_17
+    #include <filesystem>
+#endif
+
+namespace nlohmann
+{
+namespace detail
+{
+//////////////////
+// constructors //
+//////////////////
+
+/*
+ * Note all external_constructor<>::construct functions need to call
+ * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
+ * allocated value (e.g., a string). See bug issue
+ * https://github.com/nlohmann/json/issues/2865 for more information.
+ */
+
+template<value_t> struct external_constructor;
+
+template<>
+struct external_constructor<value_t::boolean>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::boolean;
+        j.m_value = b;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::string>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::string;
+        j.m_value = s;
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::string;
+        j.m_value = std::move(s);
+        j.assert_invariant();
+    }
+
+    template < typename BasicJsonType, typename CompatibleStringType,
+               enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
+                             int > = 0 >
+    static void construct(BasicJsonType& j, const CompatibleStringType& str)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::string;
+        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::binary>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::binary;
+        j.m_value = typename BasicJsonType::binary_t(b);
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::binary;
+        j.m_value = typename BasicJsonType::binary_t(std::move(b));
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_float>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::number_float;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_unsigned>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::number_unsigned;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_integer>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::number_integer;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::array>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value = arr;
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value = std::move(arr);
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template < typename BasicJsonType, typename CompatibleArrayType,
+               enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
+                             int > = 0 >
+    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
+    {
+        using std::begin;
+        using std::end;
+
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value = value_t::array;
+        j.m_value.array->reserve(arr.size());
+        for (const bool x : arr)
+        {
+            j.m_value.array->push_back(x);
+            j.set_parent(j.m_value.array->back());
+        }
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType, typename T,
+             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::array;
+        j.m_value = value_t::array;
+        j.m_value.array->resize(arr.size());
+        if (arr.size() > 0)
+        {
+            std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
+        }
+        j.set_parents();
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::object>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::object;
+        j.m_value = obj;
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+    {
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::object;
+        j.m_value = std::move(obj);
+        j.set_parents();
+        j.assert_invariant();
+    }
+
+    template < typename BasicJsonType, typename CompatibleObjectType,
+               enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
+    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
+    {
+        using std::begin;
+        using std::end;
+
+        j.m_value.destroy(j.m_type);
+        j.m_type = value_t::object;
+        j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
+        j.set_parents();
+        j.assert_invariant();
+    }
+};
+
+/////////////
+// to_json //
+/////////////
+
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
+void to_json(BasicJsonType& j, T b) noexcept
+{
+    external_constructor<value_t::boolean>::construct(j, b);
+}
+
+template<typename BasicJsonType, typename CompatibleString,
+         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
+void to_json(BasicJsonType& j, const CompatibleString& s)
+{
+    external_constructor<value_t::string>::construct(j, s);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+{
+    external_constructor<value_t::string>::construct(j, std::move(s));
+}
+
+template<typename BasicJsonType, typename FloatType,
+         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
+void to_json(BasicJsonType& j, FloatType val) noexcept
+{
+    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
+         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
+void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
+{
+    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberIntegerType,
+         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
+void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
+{
+    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
+}
+
+template<typename BasicJsonType, typename EnumType,
+         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+void to_json(BasicJsonType& j, EnumType e) noexcept
+{
+    using underlying_type = typename std::underlying_type<EnumType>::type;
+    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, const std::vector<bool>& e)
+{
+    external_constructor<value_t::array>::construct(j, e);
+}
+
+template < typename BasicJsonType, typename CompatibleArrayType,
+           enable_if_t < is_compatible_array_type<BasicJsonType,
+                         CompatibleArrayType>::value&&
+                         !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
+                         !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
+                         !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
+                         !is_basic_json<CompatibleArrayType>::value,
+                         int > = 0 >
+void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
+{
+    external_constructor<value_t::array>::construct(j, arr);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
+{
+    external_constructor<value_t::binary>::construct(j, bin);
+}
+
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+void to_json(BasicJsonType& j, const std::valarray<T>& arr)
+{
+    external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+{
+    external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template < typename BasicJsonType, typename CompatibleObjectType,
+           enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
+void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
+{
+    external_constructor<value_t::object>::construct(j, obj);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+{
+    external_constructor<value_t::object>::construct(j, std::move(obj));
+}
+
+template <
+    typename BasicJsonType, typename T, std::size_t N,
+    enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
+                  const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+                  int > = 0 >
+void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+{
+    external_constructor<value_t::array>::construct(j, arr);
+}
+
+template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
+void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
+{
+    j = { p.first, p.second };
+}
+
+// for https://github.com/nlohmann/json/pull/1134
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
+void to_json(BasicJsonType& j, const T& b)
+{
+    j = { {b.key(), b.value()} };
+}
+
+template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
+void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
+{
+    j = { std::get<Idx>(t)... };
+}
+
+template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
+void to_json(BasicJsonType& j, const T& t)
+{
+    to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
+}
+
+#ifdef JSON_HAS_CPP_17
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, const std::filesystem::path& p)
+{
+    j = p.string();
+}
+#endif
+
+struct to_json_fn
+{
+    template<typename BasicJsonType, typename T>
+    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
+    -> decltype(to_json(j, std::forward<T>(val)), void())
+    {
+        return to_json(j, std::forward<T>(val));
+    }
+};
+}  // namespace detail
+
+/// namespace to hold default `to_json` function
+/// to see why this is required:
+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
+namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
+{
+constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
+} // namespace
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/identity_tag.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+
+template<typename ValueType, typename>
+struct adl_serializer
+{
+    /*!
+    @brief convert a JSON value to any value type
+
+    This function is usually called by the `get()` function of the
+    @ref basic_json class (either explicit or via conversion operators).
+
+    @note This function is chosen for default-constructible value types.
+
+    @param[in] j        JSON value to read from
+    @param[in,out] val  value to write to
+    */
+    template<typename BasicJsonType, typename TargetType = ValueType>
+    static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
+        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
+    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
+    {
+        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
+    }
+
+    /*!
+    @brief convert a JSON value to any value type
+
+    This function is usually called by the `get()` function of the
+    @ref basic_json class (either explicit or via conversion operators).
+
+    @note This function is chosen for value types which are not default-constructible.
+
+    @param[in] j  JSON value to read from
+
+    @return copy of the JSON value, converted to @a ValueType
+    */
+    template<typename BasicJsonType, typename TargetType = ValueType>
+    static auto from_json(BasicJsonType && j) noexcept(
+    noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
+    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
+    {
+        return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
+    }
+
+    /*!
+    @brief convert any value type to a JSON value
+
+    This function is usually called by the constructors of the @ref basic_json
+    class.
+
+    @param[in,out] j  JSON value to write to
+    @param[in] val    value to read from
+    */
+    template<typename BasicJsonType, typename TargetType = ValueType>
+    static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
+        noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
+    -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
+    {
+        ::nlohmann::to_json(j, std::forward<TargetType>(val));
+    }
+};
+}  // namespace nlohmann
+
+// #include <nlohmann/byte_container_with_subtype.hpp>
+
+
+#include <cstdint> // uint8_t, uint64_t
+#include <tuple> // tie
+#include <utility> // move
+
+namespace nlohmann
+{
+
+/*!
+@brief an internal type for a backed binary type
+
+This type extends the template parameter @a BinaryType provided to `basic_json`
+with a subtype used by BSON and MessagePack. This type exists so that the user
+does not have to specify a type themselves with a specific naming scheme in
+order to override the binary type.
+
+@tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
+                   default)
+
+@since version 3.8.0; changed type of subtypes to std::uint64_t in 3.10.0.
+*/
+template<typename BinaryType>
+class byte_container_with_subtype : public BinaryType
+{
+  public:
+    /// the type of the underlying container
+    using container_type = BinaryType;
+    /// the type of the subtype
+    using subtype_type = std::uint64_t;
+
+    byte_container_with_subtype() noexcept(noexcept(container_type()))
+        : container_type()
+    {}
+
+    byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
+        : container_type(b)
+    {}
+
+    byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
+        : container_type(std::move(b))
+    {}
+
+    byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
+        : container_type(b)
+        , m_subtype(subtype_)
+        , m_has_subtype(true)
+    {}
+
+    byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
+        : container_type(std::move(b))
+        , m_subtype(subtype_)
+        , m_has_subtype(true)
+    {}
+
+    bool operator==(const byte_container_with_subtype& rhs) const
+    {
+        return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
+               std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
+    }
+
+    bool operator!=(const byte_container_with_subtype& rhs) const
+    {
+        return !(rhs == *this);
+    }
+
+    /*!
+    @brief sets the binary subtype
+
+    Sets the binary subtype of the value, also flags a binary JSON value as
+    having a subtype, which has implications for serialization.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @sa see @ref subtype() -- return the binary subtype
+    @sa see @ref clear_subtype() -- clears the binary subtype
+    @sa see @ref has_subtype() -- returns whether or not the binary value has a
+    subtype
+
+    @since version 3.8.0
+    */
+    void set_subtype(subtype_type subtype_) noexcept
+    {
+        m_subtype = subtype_;
+        m_has_subtype = true;
+    }
+
+    /*!
+    @brief return the binary subtype
+
+    Returns the numerical subtype of the value if it has a subtype. If it does
+    not have a subtype, this function will return subtype_type(-1) as a sentinel
+    value.
+
+    @return the numerical subtype of the binary value
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @sa see @ref set_subtype() -- sets the binary subtype
+    @sa see @ref clear_subtype() -- clears the binary subtype
+    @sa see @ref has_subtype() -- returns whether or not the binary value has a
+    subtype
+
+    @since version 3.8.0; fixed return value to properly return
+           subtype_type(-1) as documented in version 3.10.0
+    */
+    constexpr subtype_type subtype() const noexcept
+    {
+        return m_has_subtype ? m_subtype : subtype_type(-1);
+    }
+
+    /*!
+    @brief return whether the value has a subtype
+
+    @return whether the value has a subtype
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @sa see @ref subtype() -- return the binary subtype
+    @sa see @ref set_subtype() -- sets the binary subtype
+    @sa see @ref clear_subtype() -- clears the binary subtype
+
+    @since version 3.8.0
+    */
+    constexpr bool has_subtype() const noexcept
+    {
+        return m_has_subtype;
+    }
+
+    /*!
+    @brief clears the binary subtype
+
+    Clears the binary subtype and flags the value as not having a subtype, which
+    has implications for serialization; for instance MessagePack will prefer the
+    bin family over the ext family.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @sa see @ref subtype() -- return the binary subtype
+    @sa see @ref set_subtype() -- sets the binary subtype
+    @sa see @ref has_subtype() -- returns whether or not the binary value has a
+    subtype
+
+    @since version 3.8.0
+    */
+    void clear_subtype() noexcept
+    {
+        m_subtype = 0;
+        m_has_subtype = false;
+    }
+
+  private:
+    subtype_type m_subtype = 0;
+    bool m_has_subtype = false;
+};
+
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/conversions/from_json.hpp>
+
+// #include <nlohmann/detail/conversions/to_json.hpp>
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/hash.hpp>
+
+
+#include <cstdint> // uint8_t
+#include <cstddef> // size_t
+#include <functional> // hash
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+// boost::hash_combine
+inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
+{
+    seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
+    return seed;
+}
+
+/*!
+@brief hash a JSON value
+
+The hash function tries to rely on std::hash where possible. Furthermore, the
+type of the JSON value is taken into account to have different hash values for
+null, 0, 0U, and false, etc.
+
+@tparam BasicJsonType basic_json specialization
+@param j JSON value to hash
+@return hash value of j
+*/
+template<typename BasicJsonType>
+std::size_t hash(const BasicJsonType& j)
+{
+    using string_t = typename BasicJsonType::string_t;
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+
+    const auto type = static_cast<std::size_t>(j.type());
+    switch (j.type())
+    {
+        case BasicJsonType::value_t::null:
+        case BasicJsonType::value_t::discarded:
+        {
+            return combine(type, 0);
+        }
+
+        case BasicJsonType::value_t::object:
+        {
+            auto seed = combine(type, j.size());
+            for (const auto& element : j.items())
+            {
+                const auto h = std::hash<string_t> {}(element.key());
+                seed = combine(seed, h);
+                seed = combine(seed, hash(element.value()));
+            }
+            return seed;
+        }
+
+        case BasicJsonType::value_t::array:
+        {
+            auto seed = combine(type, j.size());
+            for (const auto& element : j)
+            {
+                seed = combine(seed, hash(element));
+            }
+            return seed;
+        }
+
+        case BasicJsonType::value_t::string:
+        {
+            const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::boolean:
+        {
+            const auto h = std::hash<bool> {}(j.template get<bool>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::number_integer:
+        {
+            const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::number_unsigned:
+        {
+            const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::number_float:
+        {
+            const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
+            return combine(type, h);
+        }
+
+        case BasicJsonType::value_t::binary:
+        {
+            auto seed = combine(type, j.get_binary().size());
+            const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
+            seed = combine(seed, h);
+            seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
+            for (const auto byte : j.get_binary())
+            {
+                seed = combine(seed, std::hash<std::uint8_t> {}(byte));
+            }
+            return seed;
+        }
+
+        default:                   // LCOV_EXCL_LINE
+            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+            return 0;              // LCOV_EXCL_LINE
+    }
+}
+
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/input/binary_reader.hpp>
+
+
+#include <algorithm> // generate_n
+#include <array> // array
+#include <cmath> // ldexp
+#include <cstddef> // size_t
+#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstdio> // snprintf
+#include <cstring> // memcpy
+#include <iterator> // back_inserter
+#include <limits> // numeric_limits
+#include <string> // char_traits, string
+#include <utility> // make_pair, move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+
+#include <array> // array
+#include <cstddef> // size_t
+#include <cstring> // strlen
+#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
+#include <memory> // shared_ptr, make_shared, addressof
+#include <numeric> // accumulate
+#include <string> // string, char_traits
+#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
+#include <utility> // pair, declval
+
+#ifndef JSON_NO_IO
+    #include <cstdio>   // FILE *
+    #include <istream>  // istream
+#endif                  // JSON_NO_IO
+
+// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/// the supported input formats
+enum class input_format_t { json, cbor, msgpack, ubjson, bson };
+
+////////////////////
+// input adapters //
+////////////////////
+
+#ifndef JSON_NO_IO
+/*!
+Input adapter for stdio file access. This adapter read only 1 byte and do not use any
+ buffer. This adapter is a very low level adapter.
+*/
+class file_input_adapter
+{
+  public:
+    using char_type = char;
+
+    JSON_HEDLEY_NON_NULL(2)
+    explicit file_input_adapter(std::FILE* f) noexcept
+        : m_file(f)
+    {}
+
+    // make class move-only
+    file_input_adapter(const file_input_adapter&) = delete;
+    file_input_adapter(file_input_adapter&&) noexcept = default;
+    file_input_adapter& operator=(const file_input_adapter&) = delete;
+    file_input_adapter& operator=(file_input_adapter&&) = delete;
+    ~file_input_adapter() = default;
+
+    std::char_traits<char>::int_type get_character() noexcept
+    {
+        return std::fgetc(m_file);
+    }
+
+  private:
+    /// the file pointer to read from
+    std::FILE* m_file;
+};
+
+
+/*!
+Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
+beginning of input. Does not support changing the underlying std::streambuf
+in mid-input. Maintains underlying std::istream and std::streambuf to support
+subsequent use of standard std::istream operations to process any input
+characters following those used in parsing the JSON input.  Clears the
+std::istream flags; any input errors (e.g., EOF) will be detected by the first
+subsequent call for input from the std::istream.
+*/
+class input_stream_adapter
+{
+  public:
+    using char_type = char;
+
+    ~input_stream_adapter()
+    {
+        // clear stream flags; we use underlying streambuf I/O, do not
+        // maintain ifstream flags, except eof
+        if (is != nullptr)
+        {
+            is->clear(is->rdstate() & std::ios::eofbit);
+        }
+    }
+
+    explicit input_stream_adapter(std::istream& i)
+        : is(&i), sb(i.rdbuf())
+    {}
+
+    // delete because of pointer members
+    input_stream_adapter(const input_stream_adapter&) = delete;
+    input_stream_adapter& operator=(input_stream_adapter&) = delete;
+    input_stream_adapter& operator=(input_stream_adapter&&) = delete;
+
+    input_stream_adapter(input_stream_adapter&& rhs) noexcept
+        : is(rhs.is), sb(rhs.sb)
+    {
+        rhs.is = nullptr;
+        rhs.sb = nullptr;
+    }
+
+    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
+    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
+    // end up as the same value, eg. 0xFFFFFFFF.
+    std::char_traits<char>::int_type get_character()
+    {
+        auto res = sb->sbumpc();
+        // set eof manually, as we don't use the istream interface.
+        if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
+        {
+            is->clear(is->rdstate() | std::ios::eofbit);
+        }
+        return res;
+    }
+
+  private:
+    /// the associated input stream
+    std::istream* is = nullptr;
+    std::streambuf* sb = nullptr;
+};
+#endif  // JSON_NO_IO
+
+// General-purpose iterator-based adapter. It might not be as fast as
+// theoretically possible for some containers, but it is extremely versatile.
+template<typename IteratorType>
+class iterator_input_adapter
+{
+  public:
+    using char_type = typename std::iterator_traits<IteratorType>::value_type;
+
+    iterator_input_adapter(IteratorType first, IteratorType last)
+        : current(std::move(first)), end(std::move(last))
+    {}
+
+    typename std::char_traits<char_type>::int_type get_character()
+    {
+        if (JSON_HEDLEY_LIKELY(current != end))
+        {
+            auto result = std::char_traits<char_type>::to_int_type(*current);
+            std::advance(current, 1);
+            return result;
+        }
+
+        return std::char_traits<char_type>::eof();
+    }
+
+  private:
+    IteratorType current;
+    IteratorType end;
+
+    template<typename BaseInputAdapter, size_t T>
+    friend struct wide_string_input_helper;
+
+    bool empty() const
+    {
+        return current == end;
+    }
+};
+
+
+template<typename BaseInputAdapter, size_t T>
+struct wide_string_input_helper;
+
+template<typename BaseInputAdapter>
+struct wide_string_input_helper<BaseInputAdapter, 4>
+{
+    // UTF-32
+    static void fill_buffer(BaseInputAdapter& input,
+                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
+                            size_t& utf8_bytes_index,
+                            size_t& utf8_bytes_filled)
+    {
+        utf8_bytes_index = 0;
+
+        if (JSON_HEDLEY_UNLIKELY(input.empty()))
+        {
+            utf8_bytes[0] = std::char_traits<char>::eof();
+            utf8_bytes_filled = 1;
+        }
+        else
+        {
+            // get the current character
+            const auto wc = input.get_character();
+
+            // UTF-32 to UTF-8 encoding
+            if (wc < 0x80)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+            else if (wc <= 0x7FF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 2;
+            }
+            else if (wc <= 0xFFFF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 3;
+            }
+            else if (wc <= 0x10FFFF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+                utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 4;
+            }
+            else
+            {
+                // unknown character
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+        }
+    }
+};
+
+template<typename BaseInputAdapter>
+struct wide_string_input_helper<BaseInputAdapter, 2>
+{
+    // UTF-16
+    static void fill_buffer(BaseInputAdapter& input,
+                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
+                            size_t& utf8_bytes_index,
+                            size_t& utf8_bytes_filled)
+    {
+        utf8_bytes_index = 0;
+
+        if (JSON_HEDLEY_UNLIKELY(input.empty()))
+        {
+            utf8_bytes[0] = std::char_traits<char>::eof();
+            utf8_bytes_filled = 1;
+        }
+        else
+        {
+            // get the current character
+            const auto wc = input.get_character();
+
+            // UTF-16 to UTF-8 encoding
+            if (wc < 0x80)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+            else if (wc <= 0x7FF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 2;
+            }
+            else if (0xD800 > wc || wc >= 0xE000)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+                utf8_bytes_filled = 3;
+            }
+            else
+            {
+                if (JSON_HEDLEY_UNLIKELY(!input.empty()))
+                {
+                    const auto wc2 = static_cast<unsigned int>(input.get_character());
+                    const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
+                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
+                    utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
+                    utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
+                    utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
+                    utf8_bytes_filled = 4;
+                }
+                else
+                {
+                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                    utf8_bytes_filled = 1;
+                }
+            }
+        }
+    }
+};
+
+// Wraps another input apdater to convert wide character types into individual bytes.
+template<typename BaseInputAdapter, typename WideCharType>
+class wide_string_input_adapter
+{
+  public:
+    using char_type = char;
+
+    wide_string_input_adapter(BaseInputAdapter base)
+        : base_adapter(base) {}
+
+    typename std::char_traits<char>::int_type get_character() noexcept
+    {
+        // check if buffer needs to be filled
+        if (utf8_bytes_index == utf8_bytes_filled)
+        {
+            fill_buffer<sizeof(WideCharType)>();
+
+            JSON_ASSERT(utf8_bytes_filled > 0);
+            JSON_ASSERT(utf8_bytes_index == 0);
+        }
+
+        // use buffer
+        JSON_ASSERT(utf8_bytes_filled > 0);
+        JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
+        return utf8_bytes[utf8_bytes_index++];
+    }
+
+  private:
+    BaseInputAdapter base_adapter;
+
+    template<size_t T>
+    void fill_buffer()
+    {
+        wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
+    }
+
+    /// a buffer for UTF-8 bytes
+    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
+
+    /// index to the utf8_codes array for the next valid byte
+    std::size_t utf8_bytes_index = 0;
+    /// number of valid bytes in the utf8_codes array
+    std::size_t utf8_bytes_filled = 0;
+};
+
+
+template<typename IteratorType, typename Enable = void>
+struct iterator_input_adapter_factory
+{
+    using iterator_type = IteratorType;
+    using char_type = typename std::iterator_traits<iterator_type>::value_type;
+    using adapter_type = iterator_input_adapter<iterator_type>;
+
+    static adapter_type create(IteratorType first, IteratorType last)
+    {
+        return adapter_type(std::move(first), std::move(last));
+    }
+};
+
+template<typename T>
+struct is_iterator_of_multibyte
+{
+    using value_type = typename std::iterator_traits<T>::value_type;
+    enum
+    {
+        value = sizeof(value_type) > 1
+    };
+};
+
+template<typename IteratorType>
+struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
+{
+    using iterator_type = IteratorType;
+    using char_type = typename std::iterator_traits<iterator_type>::value_type;
+    using base_adapter_type = iterator_input_adapter<iterator_type>;
+    using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
+
+    static adapter_type create(IteratorType first, IteratorType last)
+    {
+        return adapter_type(base_adapter_type(std::move(first), std::move(last)));
+    }
+};
+
+// General purpose iterator-based input
+template<typename IteratorType>
+typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
+{
+    using factory_type = iterator_input_adapter_factory<IteratorType>;
+    return factory_type::create(first, last);
+}
+
+// Convenience shorthand from container to iterator
+// Enables ADL on begin(container) and end(container)
+// Encloses the using declarations in namespace for not to leak them to outside scope
+
+namespace container_input_adapter_factory_impl
+{
+
+using std::begin;
+using std::end;
+
+template<typename ContainerType, typename Enable = void>
+struct container_input_adapter_factory {};
+
+template<typename ContainerType>
+struct container_input_adapter_factory< ContainerType,
+       void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
+       {
+           using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
+
+           static adapter_type create(const ContainerType& container)
+{
+    return input_adapter(begin(container), end(container));
+}
+       };
+
+} // namespace container_input_adapter_factory_impl
+
+template<typename ContainerType>
+typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
+{
+    return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
+}
+
+#ifndef JSON_NO_IO
+// Special cases with fast paths
+inline file_input_adapter input_adapter(std::FILE* file)
+{
+    return file_input_adapter(file);
+}
+
+inline input_stream_adapter input_adapter(std::istream& stream)
+{
+    return input_stream_adapter(stream);
+}
+
+inline input_stream_adapter input_adapter(std::istream&& stream)
+{
+    return input_stream_adapter(stream);
+}
+#endif  // JSON_NO_IO
+
+using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
+
+// Null-delimited strings, and the like.
+template < typename CharT,
+           typename std::enable_if <
+               std::is_pointer<CharT>::value&&
+               !std::is_array<CharT>::value&&
+               std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
+               sizeof(typename std::remove_pointer<CharT>::type) == 1,
+               int >::type = 0 >
+contiguous_bytes_input_adapter input_adapter(CharT b)
+{
+    auto length = std::strlen(reinterpret_cast<const char*>(b));
+    const auto* ptr = reinterpret_cast<const char*>(b);
+    return input_adapter(ptr, ptr + length);
+}
+
+template<typename T, std::size_t N>
+auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+{
+    return input_adapter(array, array + N);
+}
+
+// This class only handles inputs of input_buffer_adapter type.
+// It's required so that expressions like {ptr, len} can be implicitly casted
+// to the correct adapter.
+class span_input_adapter
+{
+  public:
+    template < typename CharT,
+               typename std::enable_if <
+                   std::is_pointer<CharT>::value&&
+                   std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
+                   sizeof(typename std::remove_pointer<CharT>::type) == 1,
+                   int >::type = 0 >
+    span_input_adapter(CharT b, std::size_t l)
+        : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
+
+    template<class IteratorType,
+             typename std::enable_if<
+                 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
+                 int>::type = 0>
+    span_input_adapter(IteratorType first, IteratorType last)
+        : ia(input_adapter(first, last)) {}
+
+    contiguous_bytes_input_adapter&& get()
+    {
+        return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
+    }
+
+  private:
+    contiguous_bytes_input_adapter ia;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/input/json_sax.hpp>
+
+
+#include <cstddef>
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+
+/*!
+@brief SAX interface
+
+This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
+Each function is called in different situations while the input is parsed. The
+boolean return value informs the parser whether to continue processing the
+input.
+*/
+template<typename BasicJsonType>
+struct json_sax
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+
+    /*!
+    @brief a null value was read
+    @return whether parsing should proceed
+    */
+    virtual bool null() = 0;
+
+    /*!
+    @brief a boolean value was read
+    @param[in] val  boolean value
+    @return whether parsing should proceed
+    */
+    virtual bool boolean(bool val) = 0;
+
+    /*!
+    @brief an integer number was read
+    @param[in] val  integer value
+    @return whether parsing should proceed
+    */
+    virtual bool number_integer(number_integer_t val) = 0;
+
+    /*!
+    @brief an unsigned integer number was read
+    @param[in] val  unsigned integer value
+    @return whether parsing should proceed
+    */
+    virtual bool number_unsigned(number_unsigned_t val) = 0;
+
+    /*!
+    @brief an floating-point number was read
+    @param[in] val  floating-point value
+    @param[in] s    raw token value
+    @return whether parsing should proceed
+    */
+    virtual bool number_float(number_float_t val, const string_t& s) = 0;
+
+    /*!
+    @brief a string was read
+    @param[in] val  string value
+    @return whether parsing should proceed
+    @note It is safe to move the passed string.
+    */
+    virtual bool string(string_t& val) = 0;
+
+    /*!
+    @brief a binary string was read
+    @param[in] val  binary value
+    @return whether parsing should proceed
+    @note It is safe to move the passed binary.
+    */
+    virtual bool binary(binary_t& val) = 0;
+
+    /*!
+    @brief the beginning of an object was read
+    @param[in] elements  number of object elements or -1 if unknown
+    @return whether parsing should proceed
+    @note binary formats may report the number of elements
+    */
+    virtual bool start_object(std::size_t elements) = 0;
+
+    /*!
+    @brief an object key was read
+    @param[in] val  object key
+    @return whether parsing should proceed
+    @note It is safe to move the passed string.
+    */
+    virtual bool key(string_t& val) = 0;
+
+    /*!
+    @brief the end of an object was read
+    @return whether parsing should proceed
+    */
+    virtual bool end_object() = 0;
+
+    /*!
+    @brief the beginning of an array was read
+    @param[in] elements  number of array elements or -1 if unknown
+    @return whether parsing should proceed
+    @note binary formats may report the number of elements
+    */
+    virtual bool start_array(std::size_t elements) = 0;
+
+    /*!
+    @brief the end of an array was read
+    @return whether parsing should proceed
+    */
+    virtual bool end_array() = 0;
+
+    /*!
+    @brief a parse error occurred
+    @param[in] position    the position in the input where the error occurs
+    @param[in] last_token  the last read token
+    @param[in] ex          an exception object describing the error
+    @return whether parsing should proceed (must return false)
+    */
+    virtual bool parse_error(std::size_t position,
+                             const std::string& last_token,
+                             const detail::exception& ex) = 0;
+
+    json_sax() = default;
+    json_sax(const json_sax&) = default;
+    json_sax(json_sax&&) noexcept = default;
+    json_sax& operator=(const json_sax&) = default;
+    json_sax& operator=(json_sax&&) noexcept = default;
+    virtual ~json_sax() = default;
+};
+
+
+namespace detail
+{
+/*!
+@brief SAX implementation to create a JSON value from SAX events
+
+This class implements the @ref json_sax interface and processes the SAX events
+to create a JSON value which makes it basically a DOM parser. The structure or
+hierarchy of the JSON value is managed by the stack `ref_stack` which contains
+a pointer to the respective array or object for each recursion depth.
+
+After successful parsing, the value that is passed by reference to the
+constructor contains the parsed value.
+
+@tparam BasicJsonType  the JSON type
+*/
+template<typename BasicJsonType>
+class json_sax_dom_parser
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+
+    /*!
+    @param[in,out] r  reference to a JSON value that is manipulated while
+                       parsing
+    @param[in] allow_exceptions_  whether parse errors yield exceptions
+    */
+    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
+        : root(r), allow_exceptions(allow_exceptions_)
+    {}
+
+    // make class move-only
+    json_sax_dom_parser(const json_sax_dom_parser&) = delete;
+    json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
+    json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    ~json_sax_dom_parser() = default;
+
+    bool null()
+    {
+        handle_value(nullptr);
+        return true;
+    }
+
+    bool boolean(bool val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_integer(number_integer_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_float(number_float_t val, const string_t& /*unused*/)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool string(string_t& val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool binary(binary_t& val)
+    {
+        handle_value(std::move(val));
+        return true;
+    }
+
+    bool start_object(std::size_t len)
+    {
+        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
+
+        if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
+        }
+
+        return true;
+    }
+
+    bool key(string_t& val)
+    {
+        // add null at given key and store the reference for later
+        object_element = &(ref_stack.back()->m_value.object->operator[](val));
+        return true;
+    }
+
+    bool end_object()
+    {
+        ref_stack.back()->set_parents();
+        ref_stack.pop_back();
+        return true;
+    }
+
+    bool start_array(std::size_t len)
+    {
+        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
+
+        if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
+        }
+
+        return true;
+    }
+
+    bool end_array()
+    {
+        ref_stack.back()->set_parents();
+        ref_stack.pop_back();
+        return true;
+    }
+
+    template<class Exception>
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
+                     const Exception& ex)
+    {
+        errored = true;
+        static_cast<void>(ex);
+        if (allow_exceptions)
+        {
+            JSON_THROW(ex);
+        }
+        return false;
+    }
+
+    constexpr bool is_errored() const
+    {
+        return errored;
+    }
+
+  private:
+    /*!
+    @invariant If the ref stack is empty, then the passed value will be the new
+               root.
+    @invariant If the ref stack contains a value, then it is an array or an
+               object to which we can add elements
+    */
+    template<typename Value>
+    JSON_HEDLEY_RETURNS_NON_NULL
+    BasicJsonType* handle_value(Value&& v)
+    {
+        if (ref_stack.empty())
+        {
+            root = BasicJsonType(std::forward<Value>(v));
+            return &root;
+        }
+
+        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
+
+        if (ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
+            return &(ref_stack.back()->m_value.array->back());
+        }
+
+        JSON_ASSERT(ref_stack.back()->is_object());
+        JSON_ASSERT(object_element);
+        *object_element = BasicJsonType(std::forward<Value>(v));
+        return object_element;
+    }
+
+    /// the parsed JSON value
+    BasicJsonType& root;
+    /// stack to model hierarchy of values
+    std::vector<BasicJsonType*> ref_stack {};
+    /// helper to hold the reference for the next object element
+    BasicJsonType* object_element = nullptr;
+    /// whether a syntax error occurred
+    bool errored = false;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+};
+
+template<typename BasicJsonType>
+class json_sax_dom_callback_parser
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using parser_callback_t = typename BasicJsonType::parser_callback_t;
+    using parse_event_t = typename BasicJsonType::parse_event_t;
+
+    json_sax_dom_callback_parser(BasicJsonType& r,
+                                 const parser_callback_t cb,
+                                 const bool allow_exceptions_ = true)
+        : root(r), callback(cb), allow_exceptions(allow_exceptions_)
+    {
+        keep_stack.push_back(true);
+    }
+
+    // make class move-only
+    json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
+    json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
+    json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    ~json_sax_dom_callback_parser() = default;
+
+    bool null()
+    {
+        handle_value(nullptr);
+        return true;
+    }
+
+    bool boolean(bool val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_integer(number_integer_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_float(number_float_t val, const string_t& /*unused*/)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool string(string_t& val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool binary(binary_t& val)
+    {
+        handle_value(std::move(val));
+        return true;
+    }
+
+    bool start_object(std::size_t len)
+    {
+        // check callback for object start
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
+        keep_stack.push_back(keep);
+
+        auto val = handle_value(BasicJsonType::value_t::object, true);
+        ref_stack.push_back(val.second);
+
+        // check object limit
+        if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
+        }
+
+        return true;
+    }
+
+    bool key(string_t& val)
+    {
+        BasicJsonType k = BasicJsonType(val);
+
+        // check callback for key
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
+        key_keep_stack.push_back(keep);
+
+        // add discarded value at given key and store the reference for later
+        if (keep && ref_stack.back())
+        {
+            object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
+        }
+
+        return true;
+    }
+
+    bool end_object()
+    {
+        if (ref_stack.back())
+        {
+            if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
+            {
+                // discard object
+                *ref_stack.back() = discarded;
+            }
+            else
+            {
+                ref_stack.back()->set_parents();
+            }
+        }
+
+        JSON_ASSERT(!ref_stack.empty());
+        JSON_ASSERT(!keep_stack.empty());
+        ref_stack.pop_back();
+        keep_stack.pop_back();
+
+        if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
+        {
+            // remove discarded value
+            for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
+            {
+                if (it->is_discarded())
+                {
+                    ref_stack.back()->erase(it);
+                    break;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    bool start_array(std::size_t len)
+    {
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
+        keep_stack.push_back(keep);
+
+        auto val = handle_value(BasicJsonType::value_t::array, true);
+        ref_stack.push_back(val.second);
+
+        // check array limit
+        if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
+        }
+
+        return true;
+    }
+
+    bool end_array()
+    {
+        bool keep = true;
+
+        if (ref_stack.back())
+        {
+            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
+            if (keep)
+            {
+                ref_stack.back()->set_parents();
+            }
+            else
+            {
+                // discard array
+                *ref_stack.back() = discarded;
+            }
+        }
+
+        JSON_ASSERT(!ref_stack.empty());
+        JSON_ASSERT(!keep_stack.empty());
+        ref_stack.pop_back();
+        keep_stack.pop_back();
+
+        // remove discarded value
+        if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->pop_back();
+        }
+
+        return true;
+    }
+
+    template<class Exception>
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
+                     const Exception& ex)
+    {
+        errored = true;
+        static_cast<void>(ex);
+        if (allow_exceptions)
+        {
+            JSON_THROW(ex);
+        }
+        return false;
+    }
+
+    constexpr bool is_errored() const
+    {
+        return errored;
+    }
+
+  private:
+    /*!
+    @param[in] v  value to add to the JSON value we build during parsing
+    @param[in] skip_callback  whether we should skip calling the callback
+               function; this is required after start_array() and
+               start_object() SAX events, because otherwise we would call the
+               callback function with an empty array or object, respectively.
+
+    @invariant If the ref stack is empty, then the passed value will be the new
+               root.
+    @invariant If the ref stack contains a value, then it is an array or an
+               object to which we can add elements
+
+    @return pair of boolean (whether value should be kept) and pointer (to the
+            passed value in the ref_stack hierarchy; nullptr if not kept)
+    */
+    template<typename Value>
+    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
+    {
+        JSON_ASSERT(!keep_stack.empty());
+
+        // do not handle this value if we know it would be added to a discarded
+        // container
+        if (!keep_stack.back())
+        {
+            return {false, nullptr};
+        }
+
+        // create value
+        auto value = BasicJsonType(std::forward<Value>(v));
+
+        // check callback
+        const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
+
+        // do not handle this value if we just learnt it shall be discarded
+        if (!keep)
+        {
+            return {false, nullptr};
+        }
+
+        if (ref_stack.empty())
+        {
+            root = std::move(value);
+            return {true, &root};
+        }
+
+        // skip this value if we already decided to skip the parent
+        // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
+        if (!ref_stack.back())
+        {
+            return {false, nullptr};
+        }
+
+        // we now only expect arrays and objects
+        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
+
+        // array
+        if (ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->emplace_back(std::move(value));
+            return {true, &(ref_stack.back()->m_value.array->back())};
+        }
+
+        // object
+        JSON_ASSERT(ref_stack.back()->is_object());
+        // check if we should store an element for the current key
+        JSON_ASSERT(!key_keep_stack.empty());
+        const bool store_element = key_keep_stack.back();
+        key_keep_stack.pop_back();
+
+        if (!store_element)
+        {
+            return {false, nullptr};
+        }
+
+        JSON_ASSERT(object_element);
+        *object_element = std::move(value);
+        return {true, object_element};
+    }
+
+    /// the parsed JSON value
+    BasicJsonType& root;
+    /// stack to model hierarchy of values
+    std::vector<BasicJsonType*> ref_stack {};
+    /// stack to manage which values to keep
+    std::vector<bool> keep_stack {};
+    /// stack to manage which object keys to keep
+    std::vector<bool> key_keep_stack {};
+    /// helper to hold the reference for the next object element
+    BasicJsonType* object_element = nullptr;
+    /// whether a syntax error occurred
+    bool errored = false;
+    /// callback function
+    const parser_callback_t callback = nullptr;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+    /// a discarded value for the callback
+    BasicJsonType discarded = BasicJsonType::value_t::discarded;
+};
+
+template<typename BasicJsonType>
+class json_sax_acceptor
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+
+    bool null()
+    {
+        return true;
+    }
+
+    bool boolean(bool /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_integer(number_integer_t /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool string(string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool binary(binary_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool start_object(std::size_t /*unused*/ = std::size_t(-1))
+    {
+        return true;
+    }
+
+    bool key(string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool end_object()
+    {
+        return true;
+    }
+
+    bool start_array(std::size_t /*unused*/ = std::size_t(-1))
+    {
+        return true;
+    }
+
+    bool end_array()
+    {
+        return true;
+    }
+
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
+    {
+        return false;
+    }
+};
+}  // namespace detail
+
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+
+#include <array> // array
+#include <clocale> // localeconv
+#include <cstddef> // size_t
+#include <cstdio> // snprintf
+#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
+#include <initializer_list> // initializer_list
+#include <string> // char_traits, string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/position_t.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////
+// lexer //
+///////////
+
+template<typename BasicJsonType>
+class lexer_base
+{
+  public:
+    /// token types for the parser
+    enum class token_type
+    {
+        uninitialized,    ///< indicating the scanner is uninitialized
+        literal_true,     ///< the `true` literal
+        literal_false,    ///< the `false` literal
+        literal_null,     ///< the `null` literal
+        value_string,     ///< a string -- use get_string() for actual value
+        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
+        value_integer,    ///< a signed integer -- use get_number_integer() for actual value
+        value_float,      ///< an floating point number -- use get_number_float() for actual value
+        begin_array,      ///< the character for array begin `[`
+        begin_object,     ///< the character for object begin `{`
+        end_array,        ///< the character for array end `]`
+        end_object,       ///< the character for object end `}`
+        name_separator,   ///< the name separator `:`
+        value_separator,  ///< the value separator `,`
+        parse_error,      ///< indicating a parse error
+        end_of_input,     ///< indicating the end of the input buffer
+        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
+    };
+
+    /// return name of values of type token_type (only used for errors)
+    JSON_HEDLEY_RETURNS_NON_NULL
+    JSON_HEDLEY_CONST
+    static const char* token_type_name(const token_type t) noexcept
+    {
+        switch (t)
+        {
+            case token_type::uninitialized:
+                return "<uninitialized>";
+            case token_type::literal_true:
+                return "true literal";
+            case token_type::literal_false:
+                return "false literal";
+            case token_type::literal_null:
+                return "null literal";
+            case token_type::value_string:
+                return "string literal";
+            case token_type::value_unsigned:
+            case token_type::value_integer:
+            case token_type::value_float:
+                return "number literal";
+            case token_type::begin_array:
+                return "'['";
+            case token_type::begin_object:
+                return "'{'";
+            case token_type::end_array:
+                return "']'";
+            case token_type::end_object:
+                return "'}'";
+            case token_type::name_separator:
+                return "':'";
+            case token_type::value_separator:
+                return "','";
+            case token_type::parse_error:
+                return "<parse error>";
+            case token_type::end_of_input:
+                return "end of input";
+            case token_type::literal_or_value:
+                return "'[', '{', or a literal";
+            // LCOV_EXCL_START
+            default: // catch non-enum values
+                return "unknown token";
+                // LCOV_EXCL_STOP
+        }
+    }
+};
+/*!
+@brief lexical analysis
+
+This class organizes the lexical analysis during JSON deserialization.
+*/
+template<typename BasicJsonType, typename InputAdapterType>
+class lexer : public lexer_base<BasicJsonType>
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using char_type = typename InputAdapterType::char_type;
+    using char_int_type = typename std::char_traits<char_type>::int_type;
+
+  public:
+    using token_type = typename lexer_base<BasicJsonType>::token_type;
+
+    explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
+        : ia(std::move(adapter))
+        , ignore_comments(ignore_comments_)
+        , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
+    {}
+
+    // delete because of pointer members
+    lexer(const lexer&) = delete;
+    lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    lexer& operator=(lexer&) = delete;
+    lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    ~lexer() = default;
+
+  private:
+    /////////////////////
+    // locales
+    /////////////////////
+
+    /// return the locale-dependent decimal point
+    JSON_HEDLEY_PURE
+    static char get_decimal_point() noexcept
+    {
+        const auto* loc = localeconv();
+        JSON_ASSERT(loc != nullptr);
+        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
+    }
+
+    /////////////////////
+    // scan functions
+    /////////////////////
+
+    /*!
+    @brief get codepoint from 4 hex characters following `\u`
+
+    For input "\u c1 c2 c3 c4" the codepoint is:
+      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
+    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
+
+    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
+    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
+    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
+    between the ASCII value of the character and the desired integer value.
+
+    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
+            non-hex character)
+    */
+    int get_codepoint()
+    {
+        // this function only makes sense after reading `\u`
+        JSON_ASSERT(current == 'u');
+        int codepoint = 0;
+
+        const auto factors = { 12u, 8u, 4u, 0u };
+        for (const auto factor : factors)
+        {
+            get();
+
+            if (current >= '0' && current <= '9')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
+            }
+            else if (current >= 'A' && current <= 'F')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
+            }
+            else if (current >= 'a' && current <= 'f')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
+            }
+            else
+            {
+                return -1;
+            }
+        }
+
+        JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
+        return codepoint;
+    }
+
+    /*!
+    @brief check if the next byte(s) are inside a given range
+
+    Adds the current byte and, for each passed range, reads a new byte and
+    checks if it is inside the range. If a violation was detected, set up an
+    error message and return false. Otherwise, return true.
+
+    @param[in] ranges  list of integers; interpreted as list of pairs of
+                       inclusive lower and upper bound, respectively
+
+    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
+         1, 2, or 3 pairs. This precondition is enforced by an assertion.
+
+    @return true if and only if no range violation was detected
+    */
+    bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
+    {
+        JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
+        add(current);
+
+        for (auto range = ranges.begin(); range != ranges.end(); ++range)
+        {
+            get();
+            if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
+            {
+                add(current);
+            }
+            else
+            {
+                error_message = "invalid string: ill-formed UTF-8 byte";
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /*!
+    @brief scan a string literal
+
+    This function scans a string according to Sect. 7 of RFC 8259. While
+    scanning, bytes are escaped and copied into buffer token_buffer. Then the
+    function returns successfully, token_buffer is *not* null-terminated (as it
+    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
+    string.
+
+    @return token_type::value_string if string could be successfully scanned,
+            token_type::parse_error otherwise
+
+    @note In case of errors, variable error_message contains a textual
+          description.
+    */
+    token_type scan_string()
+    {
+        // reset token_buffer (ignore opening quote)
+        reset();
+
+        // we entered the function by reading an open quote
+        JSON_ASSERT(current == '\"');
+
+        while (true)
+        {
+            // get next character
+            switch (get())
+            {
+                // end of file while parsing string
+                case std::char_traits<char_type>::eof():
+                {
+                    error_message = "invalid string: missing closing quote";
+                    return token_type::parse_error;
+                }
+
+                // closing quote
+                case '\"':
+                {
+                    return token_type::value_string;
+                }
+
+                // escapes
+                case '\\':
+                {
+                    switch (get())
+                    {
+                        // quotation mark
+                        case '\"':
+                            add('\"');
+                            break;
+                        // reverse solidus
+                        case '\\':
+                            add('\\');
+                            break;
+                        // solidus
+                        case '/':
+                            add('/');
+                            break;
+                        // backspace
+                        case 'b':
+                            add('\b');
+                            break;
+                        // form feed
+                        case 'f':
+                            add('\f');
+                            break;
+                        // line feed
+                        case 'n':
+                            add('\n');
+                            break;
+                        // carriage return
+                        case 'r':
+                            add('\r');
+                            break;
+                        // tab
+                        case 't':
+                            add('\t');
+                            break;
+
+                        // unicode escapes
+                        case 'u':
+                        {
+                            const int codepoint1 = get_codepoint();
+                            int codepoint = codepoint1; // start with codepoint1
+
+                            if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
+                            {
+                                error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+                                return token_type::parse_error;
+                            }
+
+                            // check if code point is a high surrogate
+                            if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
+                            {
+                                // expect next \uxxxx entry
+                                if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
+                                {
+                                    const int codepoint2 = get_codepoint();
+
+                                    if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
+                                    {
+                                        error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+                                        return token_type::parse_error;
+                                    }
+
+                                    // check if codepoint2 is a low surrogate
+                                    if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
+                                    {
+                                        // overwrite codepoint
+                                        codepoint = static_cast<int>(
+                                                        // high surrogate occupies the most significant 22 bits
+                                                        (static_cast<unsigned int>(codepoint1) << 10u)
+                                                        // low surrogate occupies the least significant 15 bits
+                                                        + static_cast<unsigned int>(codepoint2)
+                                                        // there is still the 0xD800, 0xDC00 and 0x10000 noise
+                                                        // in the result so we have to subtract with:
+                                                        // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
+                                                        - 0x35FDC00u);
+                                    }
+                                    else
+                                    {
+                                        error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
+                                        return token_type::parse_error;
+                                    }
+                                }
+                                else
+                                {
+                                    error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
+                                    return token_type::parse_error;
+                                }
+                            }
+                            else
+                            {
+                                if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
+                                {
+                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
+                                    return token_type::parse_error;
+                                }
+                            }
+
+                            // result of the above calculation yields a proper codepoint
+                            JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
+
+                            // translate codepoint into bytes
+                            if (codepoint < 0x80)
+                            {
+                                // 1-byte characters: 0xxxxxxx (ASCII)
+                                add(static_cast<char_int_type>(codepoint));
+                            }
+                            else if (codepoint <= 0x7FF)
+                            {
+                                // 2-byte characters: 110xxxxx 10xxxxxx
+                                add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
+                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+                            else if (codepoint <= 0xFFFF)
+                            {
+                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
+                                add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
+                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
+                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+                            else
+                            {
+                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+                                add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
+                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
+                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
+                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+
+                            break;
+                        }
+
+                        // other characters after escape
+                        default:
+                            error_message = "invalid string: forbidden character after backslash";
+                            return token_type::parse_error;
+                    }
+
+                    break;
+                }
+
+                // invalid control characters
+                case 0x00:
+                {
+                    error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
+                    return token_type::parse_error;
+                }
+
+                case 0x01:
+                {
+                    error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
+                    return token_type::parse_error;
+                }
+
+                case 0x02:
+                {
+                    error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
+                    return token_type::parse_error;
+                }
+
+                case 0x03:
+                {
+                    error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
+                    return token_type::parse_error;
+                }
+
+                case 0x04:
+                {
+                    error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
+                    return token_type::parse_error;
+                }
+
+                case 0x05:
+                {
+                    error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
+                    return token_type::parse_error;
+                }
+
+                case 0x06:
+                {
+                    error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
+                    return token_type::parse_error;
+                }
+
+                case 0x07:
+                {
+                    error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
+                    return token_type::parse_error;
+                }
+
+                case 0x08:
+                {
+                    error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
+                    return token_type::parse_error;
+                }
+
+                case 0x09:
+                {
+                    error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
+                    return token_type::parse_error;
+                }
+
+                case 0x0A:
+                {
+                    error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
+                    return token_type::parse_error;
+                }
+
+                case 0x0B:
+                {
+                    error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
+                    return token_type::parse_error;
+                }
+
+                case 0x0C:
+                {
+                    error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
+                    return token_type::parse_error;
+                }
+
+                case 0x0D:
+                {
+                    error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
+                    return token_type::parse_error;
+                }
+
+                case 0x0E:
+                {
+                    error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
+                    return token_type::parse_error;
+                }
+
+                case 0x0F:
+                {
+                    error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
+                    return token_type::parse_error;
+                }
+
+                case 0x10:
+                {
+                    error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
+                    return token_type::parse_error;
+                }
+
+                case 0x11:
+                {
+                    error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
+                    return token_type::parse_error;
+                }
+
+                case 0x12:
+                {
+                    error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
+                    return token_type::parse_error;
+                }
+
+                case 0x13:
+                {
+                    error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
+                    return token_type::parse_error;
+                }
+
+                case 0x14:
+                {
+                    error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
+                    return token_type::parse_error;
+                }
+
+                case 0x15:
+                {
+                    error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
+                    return token_type::parse_error;
+                }
+
+                case 0x16:
+                {
+                    error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
+                    return token_type::parse_error;
+                }
+
+                case 0x17:
+                {
+                    error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
+                    return token_type::parse_error;
+                }
+
+                case 0x18:
+                {
+                    error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
+                    return token_type::parse_error;
+                }
+
+                case 0x19:
+                {
+                    error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
+                    return token_type::parse_error;
+                }
+
+                case 0x1A:
+                {
+                    error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
+                    return token_type::parse_error;
+                }
+
+                case 0x1B:
+                {
+                    error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
+                    return token_type::parse_error;
+                }
+
+                case 0x1C:
+                {
+                    error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
+                    return token_type::parse_error;
+                }
+
+                case 0x1D:
+                {
+                    error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
+                    return token_type::parse_error;
+                }
+
+                case 0x1E:
+                {
+                    error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
+                    return token_type::parse_error;
+                }
+
+                case 0x1F:
+                {
+                    error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
+                    return token_type::parse_error;
+                }
+
+                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
+                case 0x20:
+                case 0x21:
+                case 0x23:
+                case 0x24:
+                case 0x25:
+                case 0x26:
+                case 0x27:
+                case 0x28:
+                case 0x29:
+                case 0x2A:
+                case 0x2B:
+                case 0x2C:
+                case 0x2D:
+                case 0x2E:
+                case 0x2F:
+                case 0x30:
+                case 0x31:
+                case 0x32:
+                case 0x33:
+                case 0x34:
+                case 0x35:
+                case 0x36:
+                case 0x37:
+                case 0x38:
+                case 0x39:
+                case 0x3A:
+                case 0x3B:
+                case 0x3C:
+                case 0x3D:
+                case 0x3E:
+                case 0x3F:
+                case 0x40:
+                case 0x41:
+                case 0x42:
+                case 0x43:
+                case 0x44:
+                case 0x45:
+                case 0x46:
+                case 0x47:
+                case 0x48:
+                case 0x49:
+                case 0x4A:
+                case 0x4B:
+                case 0x4C:
+                case 0x4D:
+                case 0x4E:
+                case 0x4F:
+                case 0x50:
+                case 0x51:
+                case 0x52:
+                case 0x53:
+                case 0x54:
+                case 0x55:
+                case 0x56:
+                case 0x57:
+                case 0x58:
+                case 0x59:
+                case 0x5A:
+                case 0x5B:
+                case 0x5D:
+                case 0x5E:
+                case 0x5F:
+                case 0x60:
+                case 0x61:
+                case 0x62:
+                case 0x63:
+                case 0x64:
+                case 0x65:
+                case 0x66:
+                case 0x67:
+                case 0x68:
+                case 0x69:
+                case 0x6A:
+                case 0x6B:
+                case 0x6C:
+                case 0x6D:
+                case 0x6E:
+                case 0x6F:
+                case 0x70:
+                case 0x71:
+                case 0x72:
+                case 0x73:
+                case 0x74:
+                case 0x75:
+                case 0x76:
+                case 0x77:
+                case 0x78:
+                case 0x79:
+                case 0x7A:
+                case 0x7B:
+                case 0x7C:
+                case 0x7D:
+                case 0x7E:
+                case 0x7F:
+                {
+                    add(current);
+                    break;
+                }
+
+                // U+0080..U+07FF: bytes C2..DF 80..BF
+                case 0xC2:
+                case 0xC3:
+                case 0xC4:
+                case 0xC5:
+                case 0xC6:
+                case 0xC7:
+                case 0xC8:
+                case 0xC9:
+                case 0xCA:
+                case 0xCB:
+                case 0xCC:
+                case 0xCD:
+                case 0xCE:
+                case 0xCF:
+                case 0xD0:
+                case 0xD1:
+                case 0xD2:
+                case 0xD3:
+                case 0xD4:
+                case 0xD5:
+                case 0xD6:
+                case 0xD7:
+                case 0xD8:
+                case 0xD9:
+                case 0xDA:
+                case 0xDB:
+                case 0xDC:
+                case 0xDD:
+                case 0xDE:
+                case 0xDF:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
+                case 0xE0:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
+                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
+                case 0xE1:
+                case 0xE2:
+                case 0xE3:
+                case 0xE4:
+                case 0xE5:
+                case 0xE6:
+                case 0xE7:
+                case 0xE8:
+                case 0xE9:
+                case 0xEA:
+                case 0xEB:
+                case 0xEC:
+                case 0xEE:
+                case 0xEF:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+D000..U+D7FF: bytes ED 80..9F 80..BF
+                case 0xED:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
+                case 0xF0:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
+                case 0xF1:
+                case 0xF2:
+                case 0xF3:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
+                case 0xF4:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // remaining bytes (80..C1 and F5..FF) are ill-formed
+                default:
+                {
+                    error_message = "invalid string: ill-formed UTF-8 byte";
+                    return token_type::parse_error;
+                }
+            }
+        }
+    }
+
+    /*!
+     * @brief scan a comment
+     * @return whether comment could be scanned successfully
+     */
+    bool scan_comment()
+    {
+        switch (get())
+        {
+            // single-line comments skip input until a newline or EOF is read
+            case '/':
+            {
+                while (true)
+                {
+                    switch (get())
+                    {
+                        case '\n':
+                        case '\r':
+                        case std::char_traits<char_type>::eof():
+                        case '\0':
+                            return true;
+
+                        default:
+                            break;
+                    }
+                }
+            }
+
+            // multi-line comments skip input until */ is read
+            case '*':
+            {
+                while (true)
+                {
+                    switch (get())
+                    {
+                        case std::char_traits<char_type>::eof():
+                        case '\0':
+                        {
+                            error_message = "invalid comment; missing closing '*/'";
+                            return false;
+                        }
+
+                        case '*':
+                        {
+                            switch (get())
+                            {
+                                case '/':
+                                    return true;
+
+                                default:
+                                {
+                                    unget();
+                                    continue;
+                                }
+                            }
+                        }
+
+                        default:
+                            continue;
+                    }
+                }
+            }
+
+            // unexpected character after reading '/'
+            default:
+            {
+                error_message = "invalid comment; expecting '/' or '*' after '/'";
+                return false;
+            }
+        }
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(float& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtof(str, endptr);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(double& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtod(str, endptr);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(long double& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtold(str, endptr);
+    }
+
+    /*!
+    @brief scan a number literal
+
+    This function scans a string according to Sect. 6 of RFC 8259.
+
+    The function is realized with a deterministic finite state machine derived
+    from the grammar described in RFC 8259. Starting in state "init", the
+    input is read and used to determined the next state. Only state "done"
+    accepts the number. State "error" is a trap state to model errors. In the
+    table below, "anything" means any character but the ones listed before.
+
+    state    | 0        | 1-9      | e E      | +       | -       | .        | anything
+    ---------|----------|----------|----------|---------|---------|----------|-----------
+    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
+    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
+    zero     | done     | done     | exponent | done    | done    | decimal1 | done
+    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
+    decimal1 | decimal2 | decimal2 | [error]  | [error] | [error] | [error]  | [error]
+    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
+    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
+    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
+    any2     | any2     | any2     | done     | done    | done    | done     | done
+
+    The state machine is realized with one label per state (prefixed with
+    "scan_number_") and `goto` statements between them. The state machine
+    contains cycles, but any cycle can be left when EOF is read. Therefore,
+    the function is guaranteed to terminate.
+
+    During scanning, the read bytes are stored in token_buffer. This string is
+    then converted to a signed integer, an unsigned integer, or a
+    floating-point number.
+
+    @return token_type::value_unsigned, token_type::value_integer, or
+            token_type::value_float if number could be successfully scanned,
+            token_type::parse_error otherwise
+
+    @note The scanner is independent of the current locale. Internally, the
+          locale's decimal point is used instead of `.` to work with the
+          locale-dependent converters.
+    */
+    token_type scan_number()  // lgtm [cpp/use-of-goto]
+    {
+        // reset token_buffer to store the number's bytes
+        reset();
+
+        // the type of the parsed number; initially set to unsigned; will be
+        // changed if minus sign, decimal point or exponent is read
+        token_type number_type = token_type::value_unsigned;
+
+        // state (init): we just found out we need to scan a number
+        switch (current)
+        {
+            case '-':
+            {
+                add(current);
+                goto scan_number_minus;
+            }
+
+            case '0':
+            {
+                add(current);
+                goto scan_number_zero;
+            }
+
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            // all other characters are rejected outside scan_number()
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+
+scan_number_minus:
+        // state: we just parsed a leading minus sign
+        number_type = token_type::value_integer;
+        switch (get())
+        {
+            case '0':
+            {
+                add(current);
+                goto scan_number_zero;
+            }
+
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after '-'";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_zero:
+        // state: we just parse a zero (maybe with a leading minus sign)
+        switch (get())
+        {
+            case '.':
+            {
+                add(decimal_point_char);
+                goto scan_number_decimal1;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_any1:
+        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            case '.':
+            {
+                add(decimal_point_char);
+                goto scan_number_decimal1;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_decimal1:
+        // state: we just parsed a decimal point
+        number_type = token_type::value_float;
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_decimal2;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after '.'";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_decimal2:
+        // we just parsed at least one number after a decimal point
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_decimal2;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_exponent:
+        // we just parsed an exponent
+        number_type = token_type::value_float;
+        switch (get())
+        {
+            case '+':
+            case '-':
+            {
+                add(current);
+                goto scan_number_sign;
+            }
+
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+            {
+                error_message =
+                    "invalid number; expected '+', '-', or digit after exponent";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_sign:
+        // we just parsed an exponent sign
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after exponent sign";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_any2:
+        // we just parsed a number after the exponent or exponent sign
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_done:
+        // unget the character after the number (we only read it to know that
+        // we are done scanning a number)
+        unget();
+
+        char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+        errno = 0;
+
+        // try to parse integers first and fall back to floats
+        if (number_type == token_type::value_unsigned)
+        {
+            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
+
+            // we checked the number format before
+            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+            if (errno == 0)
+            {
+                value_unsigned = static_cast<number_unsigned_t>(x);
+                if (value_unsigned == x)
+                {
+                    return token_type::value_unsigned;
+                }
+            }
+        }
+        else if (number_type == token_type::value_integer)
+        {
+            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
+
+            // we checked the number format before
+            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+            if (errno == 0)
+            {
+                value_integer = static_cast<number_integer_t>(x);
+                if (value_integer == x)
+                {
+                    return token_type::value_integer;
+                }
+            }
+        }
+
+        // this code is reached if we parse a floating-point number or if an
+        // integer conversion above failed
+        strtof(value_float, token_buffer.data(), &endptr);
+
+        // we checked the number format before
+        JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+        return token_type::value_float;
+    }
+
+    /*!
+    @param[in] literal_text  the literal text to expect
+    @param[in] length        the length of the passed literal text
+    @param[in] return_type   the token type to return on success
+    */
+    JSON_HEDLEY_NON_NULL(2)
+    token_type scan_literal(const char_type* literal_text, const std::size_t length,
+                            token_type return_type)
+    {
+        JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
+        for (std::size_t i = 1; i < length; ++i)
+        {
+            if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
+            {
+                error_message = "invalid literal";
+                return token_type::parse_error;
+            }
+        }
+        return return_type;
+    }
+
+    /////////////////////
+    // input management
+    /////////////////////
+
+    /// reset token_buffer; current character is beginning of token
+    void reset() noexcept
+    {
+        token_buffer.clear();
+        token_string.clear();
+        token_string.push_back(std::char_traits<char_type>::to_char_type(current));
+    }
+
+    /*
+    @brief get next character from the input
+
+    This function provides the interface to the used input adapter. It does
+    not throw in case the input reached EOF, but returns a
+    `std::char_traits<char>::eof()` in that case.  Stores the scanned characters
+    for use in error messages.
+
+    @return character read from the input
+    */
+    char_int_type get()
+    {
+        ++position.chars_read_total;
+        ++position.chars_read_current_line;
+
+        if (next_unget)
+        {
+            // just reset the next_unget variable and work with current
+            next_unget = false;
+        }
+        else
+        {
+            current = ia.get_character();
+        }
+
+        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
+        {
+            token_string.push_back(std::char_traits<char_type>::to_char_type(current));
+        }
+
+        if (current == '\n')
+        {
+            ++position.lines_read;
+            position.chars_read_current_line = 0;
+        }
+
+        return current;
+    }
+
+    /*!
+    @brief unget current character (read it again on next get)
+
+    We implement unget by setting variable next_unget to true. The input is not
+    changed - we just simulate ungetting by modifying chars_read_total,
+    chars_read_current_line, and token_string. The next call to get() will
+    behave as if the unget character is read again.
+    */
+    void unget()
+    {
+        next_unget = true;
+
+        --position.chars_read_total;
+
+        // in case we "unget" a newline, we have to also decrement the lines_read
+        if (position.chars_read_current_line == 0)
+        {
+            if (position.lines_read > 0)
+            {
+                --position.lines_read;
+            }
+        }
+        else
+        {
+            --position.chars_read_current_line;
+        }
+
+        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
+        {
+            JSON_ASSERT(!token_string.empty());
+            token_string.pop_back();
+        }
+    }
+
+    /// add a character to token_buffer
+    void add(char_int_type c)
+    {
+        token_buffer.push_back(static_cast<typename string_t::value_type>(c));
+    }
+
+  public:
+    /////////////////////
+    // value getters
+    /////////////////////
+
+    /// return integer value
+    constexpr number_integer_t get_number_integer() const noexcept
+    {
+        return value_integer;
+    }
+
+    /// return unsigned integer value
+    constexpr number_unsigned_t get_number_unsigned() const noexcept
+    {
+        return value_unsigned;
+    }
+
+    /// return floating-point value
+    constexpr number_float_t get_number_float() const noexcept
+    {
+        return value_float;
+    }
+
+    /// return current string value (implicitly resets the token; useful only once)
+    string_t& get_string()
+    {
+        return token_buffer;
+    }
+
+    /////////////////////
+    // diagnostics
+    /////////////////////
+
+    /// return position of last read token
+    constexpr position_t get_position() const noexcept
+    {
+        return position;
+    }
+
+    /// return the last read token (for errors only).  Will never contain EOF
+    /// (an arbitrary value that is not a valid char value, often -1), because
+    /// 255 may legitimately occur.  May contain NUL, which should be escaped.
+    std::string get_token_string() const
+    {
+        // escape control characters
+        std::string result;
+        for (const auto c : token_string)
+        {
+            if (static_cast<unsigned char>(c) <= '\x1F')
+            {
+                // escape control characters
+                std::array<char, 9> cs{{}};
+                (std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+                result += cs.data();
+            }
+            else
+            {
+                // add character as is
+                result.push_back(static_cast<std::string::value_type>(c));
+            }
+        }
+
+        return result;
+    }
+
+    /// return syntax error message
+    JSON_HEDLEY_RETURNS_NON_NULL
+    constexpr const char* get_error_message() const noexcept
+    {
+        return error_message;
+    }
+
+    /////////////////////
+    // actual scanner
+    /////////////////////
+
+    /*!
+    @brief skip the UTF-8 byte order mark
+    @return true iff there is no BOM or the correct BOM has been skipped
+    */
+    bool skip_bom()
+    {
+        if (get() == 0xEF)
+        {
+            // check if we completely parse the BOM
+            return get() == 0xBB && get() == 0xBF;
+        }
+
+        // the first character is not the beginning of the BOM; unget it to
+        // process is later
+        unget();
+        return true;
+    }
+
+    void skip_whitespace()
+    {
+        do
+        {
+            get();
+        }
+        while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
+    }
+
+    token_type scan()
+    {
+        // initially, skip the BOM
+        if (position.chars_read_total == 0 && !skip_bom())
+        {
+            error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
+            return token_type::parse_error;
+        }
+
+        // read next character and ignore whitespace
+        skip_whitespace();
+
+        // ignore comments
+        while (ignore_comments && current == '/')
+        {
+            if (!scan_comment())
+            {
+                return token_type::parse_error;
+            }
+
+            // skip following whitespace
+            skip_whitespace();
+        }
+
+        switch (current)
+        {
+            // structural characters
+            case '[':
+                return token_type::begin_array;
+            case ']':
+                return token_type::end_array;
+            case '{':
+                return token_type::begin_object;
+            case '}':
+                return token_type::end_object;
+            case ':':
+                return token_type::name_separator;
+            case ',':
+                return token_type::value_separator;
+
+            // literals
+            case 't':
+            {
+                std::array<char_type, 4> true_literal = {{char_type('t'), char_type('r'), char_type('u'), char_type('e')}};
+                return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
+            }
+            case 'f':
+            {
+                std::array<char_type, 5> false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), char_type('e')}};
+                return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
+            }
+            case 'n':
+            {
+                std::array<char_type, 4> null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}};
+                return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
+            }
+
+            // string
+            case '\"':
+                return scan_string();
+
+            // number
+            case '-':
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                return scan_number();
+
+            // end of input (the null byte is needed when parsing from
+            // string literals)
+            case '\0':
+            case std::char_traits<char_type>::eof():
+                return token_type::end_of_input;
+
+            // error
+            default:
+                error_message = "invalid literal";
+                return token_type::parse_error;
+        }
+    }
+
+  private:
+    /// input adapter
+    InputAdapterType ia;
+
+    /// whether comments should be ignored (true) or signaled as errors (false)
+    const bool ignore_comments = false;
+
+    /// the current character
+    char_int_type current = std::char_traits<char_type>::eof();
+
+    /// whether the next get() call should just return current
+    bool next_unget = false;
+
+    /// the start position of the current token
+    position_t position {};
+
+    /// raw input token string (for error messages)
+    std::vector<char_type> token_string {};
+
+    /// buffer for variable-length tokens (numbers, strings)
+    string_t token_buffer {};
+
+    /// a description of occurred lexer errors
+    const char* error_message = "";
+
+    // number values
+    number_integer_t value_integer = 0;
+    number_unsigned_t value_unsigned = 0;
+    number_float_t value_float = 0;
+
+    /// the decimal point
+    const char_int_type decimal_point_char = '.';
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
+
+#include <cstdint> // size_t
+#include <utility> // declval
+#include <string> // string
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename T>
+using null_function_t = decltype(std::declval<T&>().null());
+
+template<typename T>
+using boolean_function_t =
+    decltype(std::declval<T&>().boolean(std::declval<bool>()));
+
+template<typename T, typename Integer>
+using number_integer_function_t =
+    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
+
+template<typename T, typename Unsigned>
+using number_unsigned_function_t =
+    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
+
+template<typename T, typename Float, typename String>
+using number_float_function_t = decltype(std::declval<T&>().number_float(
+                                    std::declval<Float>(), std::declval<const String&>()));
+
+template<typename T, typename String>
+using string_function_t =
+    decltype(std::declval<T&>().string(std::declval<String&>()));
+
+template<typename T, typename Binary>
+using binary_function_t =
+    decltype(std::declval<T&>().binary(std::declval<Binary&>()));
+
+template<typename T>
+using start_object_function_t =
+    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
+
+template<typename T, typename String>
+using key_function_t =
+    decltype(std::declval<T&>().key(std::declval<String&>()));
+
+template<typename T>
+using end_object_function_t = decltype(std::declval<T&>().end_object());
+
+template<typename T>
+using start_array_function_t =
+    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
+
+template<typename T>
+using end_array_function_t = decltype(std::declval<T&>().end_array());
+
+template<typename T, typename Exception>
+using parse_error_function_t = decltype(std::declval<T&>().parse_error(
+        std::declval<std::size_t>(), std::declval<const std::string&>(),
+        std::declval<const Exception&>()));
+
+template<typename SAX, typename BasicJsonType>
+struct is_sax
+{
+  private:
+    static_assert(is_basic_json<BasicJsonType>::value,
+                  "BasicJsonType must be of type basic_json<...>");
+
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using exception_t = typename BasicJsonType::exception;
+
+  public:
+    static constexpr bool value =
+        is_detected_exact<bool, null_function_t, SAX>::value &&
+        is_detected_exact<bool, boolean_function_t, SAX>::value &&
+        is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
+        is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
+        is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
+        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
+        is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
+        is_detected_exact<bool, start_object_function_t, SAX>::value &&
+        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
+        is_detected_exact<bool, end_object_function_t, SAX>::value &&
+        is_detected_exact<bool, start_array_function_t, SAX>::value &&
+        is_detected_exact<bool, end_array_function_t, SAX>::value &&
+        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
+};
+
+template<typename SAX, typename BasicJsonType>
+struct is_sax_static_asserts
+{
+  private:
+    static_assert(is_basic_json<BasicJsonType>::value,
+                  "BasicJsonType must be of type basic_json<...>");
+
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using exception_t = typename BasicJsonType::exception;
+
+  public:
+    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
+                  "Missing/invalid function: bool null()");
+    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+                  "Missing/invalid function: bool boolean(bool)");
+    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+                  "Missing/invalid function: bool boolean(bool)");
+    static_assert(
+        is_detected_exact<bool, number_integer_function_t, SAX,
+        number_integer_t>::value,
+        "Missing/invalid function: bool number_integer(number_integer_t)");
+    static_assert(
+        is_detected_exact<bool, number_unsigned_function_t, SAX,
+        number_unsigned_t>::value,
+        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
+    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
+                  number_float_t, string_t>::value,
+                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
+    static_assert(
+        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
+        "Missing/invalid function: bool string(string_t&)");
+    static_assert(
+        is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
+        "Missing/invalid function: bool binary(binary_t&)");
+    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
+                  "Missing/invalid function: bool start_object(std::size_t)");
+    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
+                  "Missing/invalid function: bool key(string_t&)");
+    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
+                  "Missing/invalid function: bool end_object()");
+    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
+                  "Missing/invalid function: bool start_array(std::size_t)");
+    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
+                  "Missing/invalid function: bool end_array()");
+    static_assert(
+        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
+        "Missing/invalid function: bool parse_error(std::size_t, const "
+        "std::string&, const exception&)");
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+/// how to treat CBOR tags
+enum class cbor_tag_handler_t
+{
+    error,   ///< throw a parse_error exception in case of a tag
+    ignore,  ///< ignore tags
+    store    ///< store tags as binary type
+};
+
+/*!
+@brief determine system byte order
+
+@return true if and only if system's byte order is little endian
+
+@note from https://stackoverflow.com/a/1001328/266378
+*/
+static inline bool little_endianness(int num = 1) noexcept
+{
+    return *reinterpret_cast<char*>(&num) == 1;
+}
+
+
+///////////////////
+// binary reader //
+///////////////////
+
+/*!
+@brief deserialization of CBOR, MessagePack, and UBJSON values
+*/
+template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
+class binary_reader
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using json_sax_t = SAX;
+    using char_type = typename InputAdapterType::char_type;
+    using char_int_type = typename std::char_traits<char_type>::int_type;
+
+  public:
+    /*!
+    @brief create a binary reader
+
+    @param[in] adapter  input adapter to read from
+    */
+    explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter))
+    {
+        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+    }
+
+    // make class move-only
+    binary_reader(const binary_reader&) = delete;
+    binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    binary_reader& operator=(const binary_reader&) = delete;
+    binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+    ~binary_reader() = default;
+
+    /*!
+    @param[in] format  the binary format to parse
+    @param[in] sax_    a SAX event processor
+    @param[in] strict  whether to expect the input to be consumed completed
+    @param[in] tag_handler  how to treat CBOR tags
+
+    @return whether parsing was successful
+    */
+    JSON_HEDLEY_NON_NULL(3)
+    bool sax_parse(const input_format_t format,
+                   json_sax_t* sax_,
+                   const bool strict = true,
+                   const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        sax = sax_;
+        bool result = false;
+
+        switch (format)
+        {
+            case input_format_t::bson:
+                result = parse_bson_internal();
+                break;
+
+            case input_format_t::cbor:
+                result = parse_cbor_internal(true, tag_handler);
+                break;
+
+            case input_format_t::msgpack:
+                result = parse_msgpack_internal();
+                break;
+
+            case input_format_t::ubjson:
+                result = parse_ubjson_internal();
+                break;
+
+            case input_format_t::json: // LCOV_EXCL_LINE
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+
+        // strict mode: next byte must be EOF
+        if (result && strict)
+        {
+            if (format == input_format_t::ubjson)
+            {
+                get_ignore_noop();
+            }
+            else
+            {
+                get();
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
+            {
+                return sax->parse_error(chars_read, get_token_string(),
+                                        parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
+            }
+        }
+
+        return result;
+    }
+
+  private:
+    //////////
+    // BSON //
+    //////////
+
+    /*!
+    @brief Reads in a BSON-object and passes it to the SAX-parser.
+    @return whether a valid BSON-value was passed to the SAX parser
+    */
+    bool parse_bson_internal()
+    {
+        std::int32_t document_size{};
+        get_number<std::int32_t, true>(input_format_t::bson, document_size);
+
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
+        {
+            return false;
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
+        {
+            return false;
+        }
+
+        return sax->end_object();
+    }
+
+    /*!
+    @brief Parses a C-style string from the BSON input.
+    @param[in,out] result  A reference to the string variable where the read
+                            string is to be stored.
+    @return `true` if the \x00-byte indicating the end of the string was
+             encountered before the EOF; false` indicates an unexpected EOF.
+    */
+    bool get_bson_cstr(string_t& result)
+    {
+        auto out = std::back_inserter(result);
+        while (true)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
+            {
+                return false;
+            }
+            if (current == 0x00)
+            {
+                return true;
+            }
+            *out++ = static_cast<typename string_t::value_type>(current);
+        }
+    }
+
+    /*!
+    @brief Parses a zero-terminated string of length @a len from the BSON
+           input.
+    @param[in] len  The length (including the zero-byte at the end) of the
+                    string to be read.
+    @param[in,out] result  A reference to the string variable where the read
+                            string is to be stored.
+    @tparam NumberType The type of the length @a len
+    @pre len >= 1
+    @return `true` if the string was successfully parsed
+    */
+    template<typename NumberType>
+    bool get_bson_string(const NumberType len, string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(len < 1))
+        {
+            auto last_token = get_token_string();
+            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType()));
+        }
+
+        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
+    }
+
+    /*!
+    @brief Parses a byte array input of length @a len from the BSON input.
+    @param[in] len  The length of the byte array to be read.
+    @param[in,out] result  A reference to the binary variable where the read
+                            array is to be stored.
+    @tparam NumberType The type of the length @a len
+    @pre len >= 0
+    @return `true` if the byte array was successfully parsed
+    */
+    template<typename NumberType>
+    bool get_bson_binary(const NumberType len, binary_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(len < 0))
+        {
+            auto last_token = get_token_string();
+            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType()));
+        }
+
+        // All BSON binary values have a subtype
+        std::uint8_t subtype{};
+        get_number<std::uint8_t>(input_format_t::bson, subtype);
+        result.set_subtype(subtype);
+
+        return get_binary(input_format_t::bson, len, result);
+    }
+
+    /*!
+    @brief Read a BSON document element of the given @a element_type.
+    @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
+    @param[in] element_type_parse_position The position in the input stream,
+               where the `element_type` was read.
+    @warning Not all BSON element types are supported yet. An unsupported
+             @a element_type will give rise to a parse_error.114:
+             Unsupported BSON record type 0x...
+    @return whether a valid BSON-object/array was passed to the SAX parser
+    */
+    bool parse_bson_element_internal(const char_int_type element_type,
+                                     const std::size_t element_type_parse_position)
+    {
+        switch (element_type)
+        {
+            case 0x01: // double
+            {
+                double number{};
+                return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0x02: // string
+            {
+                std::int32_t len{};
+                string_t value;
+                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
+            }
+
+            case 0x03: // object
+            {
+                return parse_bson_internal();
+            }
+
+            case 0x04: // array
+            {
+                return parse_bson_array();
+            }
+
+            case 0x05: // binary
+            {
+                std::int32_t len{};
+                binary_t value;
+                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
+            }
+
+            case 0x08: // boolean
+            {
+                return sax->boolean(get() != 0);
+            }
+
+            case 0x0A: // null
+            {
+                return sax->null();
+            }
+
+            case 0x10: // int32
+            {
+                std::int32_t value{};
+                return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
+            }
+
+            case 0x12: // int64
+            {
+                std::int64_t value{};
+                return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
+            }
+
+            default: // anything else not supported (yet)
+            {
+                std::array<char, 3> cr{{}};
+                (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+                return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType()));
+            }
+        }
+    }
+
+    /*!
+    @brief Read a BSON element list (as specified in the BSON-spec)
+
+    The same binary layout is used for objects and arrays, hence it must be
+    indicated with the argument @a is_array which one is expected
+    (true --> array, false --> object).
+
+    @param[in] is_array Determines if the element list being read is to be
+                        treated as an object (@a is_array == false), or as an
+                        array (@a is_array == true).
+    @return whether a valid BSON-object/array was passed to the SAX parser
+    */
+    bool parse_bson_element_list(const bool is_array)
+    {
+        string_t key;
+
+        while (auto element_type = get())
+        {
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
+            {
+                return false;
+            }
+
+            const std::size_t element_type_parse_position = chars_read;
+            if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
+            {
+                return false;
+            }
+
+            if (!is_array && !sax->key(key))
+            {
+                return false;
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
+            {
+                return false;
+            }
+
+            // get_bson_cstr only appends
+            key.clear();
+        }
+
+        return true;
+    }
+
+    /*!
+    @brief Reads an array from the BSON input and passes it to the SAX-parser.
+    @return whether a valid BSON-array was passed to the SAX parser
+    */
+    bool parse_bson_array()
+    {
+        std::int32_t document_size{};
+        get_number<std::int32_t, true>(input_format_t::bson, document_size);
+
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
+        {
+            return false;
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
+        {
+            return false;
+        }
+
+        return sax->end_array();
+    }
+
+    //////////
+    // CBOR //
+    //////////
+
+    /*!
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true) or whether the last read character should
+                         be considered instead (false)
+    @param[in] tag_handler how CBOR tags should be treated
+
+    @return whether a valid CBOR value was passed to the SAX parser
+    */
+    bool parse_cbor_internal(const bool get_char,
+                             const cbor_tag_handler_t tag_handler)
+    {
+        switch (get_char ? get() : current)
+        {
+            // EOF
+            case std::char_traits<char_type>::eof():
+                return unexpect_eof(input_format_t::cbor, "value");
+
+            // Integer 0x00..0x17 (0..23)
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x04:
+            case 0x05:
+            case 0x06:
+            case 0x07:
+            case 0x08:
+            case 0x09:
+            case 0x0A:
+            case 0x0B:
+            case 0x0C:
+            case 0x0D:
+            case 0x0E:
+            case 0x0F:
+            case 0x10:
+            case 0x11:
+            case 0x12:
+            case 0x13:
+            case 0x14:
+            case 0x15:
+            case 0x16:
+            case 0x17:
+                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
+
+            case 0x18: // Unsigned integer (one-byte uint8_t follows)
+            {
+                std::uint8_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+            }
+
+            case 0x19: // Unsigned integer (two-byte uint16_t follows)
+            {
+                std::uint16_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+            }
+
+            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
+            {
+                std::uint32_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+            }
+
+            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
+            {
+                std::uint64_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+            }
+
+            // Negative integer -1-0x00..-1-0x17 (-1..-24)
+            case 0x20:
+            case 0x21:
+            case 0x22:
+            case 0x23:
+            case 0x24:
+            case 0x25:
+            case 0x26:
+            case 0x27:
+            case 0x28:
+            case 0x29:
+            case 0x2A:
+            case 0x2B:
+            case 0x2C:
+            case 0x2D:
+            case 0x2E:
+            case 0x2F:
+            case 0x30:
+            case 0x31:
+            case 0x32:
+            case 0x33:
+            case 0x34:
+            case 0x35:
+            case 0x36:
+            case 0x37:
+                return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
+
+            case 0x38: // Negative integer (one-byte uint8_t follows)
+            {
+                std::uint8_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+            {
+                std::uint16_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
+            {
+                std::uint32_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
+            {
+                std::uint64_t number{};
+                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
+                        - static_cast<number_integer_t>(number));
+            }
+
+            // Binary data (0x00..0x17 bytes follow)
+            case 0x40:
+            case 0x41:
+            case 0x42:
+            case 0x43:
+            case 0x44:
+            case 0x45:
+            case 0x46:
+            case 0x47:
+            case 0x48:
+            case 0x49:
+            case 0x4A:
+            case 0x4B:
+            case 0x4C:
+            case 0x4D:
+            case 0x4E:
+            case 0x4F:
+            case 0x50:
+            case 0x51:
+            case 0x52:
+            case 0x53:
+            case 0x54:
+            case 0x55:
+            case 0x56:
+            case 0x57:
+            case 0x58: // Binary data (one-byte uint8_t for n follows)
+            case 0x59: // Binary data (two-byte uint16_t for n follow)
+            case 0x5A: // Binary data (four-byte uint32_t for n follow)
+            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
+            case 0x5F: // Binary data (indefinite length)
+            {
+                binary_t b;
+                return get_cbor_binary(b) && sax->binary(b);
+            }
+
+            // UTF-8 string (0x00..0x17 bytes follow)
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+            case 0x7F: // UTF-8 string (indefinite length)
+            {
+                string_t s;
+                return get_cbor_string(s) && sax->string(s);
+            }
+
+            // array (0x00..0x17 data items follow)
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+            case 0x88:
+            case 0x89:
+            case 0x8A:
+            case 0x8B:
+            case 0x8C:
+            case 0x8D:
+            case 0x8E:
+            case 0x8F:
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+                return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
+
+            case 0x98: // array (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0x99: // array (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0x9A: // array (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0x9B: // array (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0x9F: // array (indefinite length)
+                return get_cbor_array(std::size_t(-1), tag_handler);
+
+            // map (0x00..0x17 pairs of data items follow)
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+                return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
+
+            case 0xB8: // map (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0xB9: // map (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0xBA: // map (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0xBB: // map (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len{};
+                return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast<std::size_t>(len), tag_handler);
+            }
+
+            case 0xBF: // map (indefinite length)
+                return get_cbor_object(std::size_t(-1), tag_handler);
+
+            case 0xC6: // tagged item
+            case 0xC7:
+            case 0xC8:
+            case 0xC9:
+            case 0xCA:
+            case 0xCB:
+            case 0xCC:
+            case 0xCD:
+            case 0xCE:
+            case 0xCF:
+            case 0xD0:
+            case 0xD1:
+            case 0xD2:
+            case 0xD3:
+            case 0xD4:
+            case 0xD8: // tagged item (1 bytes follow)
+            case 0xD9: // tagged item (2 bytes follow)
+            case 0xDA: // tagged item (4 bytes follow)
+            case 0xDB: // tagged item (8 bytes follow)
+            {
+                switch (tag_handler)
+                {
+                    case cbor_tag_handler_t::error:
+                    {
+                        auto last_token = get_token_string();
+                        return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+                    }
+
+                    case cbor_tag_handler_t::ignore:
+                    {
+                        // ignore binary subtype
+                        switch (current)
+                        {
+                            case 0xD8:
+                            {
+                                std::uint8_t subtype_to_ignore{};
+                                get_number(input_format_t::cbor, subtype_to_ignore);
+                                break;
+                            }
+                            case 0xD9:
+                            {
+                                std::uint16_t subtype_to_ignore{};
+                                get_number(input_format_t::cbor, subtype_to_ignore);
+                                break;
+                            }
+                            case 0xDA:
+                            {
+                                std::uint32_t subtype_to_ignore{};
+                                get_number(input_format_t::cbor, subtype_to_ignore);
+                                break;
+                            }
+                            case 0xDB:
+                            {
+                                std::uint64_t subtype_to_ignore{};
+                                get_number(input_format_t::cbor, subtype_to_ignore);
+                                break;
+                            }
+                            default:
+                                break;
+                        }
+                        return parse_cbor_internal(true, tag_handler);
+                    }
+
+                    case cbor_tag_handler_t::store:
+                    {
+                        binary_t b;
+                        // use binary subtype and store in binary container
+                        switch (current)
+                        {
+                            case 0xD8:
+                            {
+                                std::uint8_t subtype{};
+                                get_number(input_format_t::cbor, subtype);
+                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+                                break;
+                            }
+                            case 0xD9:
+                            {
+                                std::uint16_t subtype{};
+                                get_number(input_format_t::cbor, subtype);
+                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+                                break;
+                            }
+                            case 0xDA:
+                            {
+                                std::uint32_t subtype{};
+                                get_number(input_format_t::cbor, subtype);
+                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+                                break;
+                            }
+                            case 0xDB:
+                            {
+                                std::uint64_t subtype{};
+                                get_number(input_format_t::cbor, subtype);
+                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+                                break;
+                            }
+                            default:
+                                return parse_cbor_internal(true, tag_handler);
+                        }
+                        get();
+                        return get_cbor_binary(b) && sax->binary(b);
+                    }
+
+                    default:                 // LCOV_EXCL_LINE
+                        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+                        return false;        // LCOV_EXCL_LINE
+                }
+            }
+
+            case 0xF4: // false
+                return sax->boolean(false);
+
+            case 0xF5: // true
+                return sax->boolean(true);
+
+            case 0xF6: // null
+                return sax->null();
+
+            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
+            {
+                const auto byte1_raw = get();
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
+                {
+                    return false;
+                }
+                const auto byte2_raw = get();
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
+                {
+                    return false;
+                }
+
+                const auto byte1 = static_cast<unsigned char>(byte1_raw);
+                const auto byte2 = static_cast<unsigned char>(byte2_raw);
+
+                // code from RFC 7049, Appendix D, Figure 3:
+                // As half-precision floating-point numbers were only added
+                // to IEEE 754 in 2008, today's programming platforms often
+                // still only have limited support for them. It is very
+                // easy to include at least decoding support for them even
+                // without such support. An example of a small decoder for
+                // half-precision floating-point numbers in the C language
+                // is shown in Fig. 3.
+                const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
+                const double val = [&half]
+                {
+                    const int exp = (half >> 10u) & 0x1Fu;
+                    const unsigned int mant = half & 0x3FFu;
+                    JSON_ASSERT(0 <= exp&& exp <= 32);
+                    JSON_ASSERT(mant <= 1024);
+                    switch (exp)
+                    {
+                        case 0:
+                            return std::ldexp(mant, -24);
+                        case 31:
+                            return (mant == 0)
+                            ? std::numeric_limits<double>::infinity()
+                            : std::numeric_limits<double>::quiet_NaN();
+                        default:
+                            return std::ldexp(mant + 1024, exp - 25);
+                    }
+                }();
+                return sax->number_float((half & 0x8000u) != 0
+                                         ? static_cast<number_float_t>(-val)
+                                         : static_cast<number_float_t>(val), "");
+            }
+
+            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
+            {
+                float number{};
+                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
+            {
+                double number{};
+                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            default: // anything else (0xFF is handled inside the other types)
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a CBOR string
+
+    This function first reads starting bytes to determine the expected
+    string length and then copies this number of bytes into a string.
+    Additionally, CBOR's strings with indefinite lengths are supported.
+
+    @param[out] result  created string
+
+    @return whether string creation completed
+    */
+    bool get_cbor_string(string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            // UTF-8 string (0x00..0x17 bytes follow)
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            {
+                return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
+            }
+
+            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len{};
+                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7F: // UTF-8 string (indefinite length)
+            {
+                while (get() != 0xFF)
+                {
+                    string_t chunk;
+                    if (!get_cbor_string(chunk))
+                    {
+                        return false;
+                    }
+                    result.append(chunk);
+                }
+                return true;
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType()));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a CBOR byte array
+
+    This function first reads starting bytes to determine the expected
+    byte array length and then copies this number of bytes into the byte array.
+    Additionally, CBOR's byte arrays with indefinite lengths are supported.
+
+    @param[out] result  created byte array
+
+    @return whether byte array creation completed
+    */
+    bool get_cbor_binary(binary_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            // Binary data (0x00..0x17 bytes follow)
+            case 0x40:
+            case 0x41:
+            case 0x42:
+            case 0x43:
+            case 0x44:
+            case 0x45:
+            case 0x46:
+            case 0x47:
+            case 0x48:
+            case 0x49:
+            case 0x4A:
+            case 0x4B:
+            case 0x4C:
+            case 0x4D:
+            case 0x4E:
+            case 0x4F:
+            case 0x50:
+            case 0x51:
+            case 0x52:
+            case 0x53:
+            case 0x54:
+            case 0x55:
+            case 0x56:
+            case 0x57:
+            {
+                return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
+            }
+
+            case 0x58: // Binary data (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::cbor, len) &&
+                       get_binary(input_format_t::cbor, len, result);
+            }
+
+            case 0x59: // Binary data (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::cbor, len) &&
+                       get_binary(input_format_t::cbor, len, result);
+            }
+
+            case 0x5A: // Binary data (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::cbor, len) &&
+                       get_binary(input_format_t::cbor, len, result);
+            }
+
+            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len{};
+                return get_number(input_format_t::cbor, len) &&
+                       get_binary(input_format_t::cbor, len, result);
+            }
+
+            case 0x5F: // Binary data (indefinite length)
+            {
+                while (get() != 0xFF)
+                {
+                    binary_t chunk;
+                    if (!get_cbor_binary(chunk))
+                    {
+                        return false;
+                    }
+                    result.insert(result.end(), chunk.begin(), chunk.end());
+                }
+                return true;
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType()));
+            }
+        }
+    }
+
+    /*!
+    @param[in] len  the length of the array or std::size_t(-1) for an
+                    array of indefinite size
+    @param[in] tag_handler how CBOR tags should be treated
+    @return whether array creation completed
+    */
+    bool get_cbor_array(const std::size_t len,
+                        const cbor_tag_handler_t tag_handler)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
+        {
+            return false;
+        }
+
+        if (len != std::size_t(-1))
+        {
+            for (std::size_t i = 0; i < len; ++i)
+            {
+                if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+                {
+                    return false;
+                }
+            }
+        }
+        else
+        {
+            while (get() != 0xFF)
+            {
+                if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
+                {
+                    return false;
+                }
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @param[in] len  the length of the object or std::size_t(-1) for an
+                    object of indefinite size
+    @param[in] tag_handler how CBOR tags should be treated
+    @return whether object creation completed
+    */
+    bool get_cbor_object(const std::size_t len,
+                         const cbor_tag_handler_t tag_handler)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
+        {
+            return false;
+        }
+
+        if (len != 0)
+        {
+            string_t key;
+            if (len != std::size_t(-1))
+            {
+                for (std::size_t i = 0; i < len; ++i)
+                {
+                    get();
+                    if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
+                    {
+                        return false;
+                    }
+
+                    if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+            else
+            {
+                while (get() != 0xFF)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
+                    {
+                        return false;
+                    }
+
+                    if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+        }
+
+        return sax->end_object();
+    }
+
+    /////////////
+    // MsgPack //
+    /////////////
+
+    /*!
+    @return whether a valid MessagePack value was passed to the SAX parser
+    */
+    bool parse_msgpack_internal()
+    {
+        switch (get())
+        {
+            // EOF
+            case std::char_traits<char_type>::eof():
+                return unexpect_eof(input_format_t::msgpack, "value");
+
+            // positive fixint
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x04:
+            case 0x05:
+            case 0x06:
+            case 0x07:
+            case 0x08:
+            case 0x09:
+            case 0x0A:
+            case 0x0B:
+            case 0x0C:
+            case 0x0D:
+            case 0x0E:
+            case 0x0F:
+            case 0x10:
+            case 0x11:
+            case 0x12:
+            case 0x13:
+            case 0x14:
+            case 0x15:
+            case 0x16:
+            case 0x17:
+            case 0x18:
+            case 0x19:
+            case 0x1A:
+            case 0x1B:
+            case 0x1C:
+            case 0x1D:
+            case 0x1E:
+            case 0x1F:
+            case 0x20:
+            case 0x21:
+            case 0x22:
+            case 0x23:
+            case 0x24:
+            case 0x25:
+            case 0x26:
+            case 0x27:
+            case 0x28:
+            case 0x29:
+            case 0x2A:
+            case 0x2B:
+            case 0x2C:
+            case 0x2D:
+            case 0x2E:
+            case 0x2F:
+            case 0x30:
+            case 0x31:
+            case 0x32:
+            case 0x33:
+            case 0x34:
+            case 0x35:
+            case 0x36:
+            case 0x37:
+            case 0x38:
+            case 0x39:
+            case 0x3A:
+            case 0x3B:
+            case 0x3C:
+            case 0x3D:
+            case 0x3E:
+            case 0x3F:
+            case 0x40:
+            case 0x41:
+            case 0x42:
+            case 0x43:
+            case 0x44:
+            case 0x45:
+            case 0x46:
+            case 0x47:
+            case 0x48:
+            case 0x49:
+            case 0x4A:
+            case 0x4B:
+            case 0x4C:
+            case 0x4D:
+            case 0x4E:
+            case 0x4F:
+            case 0x50:
+            case 0x51:
+            case 0x52:
+            case 0x53:
+            case 0x54:
+            case 0x55:
+            case 0x56:
+            case 0x57:
+            case 0x58:
+            case 0x59:
+            case 0x5A:
+            case 0x5B:
+            case 0x5C:
+            case 0x5D:
+            case 0x5E:
+            case 0x5F:
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            case 0x78:
+            case 0x79:
+            case 0x7A:
+            case 0x7B:
+            case 0x7C:
+            case 0x7D:
+            case 0x7E:
+            case 0x7F:
+                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
+
+            // fixmap
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+            case 0x88:
+            case 0x89:
+            case 0x8A:
+            case 0x8B:
+            case 0x8C:
+            case 0x8D:
+            case 0x8E:
+            case 0x8F:
+                return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+
+            // fixarray
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+            case 0x98:
+            case 0x99:
+            case 0x9A:
+            case 0x9B:
+            case 0x9C:
+            case 0x9D:
+            case 0x9E:
+            case 0x9F:
+                return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+
+            // fixstr
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+            case 0xB8:
+            case 0xB9:
+            case 0xBA:
+            case 0xBB:
+            case 0xBC:
+            case 0xBD:
+            case 0xBE:
+            case 0xBF:
+            case 0xD9: // str 8
+            case 0xDA: // str 16
+            case 0xDB: // str 32
+            {
+                string_t s;
+                return get_msgpack_string(s) && sax->string(s);
+            }
+
+            case 0xC0: // nil
+                return sax->null();
+
+            case 0xC2: // false
+                return sax->boolean(false);
+
+            case 0xC3: // true
+                return sax->boolean(true);
+
+            case 0xC4: // bin 8
+            case 0xC5: // bin 16
+            case 0xC6: // bin 32
+            case 0xC7: // ext 8
+            case 0xC8: // ext 16
+            case 0xC9: // ext 32
+            case 0xD4: // fixext 1
+            case 0xD5: // fixext 2
+            case 0xD6: // fixext 4
+            case 0xD7: // fixext 8
+            case 0xD8: // fixext 16
+            {
+                binary_t b;
+                return get_msgpack_binary(b) && sax->binary(b);
+            }
+
+            case 0xCA: // float 32
+            {
+                float number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xCB: // float 64
+            {
+                double number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xCC: // uint 8
+            {
+                std::uint8_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+            }
+
+            case 0xCD: // uint 16
+            {
+                std::uint16_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+            }
+
+            case 0xCE: // uint 32
+            {
+                std::uint32_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+            }
+
+            case 0xCF: // uint 64
+            {
+                std::uint64_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+            }
+
+            case 0xD0: // int 8
+            {
+                std::int8_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+            }
+
+            case 0xD1: // int 16
+            {
+                std::int16_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+            }
+
+            case 0xD2: // int 32
+            {
+                std::int32_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+            }
+
+            case 0xD3: // int 64
+            {
+                std::int64_t number{};
+                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+            }
+
+            case 0xDC: // array 16
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
+            }
+
+            case 0xDD: // array 32
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
+            }
+
+            case 0xDE: // map 16
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
+            }
+
+            case 0xDF: // map 32
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
+            }
+
+            // negative fixint
+            case 0xE0:
+            case 0xE1:
+            case 0xE2:
+            case 0xE3:
+            case 0xE4:
+            case 0xE5:
+            case 0xE6:
+            case 0xE7:
+            case 0xE8:
+            case 0xE9:
+            case 0xEA:
+            case 0xEB:
+            case 0xEC:
+            case 0xED:
+            case 0xEE:
+            case 0xEF:
+            case 0xF0:
+            case 0xF1:
+            case 0xF2:
+            case 0xF3:
+            case 0xF4:
+            case 0xF5:
+            case 0xF6:
+            case 0xF7:
+            case 0xF8:
+            case 0xF9:
+            case 0xFA:
+            case 0xFB:
+            case 0xFC:
+            case 0xFD:
+            case 0xFE:
+            case 0xFF:
+                return sax->number_integer(static_cast<std::int8_t>(current));
+
+            default: // anything else
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a MessagePack string
+
+    This function first reads starting bytes to determine the expected
+    string length and then copies this number of bytes into a string.
+
+    @param[out] result  created string
+
+    @return whether string creation completed
+    */
+    bool get_msgpack_string(string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            // fixstr
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+            case 0xB8:
+            case 0xB9:
+            case 0xBA:
+            case 0xBB:
+            case 0xBC:
+            case 0xBD:
+            case 0xBE:
+            case 0xBF:
+            {
+                return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
+            }
+
+            case 0xD9: // str 8
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+            }
+
+            case 0xDA: // str 16
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+            }
+
+            case 0xDB: // str 32
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType()));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a MessagePack byte array
+
+    This function first reads starting bytes to determine the expected
+    byte array length and then copies this number of bytes into a byte array.
+
+    @param[out] result  created byte array
+
+    @return whether byte array creation completed
+    */
+    bool get_msgpack_binary(binary_t& result)
+    {
+        // helper function to set the subtype
+        auto assign_and_return_true = [&result](std::int8_t subtype)
+        {
+            result.set_subtype(static_cast<std::uint8_t>(subtype));
+            return true;
+        };
+
+        switch (current)
+        {
+            case 0xC4: // bin 8
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_binary(input_format_t::msgpack, len, result);
+            }
+
+            case 0xC5: // bin 16
+            {
+                std::uint16_t len{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_binary(input_format_t::msgpack, len, result);
+            }
+
+            case 0xC6: // bin 32
+            {
+                std::uint32_t len{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_binary(input_format_t::msgpack, len, result);
+            }
+
+            case 0xC7: // ext 8
+            {
+                std::uint8_t len{};
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, len, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xC8: // ext 16
+            {
+                std::uint16_t len{};
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, len, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xC9: // ext 32
+            {
+                std::uint32_t len{};
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, len) &&
+                       get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, len, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD4: // fixext 1
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 1, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD5: // fixext 2
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 2, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD6: // fixext 4
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 4, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD7: // fixext 8
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 8, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            case 0xD8: // fixext 16
+            {
+                std::int8_t subtype{};
+                return get_number(input_format_t::msgpack, subtype) &&
+                       get_binary(input_format_t::msgpack, 16, result) &&
+                       assign_and_return_true(subtype);
+            }
+
+            default:           // LCOV_EXCL_LINE
+                return false;  // LCOV_EXCL_LINE
+        }
+    }
+
+    /*!
+    @param[in] len  the length of the array
+    @return whether array creation completed
+    */
+    bool get_msgpack_array(const std::size_t len)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
+        {
+            return false;
+        }
+
+        for (std::size_t i = 0; i < len; ++i)
+        {
+            if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
+            {
+                return false;
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @param[in] len  the length of the object
+    @return whether object creation completed
+    */
+    bool get_msgpack_object(const std::size_t len)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
+        {
+            return false;
+        }
+
+        string_t key;
+        for (std::size_t i = 0; i < len; ++i)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
+            {
+                return false;
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
+            {
+                return false;
+            }
+            key.clear();
+        }
+
+        return sax->end_object();
+    }
+
+    ////////////
+    // UBJSON //
+    ////////////
+
+    /*!
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true, default) or whether the last read
+                         character should be considered instead
+
+    @return whether a valid UBJSON value was passed to the SAX parser
+    */
+    bool parse_ubjson_internal(const bool get_char = true)
+    {
+        return get_ubjson_value(get_char ? get_ignore_noop() : current);
+    }
+
+    /*!
+    @brief reads a UBJSON string
+
+    This function is either called after reading the 'S' byte explicitly
+    indicating a string, or in case of an object key where the 'S' byte can be
+    left out.
+
+    @param[out] result   created string
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true, default) or whether the last read
+                         character should be considered instead
+
+    @return whether string creation completed
+    */
+    bool get_ubjson_string(string_t& result, const bool get_char = true)
+    {
+        if (get_char)
+        {
+            get();  // TODO(niels): may we ignore N here?
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            case 'U':
+            {
+                std::uint8_t len{};
+                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+            }
+
+            case 'i':
+            {
+                std::int8_t len{};
+                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+            }
+
+            case 'I':
+            {
+                std::int16_t len{};
+                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+            }
+
+            case 'l':
+            {
+                std::int32_t len{};
+                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+            }
+
+            case 'L':
+            {
+                std::int64_t len{};
+                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+            }
+
+            default:
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType()));
+        }
+    }
+
+    /*!
+    @param[out] result  determined size
+    @return whether size determination completed
+    */
+    bool get_ubjson_size_value(std::size_t& result)
+    {
+        switch (get_ignore_noop())
+        {
+            case 'U':
+            {
+                std::uint8_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'i':
+            {
+                std::int8_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
+                return true;
+            }
+
+            case 'I':
+            {
+                std::int16_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'l':
+            {
+                std::int32_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'L':
+            {
+                std::int64_t number{};
+                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType()));
+            }
+        }
+    }
+
+    /*!
+    @brief determine the type and size for a container
+
+    In the optimized UBJSON format, a type and a size can be provided to allow
+    for a more compact representation.
+
+    @param[out] result  pair of the size and the type
+
+    @return whether pair creation completed
+    */
+    bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
+    {
+        result.first = string_t::npos; // size
+        result.second = 0; // type
+
+        get_ignore_noop();
+
+        if (current == '$')
+        {
+            result.second = get();  // must not ignore 'N', because 'N' maybe the type
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
+            {
+                return false;
+            }
+
+            get_ignore_noop();
+            if (JSON_HEDLEY_UNLIKELY(current != '#'))
+            {
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
+                {
+                    return false;
+                }
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType()));
+            }
+
+            return get_ubjson_size_value(result.first);
+        }
+
+        if (current == '#')
+        {
+            return get_ubjson_size_value(result.first);
+        }
+
+        return true;
+    }
+
+    /*!
+    @param prefix  the previously read or set type prefix
+    @return whether value creation completed
+    */
+    bool get_ubjson_value(const char_int_type prefix)
+    {
+        switch (prefix)
+        {
+            case std::char_traits<char_type>::eof():  // EOF
+                return unexpect_eof(input_format_t::ubjson, "value");
+
+            case 'T':  // true
+                return sax->boolean(true);
+            case 'F':  // false
+                return sax->boolean(false);
+
+            case 'Z':  // null
+                return sax->null();
+
+            case 'U':
+            {
+                std::uint8_t number{};
+                return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
+            }
+
+            case 'i':
+            {
+                std::int8_t number{};
+                return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+            }
+
+            case 'I':
+            {
+                std::int16_t number{};
+                return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+            }
+
+            case 'l':
+            {
+                std::int32_t number{};
+                return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+            }
+
+            case 'L':
+            {
+                std::int64_t number{};
+                return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+            }
+
+            case 'd':
+            {
+                float number{};
+                return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 'D':
+            {
+                double number{};
+                return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 'H':
+            {
+                return get_ubjson_high_precision_number();
+            }
+
+            case 'C':  // char
+            {
+                get();
+                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
+                {
+                    return false;
+                }
+                if (JSON_HEDLEY_UNLIKELY(current > 127))
+                {
+                    auto last_token = get_token_string();
+                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType()));
+                }
+                string_t s(1, static_cast<typename string_t::value_type>(current));
+                return sax->string(s);
+            }
+
+            case 'S':  // string
+            {
+                string_t s;
+                return get_ubjson_string(s) && sax->string(s);
+            }
+
+            case '[':  // array
+                return get_ubjson_array();
+
+            case '{':  // object
+                return get_ubjson_object();
+
+            default: // anything else
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+            }
+        }
+    }
+
+    /*!
+    @return whether array creation completed
+    */
+    bool get_ubjson_array()
+    {
+        std::pair<std::size_t, char_int_type> size_and_type;
+        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
+        {
+            return false;
+        }
+
+        if (size_and_type.first != string_t::npos)
+        {
+            if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
+            {
+                return false;
+            }
+
+            if (size_and_type.second != 0)
+            {
+                if (size_and_type.second != 'N')
+                {
+                    for (std::size_t i = 0; i < size_and_type.first; ++i)
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
+                        {
+                            return false;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+                    {
+                        return false;
+                    }
+                }
+            }
+        }
+        else
+        {
+            if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
+            {
+                return false;
+            }
+
+            while (current != ']')
+            {
+                if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
+                {
+                    return false;
+                }
+                get_ignore_noop();
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @return whether object creation completed
+    */
+    bool get_ubjson_object()
+    {
+        std::pair<std::size_t, char_int_type> size_and_type;
+        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
+        {
+            return false;
+        }
+
+        string_t key;
+        if (size_and_type.first != string_t::npos)
+        {
+            if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
+            {
+                return false;
+            }
+
+            if (size_and_type.second != 0)
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
+                    {
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+            else
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
+                    {
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+        }
+        else
+        {
+            if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
+            {
+                return false;
+            }
+
+            while (current != '}')
+            {
+                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
+                {
+                    return false;
+                }
+                if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+                {
+                    return false;
+                }
+                get_ignore_noop();
+                key.clear();
+            }
+        }
+
+        return sax->end_object();
+    }
+
+    // Note, no reader for UBJSON binary types is implemented because they do
+    // not exist
+
+    bool get_ubjson_high_precision_number()
+    {
+        // get size of following number string
+        std::size_t size{};
+        auto res = get_ubjson_size_value(size);
+        if (JSON_HEDLEY_UNLIKELY(!res))
+        {
+            return res;
+        }
+
+        // get number string
+        std::vector<char> number_vector;
+        for (std::size_t i = 0; i < size; ++i)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
+            {
+                return false;
+            }
+            number_vector.push_back(static_cast<char>(current));
+        }
+
+        // parse number string
+        using ia_type = decltype(detail::input_adapter(number_vector));
+        auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
+        const auto result_number = number_lexer.scan();
+        const auto number_string = number_lexer.get_token_string();
+        const auto result_remainder = number_lexer.scan();
+
+        using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
+
+        if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
+        {
+            return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
+        }
+
+        switch (result_number)
+        {
+            case token_type::value_integer:
+                return sax->number_integer(number_lexer.get_number_integer());
+            case token_type::value_unsigned:
+                return sax->number_unsigned(number_lexer.get_number_unsigned());
+            case token_type::value_float:
+                return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
+            case token_type::uninitialized:
+            case token_type::literal_true:
+            case token_type::literal_false:
+            case token_type::literal_null:
+            case token_type::value_string:
+            case token_type::begin_array:
+            case token_type::begin_object:
+            case token_type::end_array:
+            case token_type::end_object:
+            case token_type::name_separator:
+            case token_type::value_separator:
+            case token_type::parse_error:
+            case token_type::end_of_input:
+            case token_type::literal_or_value:
+            default:
+                return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
+        }
+    }
+
+    ///////////////////////
+    // Utility functions //
+    ///////////////////////
+
+    /*!
+    @brief get next character from the input
+
+    This function provides the interface to the used input adapter. It does
+    not throw in case the input reached EOF, but returns a -'ve valued
+    `std::char_traits<char_type>::eof()` in that case.
+
+    @return character read from the input
+    */
+    char_int_type get()
+    {
+        ++chars_read;
+        return current = ia.get_character();
+    }
+
+    /*!
+    @return character read from the input after ignoring all 'N' entries
+    */
+    char_int_type get_ignore_noop()
+    {
+        do
+        {
+            get();
+        }
+        while (current == 'N');
+
+        return current;
+    }
+
+    /*
+    @brief read a number from the input
+
+    @tparam NumberType the type of the number
+    @param[in] format   the current format (for diagnostics)
+    @param[out] result  number of type @a NumberType
+
+    @return whether conversion completed
+
+    @note This function needs to respect the system's endianness, because
+          bytes in CBOR, MessagePack, and UBJSON are stored in network order
+          (big endian) and therefore need reordering on little endian systems.
+    */
+    template<typename NumberType, bool InputIsLittleEndian = false>
+    bool get_number(const input_format_t format, NumberType& result)
+    {
+        // step 1: read input into array with system's byte order
+        std::array<std::uint8_t, sizeof(NumberType)> vec{};
+        for (std::size_t i = 0; i < sizeof(NumberType); ++i)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
+            {
+                return false;
+            }
+
+            // reverse byte order prior to conversion if necessary
+            if (is_little_endian != InputIsLittleEndian)
+            {
+                vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
+            }
+            else
+            {
+                vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
+            }
+        }
+
+        // step 2: convert array into number of type T and return
+        std::memcpy(&result, vec.data(), sizeof(NumberType));
+        return true;
+    }
+
+    /*!
+    @brief create a string by reading characters from the input
+
+    @tparam NumberType the type of the number
+    @param[in] format the current format (for diagnostics)
+    @param[in] len number of characters to read
+    @param[out] result string created by reading @a len bytes
+
+    @return whether string creation completed
+
+    @note We can not reserve @a len bytes for the result, because @a len
+          may be too large. Usually, @ref unexpect_eof() detects the end of
+          the input before we run out of string memory.
+    */
+    template<typename NumberType>
+    bool get_string(const input_format_t format,
+                    const NumberType len,
+                    string_t& result)
+    {
+        bool success = true;
+        for (NumberType i = 0; i < len; i++)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
+            {
+                success = false;
+                break;
+            }
+            result.push_back(static_cast<typename string_t::value_type>(current));
+        }
+        return success;
+    }
+
+    /*!
+    @brief create a byte array by reading bytes from the input
+
+    @tparam NumberType the type of the number
+    @param[in] format the current format (for diagnostics)
+    @param[in] len number of bytes to read
+    @param[out] result byte array created by reading @a len bytes
+
+    @return whether byte array creation completed
+
+    @note We can not reserve @a len bytes for the result, because @a len
+          may be too large. Usually, @ref unexpect_eof() detects the end of
+          the input before we run out of memory.
+    */
+    template<typename NumberType>
+    bool get_binary(const input_format_t format,
+                    const NumberType len,
+                    binary_t& result)
+    {
+        bool success = true;
+        for (NumberType i = 0; i < len; i++)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
+            {
+                success = false;
+                break;
+            }
+            result.push_back(static_cast<std::uint8_t>(current));
+        }
+        return success;
+    }
+
+    /*!
+    @param[in] format   the current format (for diagnostics)
+    @param[in] context  further context information (for diagnostics)
+    @return whether the last read character is not EOF
+    */
+    JSON_HEDLEY_NON_NULL(3)
+    bool unexpect_eof(const input_format_t format, const char* context) const
+    {
+        if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
+        {
+            return sax->parse_error(chars_read, "<end of file>",
+                                    parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
+        }
+        return true;
+    }
+
+    /*!
+    @return a string representation of the last read byte
+    */
+    std::string get_token_string() const
+    {
+        std::array<char, 3> cr{{}};
+        (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+        return std::string{cr.data()};
+    }
+
+    /*!
+    @param[in] format   the current format
+    @param[in] detail   a detailed error message
+    @param[in] context  further context information
+    @return a message string to use in the parse_error exceptions
+    */
+    std::string exception_message(const input_format_t format,
+                                  const std::string& detail,
+                                  const std::string& context) const
+    {
+        std::string error_msg = "syntax error while parsing ";
+
+        switch (format)
+        {
+            case input_format_t::cbor:
+                error_msg += "CBOR";
+                break;
+
+            case input_format_t::msgpack:
+                error_msg += "MessagePack";
+                break;
+
+            case input_format_t::ubjson:
+                error_msg += "UBJSON";
+                break;
+
+            case input_format_t::bson:
+                error_msg += "BSON";
+                break;
+
+            case input_format_t::json: // LCOV_EXCL_LINE
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+
+        return error_msg + " " + context + ": " + detail;
+    }
+
+  private:
+    /// input adapter
+    InputAdapterType ia;
+
+    /// the current character
+    char_int_type current = std::char_traits<char_type>::eof();
+
+    /// the number of characters read
+    std::size_t chars_read = 0;
+
+    /// whether we can assume little endianness
+    const bool is_little_endian = little_endianness();
+
+    /// the SAX parser
+    json_sax_t* sax = nullptr;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+// #include <nlohmann/detail/input/parser.hpp>
+
+
+#include <cmath> // isfinite
+#include <cstdint> // uint8_t
+#include <functional> // function
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/json_sax.hpp>
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+////////////
+// parser //
+////////////
+
+enum class parse_event_t : std::uint8_t
+{
+    /// the parser read `{` and started to process a JSON object
+    object_start,
+    /// the parser read `}` and finished processing a JSON object
+    object_end,
+    /// the parser read `[` and started to process a JSON array
+    array_start,
+    /// the parser read `]` and finished processing a JSON array
+    array_end,
+    /// the parser read a key of a value in an object
+    key,
+    /// the parser finished reading a JSON value
+    value
+};
+
+template<typename BasicJsonType>
+using parser_callback_t =
+    std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
+
+/*!
+@brief syntax analysis
+
+This class implements a recursive descent parser.
+*/
+template<typename BasicJsonType, typename InputAdapterType>
+class parser
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using lexer_t = lexer<BasicJsonType, InputAdapterType>;
+    using token_type = typename lexer_t::token_type;
+
+  public:
+    /// a parser reading from an input adapter
+    explicit parser(InputAdapterType&& adapter,
+                    const parser_callback_t<BasicJsonType> cb = nullptr,
+                    const bool allow_exceptions_ = true,
+                    const bool skip_comments = false)
+        : callback(cb)
+        , m_lexer(std::move(adapter), skip_comments)
+        , allow_exceptions(allow_exceptions_)
+    {
+        // read first token
+        get_token();
+    }
+
+    /*!
+    @brief public parser interface
+
+    @param[in] strict      whether to expect the last token to be EOF
+    @param[in,out] result  parsed JSON value
+
+    @throw parse_error.101 in case of an unexpected token
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+    */
+    void parse(const bool strict, BasicJsonType& result)
+    {
+        if (callback)
+        {
+            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
+            sax_parse_internal(&sdp);
+
+            // in strict mode, input must be completely read
+            if (strict && (get_token() != token_type::end_of_input))
+            {
+                sdp.parse_error(m_lexer.get_position(),
+                                m_lexer.get_token_string(),
+                                parse_error::create(101, m_lexer.get_position(),
+                                                    exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+            }
+
+            // in case of an error, return discarded value
+            if (sdp.is_errored())
+            {
+                result = value_t::discarded;
+                return;
+            }
+
+            // set top-level value to null if it was discarded by the callback
+            // function
+            if (result.is_discarded())
+            {
+                result = nullptr;
+            }
+        }
+        else
+        {
+            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
+            sax_parse_internal(&sdp);
+
+            // in strict mode, input must be completely read
+            if (strict && (get_token() != token_type::end_of_input))
+            {
+                sdp.parse_error(m_lexer.get_position(),
+                                m_lexer.get_token_string(),
+                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+            }
+
+            // in case of an error, return discarded value
+            if (sdp.is_errored())
+            {
+                result = value_t::discarded;
+                return;
+            }
+        }
+
+        result.assert_invariant();
+    }
+
+    /*!
+    @brief public accept interface
+
+    @param[in] strict  whether to expect the last token to be EOF
+    @return whether the input is a proper JSON text
+    */
+    bool accept(const bool strict = true)
+    {
+        json_sax_acceptor<BasicJsonType> sax_acceptor;
+        return sax_parse(&sax_acceptor, strict);
+    }
+
+    template<typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    bool sax_parse(SAX* sax, const bool strict = true)
+    {
+        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+        const bool result = sax_parse_internal(sax);
+
+        // strict mode: next byte must be EOF
+        if (result && strict && (get_token() != token_type::end_of_input))
+        {
+            return sax->parse_error(m_lexer.get_position(),
+                                    m_lexer.get_token_string(),
+                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+        }
+
+        return result;
+    }
+
+  private:
+    template<typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    bool sax_parse_internal(SAX* sax)
+    {
+        // stack to remember the hierarchy of structured values we are parsing
+        // true = array; false = object
+        std::vector<bool> states;
+        // value to avoid a goto (see comment where set to true)
+        bool skip_to_state_evaluation = false;
+
+        while (true)
+        {
+            if (!skip_to_state_evaluation)
+            {
+                // invariant: get_token() was called before each iteration
+                switch (last_token)
+                {
+                    case token_type::begin_object:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
+                        {
+                            return false;
+                        }
+
+                        // closing } -> we are done
+                        if (get_token() == token_type::end_object)
+                        {
+                            if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
+                            {
+                                return false;
+                            }
+                            break;
+                        }
+
+                        // parse key
+                        if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
+                        }
+                        if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+
+                        // parse separator (:)
+                        if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
+                        }
+
+                        // remember we are now inside an object
+                        states.push_back(false);
+
+                        // parse values
+                        get_token();
+                        continue;
+                    }
+
+                    case token_type::begin_array:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
+                        {
+                            return false;
+                        }
+
+                        // closing ] -> we are done
+                        if (get_token() == token_type::end_array)
+                        {
+                            if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
+                            {
+                                return false;
+                            }
+                            break;
+                        }
+
+                        // remember we are now inside an array
+                        states.push_back(true);
+
+                        // parse values (no need to call get_token)
+                        continue;
+                    }
+
+                    case token_type::value_float:
+                    {
+                        const auto res = m_lexer.get_number_float();
+
+                        if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType()));
+                        }
+
+                        if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+
+                        break;
+                    }
+
+                    case token_type::literal_false:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::literal_null:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->null()))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::literal_true:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_integer:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_string:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_unsigned:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::parse_error:
+                    {
+                        // using "uninitialized" to avoid "expected" message
+                        return sax->parse_error(m_lexer.get_position(),
+                                                m_lexer.get_token_string(),
+                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType()));
+                    }
+
+                    case token_type::uninitialized:
+                    case token_type::end_array:
+                    case token_type::end_object:
+                    case token_type::name_separator:
+                    case token_type::value_separator:
+                    case token_type::end_of_input:
+                    case token_type::literal_or_value:
+                    default: // the last token was unexpected
+                    {
+                        return sax->parse_error(m_lexer.get_position(),
+                                                m_lexer.get_token_string(),
+                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType()));
+                    }
+                }
+            }
+            else
+            {
+                skip_to_state_evaluation = false;
+            }
+
+            // we reached this line after we successfully parsed a value
+            if (states.empty())
+            {
+                // empty stack: we reached the end of the hierarchy: done
+                return true;
+            }
+
+            if (states.back())  // array
+            {
+                // comma -> next value
+                if (get_token() == token_type::value_separator)
+                {
+                    // parse a new value
+                    get_token();
+                    continue;
+                }
+
+                // closing ]
+                if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
+                {
+                    if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
+                    {
+                        return false;
+                    }
+
+                    // We are done with this array. Before we can parse a
+                    // new value, we need to evaluate the new state first.
+                    // By setting skip_to_state_evaluation to false, we
+                    // are effectively jumping to the beginning of this if.
+                    JSON_ASSERT(!states.empty());
+                    states.pop_back();
+                    skip_to_state_evaluation = true;
+                    continue;
+                }
+
+                return sax->parse_error(m_lexer.get_position(),
+                                        m_lexer.get_token_string(),
+                                        parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType()));
+            }
+
+            // states.back() is false -> object
+
+            // comma -> next value
+            if (get_token() == token_type::value_separator)
+            {
+                // parse key
+                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
+                {
+                    return sax->parse_error(m_lexer.get_position(),
+                                            m_lexer.get_token_string(),
+                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
+                }
+
+                if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
+                {
+                    return false;
+                }
+
+                // parse separator (:)
+                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
+                {
+                    return sax->parse_error(m_lexer.get_position(),
+                                            m_lexer.get_token_string(),
+                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
+                }
+
+                // parse values
+                get_token();
+                continue;
+            }
+
+            // closing }
+            if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
+            {
+                if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
+                {
+                    return false;
+                }
+
+                // We are done with this object. Before we can parse a
+                // new value, we need to evaluate the new state first.
+                // By setting skip_to_state_evaluation to false, we
+                // are effectively jumping to the beginning of this if.
+                JSON_ASSERT(!states.empty());
+                states.pop_back();
+                skip_to_state_evaluation = true;
+                continue;
+            }
+
+            return sax->parse_error(m_lexer.get_position(),
+                                    m_lexer.get_token_string(),
+                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType()));
+        }
+    }
+
+    /// get next token from lexer
+    token_type get_token()
+    {
+        return last_token = m_lexer.scan();
+    }
+
+    std::string exception_message(const token_type expected, const std::string& context)
+    {
+        std::string error_msg = "syntax error ";
+
+        if (!context.empty())
+        {
+            error_msg += "while parsing " + context + " ";
+        }
+
+        error_msg += "- ";
+
+        if (last_token == token_type::parse_error)
+        {
+            error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
+                         m_lexer.get_token_string() + "'";
+        }
+        else
+        {
+            error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
+        }
+
+        if (expected != token_type::uninitialized)
+        {
+            error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
+        }
+
+        return error_msg;
+    }
+
+  private:
+    /// callback function
+    const parser_callback_t<BasicJsonType> callback = nullptr;
+    /// the type of the last read token
+    token_type last_token = token_type::uninitialized;
+    /// the lexer
+    lexer_t m_lexer;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+};
+
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+
+#include <cstddef> // ptrdiff_t
+#include <limits>  // numeric_limits
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/*
+@brief an iterator for primitive JSON types
+
+This class models an iterator for primitive JSON types (boolean, number,
+string). It's only purpose is to allow the iterator/const_iterator classes
+to "iterate" over primitive values. Internally, the iterator is modeled by
+a `difference_type` variable. Value begin_value (`0`) models the begin,
+end_value (`1`) models past the end.
+*/
+class primitive_iterator_t
+{
+  private:
+    using difference_type = std::ptrdiff_t;
+    static constexpr difference_type begin_value = 0;
+    static constexpr difference_type end_value = begin_value + 1;
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /// iterator as signed integer type
+    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
+
+  public:
+    constexpr difference_type get_value() const noexcept
+    {
+        return m_it;
+    }
+
+    /// set iterator to a defined beginning
+    void set_begin() noexcept
+    {
+        m_it = begin_value;
+    }
+
+    /// set iterator to a defined past the end
+    void set_end() noexcept
+    {
+        m_it = end_value;
+    }
+
+    /// return whether the iterator can be dereferenced
+    constexpr bool is_begin() const noexcept
+    {
+        return m_it == begin_value;
+    }
+
+    /// return whether the iterator is at end
+    constexpr bool is_end() const noexcept
+    {
+        return m_it == end_value;
+    }
+
+    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it == rhs.m_it;
+    }
+
+    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it < rhs.m_it;
+    }
+
+    primitive_iterator_t operator+(difference_type n) noexcept
+    {
+        auto result = *this;
+        result += n;
+        return result;
+    }
+
+    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it - rhs.m_it;
+    }
+
+    primitive_iterator_t& operator++() noexcept
+    {
+        ++m_it;
+        return *this;
+    }
+
+    primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type)
+    {
+        auto result = *this;
+        ++m_it;
+        return result;
+    }
+
+    primitive_iterator_t& operator--() noexcept
+    {
+        --m_it;
+        return *this;
+    }
+
+    primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type)
+    {
+        auto result = *this;
+        --m_it;
+        return result;
+    }
+
+    primitive_iterator_t& operator+=(difference_type n) noexcept
+    {
+        m_it += n;
+        return *this;
+    }
+
+    primitive_iterator_t& operator-=(difference_type n) noexcept
+    {
+        m_it -= n;
+        return *this;
+    }
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/*!
+@brief an iterator value
+
+@note This structure could easily be a union, but MSVC currently does not allow
+unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
+*/
+template<typename BasicJsonType> struct internal_iterator
+{
+    /// iterator for JSON objects
+    typename BasicJsonType::object_t::iterator object_iterator {};
+    /// iterator for JSON arrays
+    typename BasicJsonType::array_t::iterator array_iterator {};
+    /// generic iterator for all other types
+    primitive_iterator_t primitive_iterator {};
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/iter_impl.hpp>
+
+
+#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
+#include <type_traits> // conditional, is_const, remove_const
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+// forward declare, to be able to friend it later on
+template<typename IteratorType> class iteration_proxy;
+template<typename IteratorType> class iteration_proxy_value;
+
+/*!
+@brief a template for a bidirectional iterator for the @ref basic_json class
+This class implements a both iterators (iterator and const_iterator) for the
+@ref basic_json class.
+@note An iterator is called *initialized* when a pointer to a JSON value has
+      been set (e.g., by a constructor or a copy assignment). If the iterator is
+      default-constructed, it is *uninitialized* and most methods are undefined.
+      **The library uses assertions to detect calls on uninitialized iterators.**
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
+  The iterator that can be moved can be moved in both directions (i.e.
+  incremented and decremented).
+@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
+       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
+*/
+template<typename BasicJsonType>
+class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+{
+    /// the iterator with BasicJsonType of different const-ness
+    using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
+    /// allow basic_json to access private members
+    friend other_iter_impl;
+    friend BasicJsonType;
+    friend iteration_proxy<iter_impl>;
+    friend iteration_proxy_value<iter_impl>;
+
+    using object_t = typename BasicJsonType::object_t;
+    using array_t = typename BasicJsonType::array_t;
+    // make sure BasicJsonType is basic_json or const basic_json
+    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
+                  "iter_impl only accepts (const) basic_json");
+
+  public:
+
+    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
+    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
+    /// A user-defined iterator should provide publicly accessible typedefs named
+    /// iterator_category, value_type, difference_type, pointer, and reference.
+    /// Note that value_type is required to be non-const, even for constant iterators.
+    using iterator_category = std::bidirectional_iterator_tag;
+
+    /// the type of the values when the iterator is dereferenced
+    using value_type = typename BasicJsonType::value_type;
+    /// a type to represent differences between iterators
+    using difference_type = typename BasicJsonType::difference_type;
+    /// defines a pointer to the type iterated over (value_type)
+    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
+          typename BasicJsonType::const_pointer,
+          typename BasicJsonType::pointer>::type;
+    /// defines a reference to the type iterated over (value_type)
+    using reference =
+        typename std::conditional<std::is_const<BasicJsonType>::value,
+        typename BasicJsonType::const_reference,
+        typename BasicJsonType::reference>::type;
+
+    iter_impl() = default;
+    ~iter_impl() = default;
+    iter_impl(iter_impl&&) noexcept = default;
+    iter_impl& operator=(iter_impl&&) noexcept = default;
+
+    /*!
+    @brief constructor for a given JSON instance
+    @param[in] object  pointer to a JSON object for this iterator
+    @pre object != nullptr
+    @post The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    explicit iter_impl(pointer object) noexcept : m_object(object)
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = typename object_t::iterator();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = typename array_t::iterator();
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                m_it.primitive_iterator = primitive_iterator_t();
+                break;
+            }
+        }
+    }
+
+    /*!
+    @note The conventional copy constructor and copy assignment are implicitly
+          defined. Combined with the following converting constructor and
+          assignment, they support: (1) copy from iterator to iterator, (2)
+          copy from const iterator to const iterator, and (3) conversion from
+          iterator to const iterator. However conversion from const iterator
+          to iterator is not defined.
+    */
+
+    /*!
+    @brief const copy constructor
+    @param[in] other const iterator to copy from
+    @note This copy constructor had to be defined explicitly to circumvent a bug
+          occurring on msvc v19.0 compiler (VS 2015) debug build. For more
+          information refer to: https://github.com/nlohmann/json/issues/1608
+    */
+    iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
+        : m_object(other.m_object), m_it(other.m_it)
+    {}
+
+    /*!
+    @brief converting assignment
+    @param[in] other const iterator to copy from
+    @return const/non-const iterator
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
+    {
+        if (&other != this)
+        {
+            m_object = other.m_object;
+            m_it = other.m_it;
+        }
+        return *this;
+    }
+
+    /*!
+    @brief converting constructor
+    @param[in] other  non-const iterator to copy from
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
+        : m_object(other.m_object), m_it(other.m_it)
+    {}
+
+    /*!
+    @brief converting assignment
+    @param[in] other  non-const iterator to copy from
+    @return const/non-const iterator
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
+    {
+        m_object = other.m_object;
+        m_it = other.m_it;
+        return *this;
+    }
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /*!
+    @brief set the iterator to the first value
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    void set_begin() noexcept
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = m_object->m_value.object->begin();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = m_object->m_value.array->begin();
+                break;
+            }
+
+            case value_t::null:
+            {
+                // set to end so begin()==end() is true: null is empty
+                m_it.primitive_iterator.set_end();
+                break;
+            }
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                m_it.primitive_iterator.set_begin();
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief set the iterator past the last value
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    void set_end() noexcept
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = m_object->m_value.object->end();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = m_object->m_value.array->end();
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                m_it.primitive_iterator.set_end();
+                break;
+            }
+        }
+    }
+
+  public:
+    /*!
+    @brief return a reference to the value pointed to by the iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference operator*() const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
+                return m_it.object_iterator->second;
+            }
+
+            case value_t::array:
+            {
+                JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
+                return *m_it.array_iterator;
+            }
+
+            case value_t::null:
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
+                {
+                    return *m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+            }
+        }
+    }
+
+    /*!
+    @brief dereference the iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    pointer operator->() const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
+                return &(m_it.object_iterator->second);
+            }
+
+            case value_t::array:
+            {
+                JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
+                return &*m_it.array_iterator;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
+                {
+                    return m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+            }
+        }
+    }
+
+    /*!
+    @brief post-increment (it++)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl const operator++(int) // NOLINT(readability-const-return-type)
+    {
+        auto result = *this;
+        ++(*this);
+        return result;
+    }
+
+    /*!
+    @brief pre-increment (++it)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator++()
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                std::advance(m_it.object_iterator, 1);
+                break;
+            }
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, 1);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                ++m_it.primitive_iterator;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief post-decrement (it--)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl const operator--(int) // NOLINT(readability-const-return-type)
+    {
+        auto result = *this;
+        --(*this);
+        return result;
+    }
+
+    /*!
+    @brief pre-decrement (--it)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator--()
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                std::advance(m_it.object_iterator, -1);
+                break;
+            }
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, -1);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                --m_it.primitive_iterator;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief comparison: equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
+    bool operator==(const IterImpl& other) const
+    {
+        // if objects are not the same, the comparison is undefined
+        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
+        }
+
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                return (m_it.object_iterator == other.m_it.object_iterator);
+
+            case value_t::array:
+                return (m_it.array_iterator == other.m_it.array_iterator);
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                return (m_it.primitive_iterator == other.m_it.primitive_iterator);
+        }
+    }
+
+    /*!
+    @brief comparison: not equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
+    bool operator!=(const IterImpl& other) const
+    {
+        return !operator==(other);
+    }
+
+    /*!
+    @brief comparison: smaller
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator<(const iter_impl& other) const
+    {
+        // if objects are not the same, the comparison is undefined
+        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
+        }
+
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
+
+            case value_t::array:
+                return (m_it.array_iterator < other.m_it.array_iterator);
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                return (m_it.primitive_iterator < other.m_it.primitive_iterator);
+        }
+    }
+
+    /*!
+    @brief comparison: less than or equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator<=(const iter_impl& other) const
+    {
+        return !other.operator < (*this);
+    }
+
+    /*!
+    @brief comparison: greater than
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator>(const iter_impl& other) const
+    {
+        return !operator<=(other);
+    }
+
+    /*!
+    @brief comparison: greater than or equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator>=(const iter_impl& other) const
+    {
+        return !operator<(other);
+    }
+
+    /*!
+    @brief add to iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator+=(difference_type i)
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, i);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                m_it.primitive_iterator += i;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief subtract from iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator-=(difference_type i)
+    {
+        return operator+=(-i);
+    }
+
+    /*!
+    @brief add to iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl operator+(difference_type i) const
+    {
+        auto result = *this;
+        result += i;
+        return result;
+    }
+
+    /*!
+    @brief addition of distance and iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    friend iter_impl operator+(difference_type i, const iter_impl& it)
+    {
+        auto result = it;
+        result += i;
+        return result;
+    }
+
+    /*!
+    @brief subtract from iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl operator-(difference_type i) const
+    {
+        auto result = *this;
+        result -= i;
+        return result;
+    }
+
+    /*!
+    @brief return difference
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    difference_type operator-(const iter_impl& other) const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
+
+            case value_t::array:
+                return m_it.array_iterator - other.m_it.array_iterator;
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                return m_it.primitive_iterator - other.m_it.primitive_iterator;
+        }
+    }
+
+    /*!
+    @brief access to successor
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference operator[](difference_type n) const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
+
+            case value_t::array:
+                return *std::next(m_it.array_iterator, n);
+
+            case value_t::null:
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
+                {
+                    return *m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+            }
+        }
+    }
+
+    /*!
+    @brief return the key of an object iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    const typename object_t::key_type& key() const
+    {
+        JSON_ASSERT(m_object != nullptr);
+
+        if (JSON_HEDLEY_LIKELY(m_object->is_object()))
+        {
+            return m_it.object_iterator->first;
+        }
+
+        JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
+    }
+
+    /*!
+    @brief return the value of an iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference value() const
+    {
+        return operator*();
+    }
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /// associated JSON instance
+    pointer m_object = nullptr;
+    /// the actual iterator of the associated instance
+    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+
+// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
+
+
+#include <cstddef> // ptrdiff_t
+#include <iterator> // reverse_iterator
+#include <utility> // declval
+
+namespace nlohmann
+{
+namespace detail
+{
+//////////////////////
+// reverse_iterator //
+//////////////////////
+
+/*!
+@brief a template for a reverse iterator class
+
+@tparam Base the base iterator type to reverse. Valid types are @ref
+iterator (to create @ref reverse_iterator) and @ref const_iterator (to
+create @ref const_reverse_iterator).
+
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
+  The iterator that can be moved can be moved in both directions (i.e.
+  incremented and decremented).
+- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
+  It is possible to write to the pointed-to element (only if @a Base is
+  @ref iterator).
+
+@since version 1.0.0
+*/
+template<typename Base>
+class json_reverse_iterator : public std::reverse_iterator<Base>
+{
+  public:
+    using difference_type = std::ptrdiff_t;
+    /// shortcut to the reverse iterator adapter
+    using base_iterator = std::reverse_iterator<Base>;
+    /// the reference type for the pointed-to element
+    using reference = typename Base::reference;
+
+    /// create reverse iterator from iterator
+    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
+        : base_iterator(it) {}
+
+    /// create reverse iterator from base class
+    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
+
+    /// post-increment (it++)
+    json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type)
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
+    }
+
+    /// pre-increment (++it)
+    json_reverse_iterator& operator++()
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
+    }
+
+    /// post-decrement (it--)
+    json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type)
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
+    }
+
+    /// pre-decrement (--it)
+    json_reverse_iterator& operator--()
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
+    }
+
+    /// add to iterator
+    json_reverse_iterator& operator+=(difference_type i)
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
+    }
+
+    /// add to iterator
+    json_reverse_iterator operator+(difference_type i) const
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
+    }
+
+    /// subtract from iterator
+    json_reverse_iterator operator-(difference_type i) const
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
+    }
+
+    /// return difference
+    difference_type operator-(const json_reverse_iterator& other) const
+    {
+        return base_iterator(*this) - base_iterator(other);
+    }
+
+    /// access to successor
+    reference operator[](difference_type n) const
+    {
+        return *(this->operator+(n));
+    }
+
+    /// return the key of an object iterator
+    auto key() const -> decltype(std::declval<Base>().key())
+    {
+        auto it = --this->base();
+        return it.key();
+    }
+
+    /// return the value of an iterator
+    reference value() const
+    {
+        auto it = --this->base();
+        return it.operator * ();
+    }
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+// #include <nlohmann/detail/json_pointer.hpp>
+
+
+#include <algorithm> // all_of
+#include <cctype> // isdigit
+#include <limits> // max
+#include <numeric> // accumulate
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/string_escape.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+template<typename BasicJsonType>
+class json_pointer
+{
+    // allow basic_json to access private members
+    NLOHMANN_BASIC_JSON_TPL_DECLARATION
+    friend class basic_json;
+
+  public:
+    /*!
+    @brief create JSON pointer
+
+    Create a JSON pointer according to the syntax described in
+    [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
+
+    @param[in] s  string representing the JSON pointer; if omitted, the empty
+                  string is assumed which references the whole JSON value
+
+    @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
+                           not begin with a slash (`/`); see example below
+
+    @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
+    not followed by `0` (representing `~`) or `1` (representing `/`); see
+    example below
+
+    @liveexample{The example shows the construction several valid JSON pointers
+    as well as the exceptional behavior.,json_pointer}
+
+    @since version 2.0.0
+    */
+    explicit json_pointer(const std::string& s = "")
+        : reference_tokens(split(s))
+    {}
+
+    /*!
+    @brief return a string representation of the JSON pointer
+
+    @invariant For each JSON pointer `ptr`, it holds:
+    @code {.cpp}
+    ptr == json_pointer(ptr.to_string());
+    @endcode
+
+    @return a string representation of the JSON pointer
+
+    @liveexample{The example shows the result of `to_string`.,json_pointer__to_string}
+
+    @since version 2.0.0
+    */
+    std::string to_string() const
+    {
+        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
+                               std::string{},
+                               [](const std::string & a, const std::string & b)
+        {
+            return a + "/" + detail::escape(b);
+        });
+    }
+
+    /// @copydoc to_string()
+    operator std::string() const
+    {
+        return to_string();
+    }
+
+    /*!
+    @brief append another JSON pointer at the end of this JSON pointer
+
+    @param[in] ptr  JSON pointer to append
+    @return JSON pointer with @a ptr appended
+
+    @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+    @complexity Linear in the length of @a ptr.
+
+    @sa see @ref operator/=(std::string) to append a reference token
+    @sa see @ref operator/=(std::size_t) to append an array index
+    @sa see @ref operator/(const json_pointer&, const json_pointer&) for a binary operator
+
+    @since version 3.6.0
+    */
+    json_pointer& operator/=(const json_pointer& ptr)
+    {
+        reference_tokens.insert(reference_tokens.end(),
+                                ptr.reference_tokens.begin(),
+                                ptr.reference_tokens.end());
+        return *this;
+    }
+
+    /*!
+    @brief append an unescaped reference token at the end of this JSON pointer
+
+    @param[in] token  reference token to append
+    @return JSON pointer with @a token appended without escaping @a token
+
+    @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+    @complexity Amortized constant.
+
+    @sa see @ref operator/=(const json_pointer&) to append a JSON pointer
+    @sa see @ref operator/=(std::size_t) to append an array index
+    @sa see @ref operator/(const json_pointer&, std::size_t) for a binary operator
+
+    @since version 3.6.0
+    */
+    json_pointer& operator/=(std::string token)
+    {
+        push_back(std::move(token));
+        return *this;
+    }
+
+    /*!
+    @brief append an array index at the end of this JSON pointer
+
+    @param[in] array_idx  array index to append
+    @return JSON pointer with @a array_idx appended
+
+    @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+    @complexity Amortized constant.
+
+    @sa see @ref operator/=(const json_pointer&) to append a JSON pointer
+    @sa see @ref operator/=(std::string) to append a reference token
+    @sa see @ref operator/(const json_pointer&, std::string) for a binary operator
+
+    @since version 3.6.0
+    */
+    json_pointer& operator/=(std::size_t array_idx)
+    {
+        return *this /= std::to_string(array_idx);
+    }
+
+    /*!
+    @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
+
+    @param[in] lhs  JSON pointer
+    @param[in] rhs  JSON pointer
+    @return a new JSON pointer with @a rhs appended to @a lhs
+
+    @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+    @complexity Linear in the length of @a lhs and @a rhs.
+
+    @sa see @ref operator/=(const json_pointer&) to append a JSON pointer
+
+    @since version 3.6.0
+    */
+    friend json_pointer operator/(const json_pointer& lhs,
+                                  const json_pointer& rhs)
+    {
+        return json_pointer(lhs) /= rhs;
+    }
+
+    /*!
+    @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
+
+    @param[in] ptr  JSON pointer
+    @param[in] token  reference token
+    @return a new JSON pointer with unescaped @a token appended to @a ptr
+
+    @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+    @complexity Linear in the length of @a ptr.
+
+    @sa see @ref operator/=(std::string) to append a reference token
+
+    @since version 3.6.0
+    */
+    friend json_pointer operator/(const json_pointer& ptr, std::string token) // NOLINT(performance-unnecessary-value-param)
+    {
+        return json_pointer(ptr) /= std::move(token);
+    }
+
+    /*!
+    @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
+
+    @param[in] ptr  JSON pointer
+    @param[in] array_idx  array index
+    @return a new JSON pointer with @a array_idx appended to @a ptr
+
+    @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+    @complexity Linear in the length of @a ptr.
+
+    @sa see @ref operator/=(std::size_t) to append an array index
+
+    @since version 3.6.0
+    */
+    friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx)
+    {
+        return json_pointer(ptr) /= array_idx;
+    }
+
+    /*!
+    @brief returns the parent of this JSON pointer
+
+    @return parent of this JSON pointer; in case this JSON pointer is the root,
+            the root itself is returned
+
+    @complexity Linear in the length of the JSON pointer.
+
+    @liveexample{The example shows the result of `parent_pointer` for different
+    JSON Pointers.,json_pointer__parent_pointer}
+
+    @since version 3.6.0
+    */
+    json_pointer parent_pointer() const
+    {
+        if (empty())
+        {
+            return *this;
+        }
+
+        json_pointer res = *this;
+        res.pop_back();
+        return res;
+    }
+
+    /*!
+    @brief remove last reference token
+
+    @pre not `empty()`
+
+    @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}
+
+    @complexity Constant.
+
+    @throw out_of_range.405 if JSON pointer has no parent
+
+    @since version 3.6.0
+    */
+    void pop_back()
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+        }
+
+        reference_tokens.pop_back();
+    }
+
+    /*!
+    @brief return last reference token
+
+    @pre not `empty()`
+    @return last reference token
+
+    @liveexample{The example shows the usage of `back`.,json_pointer__back}
+
+    @complexity Constant.
+
+    @throw out_of_range.405 if JSON pointer has no parent
+
+    @since version 3.6.0
+    */
+    const std::string& back() const
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+        }
+
+        return reference_tokens.back();
+    }
+
+    /*!
+    @brief append an unescaped token at the end of the reference pointer
+
+    @param[in] token  token to add
+
+    @complexity Amortized constant.
+
+    @liveexample{The example shows the result of `push_back` for different
+    JSON Pointers.,json_pointer__push_back}
+
+    @since version 3.6.0
+    */
+    void push_back(const std::string& token)
+    {
+        reference_tokens.push_back(token);
+    }
+
+    /// @copydoc push_back(const std::string&)
+    void push_back(std::string&& token)
+    {
+        reference_tokens.push_back(std::move(token));
+    }
+
+    /*!
+    @brief return whether pointer points to the root document
+
+    @return true iff the JSON pointer points to the root document
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example shows the result of `empty` for different JSON
+    Pointers.,json_pointer__empty}
+
+    @since version 3.6.0
+    */
+    bool empty() const noexcept
+    {
+        return reference_tokens.empty();
+    }
+
+  private:
+    /*!
+    @param[in] s  reference token to be converted into an array index
+
+    @return integer representation of @a s
+
+    @throw parse_error.106  if an array index begins with '0'
+    @throw parse_error.109  if an array index begins not with a digit
+    @throw out_of_range.404 if string @a s could not be converted to an integer
+    @throw out_of_range.410 if an array index exceeds size_type
+    */
+    static typename BasicJsonType::size_type array_index(const std::string& s)
+    {
+        using size_type = typename BasicJsonType::size_type;
+
+        // error condition (cf. RFC 6901, Sect. 4)
+        if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
+        {
+            JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
+        }
+
+        // error condition (cf. RFC 6901, Sect. 4)
+        if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
+        {
+            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
+        }
+
+        std::size_t processed_chars = 0;
+        unsigned long long res = 0;  // NOLINT(runtime/int)
+        JSON_TRY
+        {
+            res = std::stoull(s, &processed_chars);
+        }
+        JSON_CATCH(std::out_of_range&)
+        {
+            JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
+        }
+
+        // check if the string was completely read
+        if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
+        {
+            JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
+        }
+
+        // only triggered on special platforms (like 32bit), see also
+        // https://github.com/nlohmann/json/pull/2203
+        if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int)
+        {
+            JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
+        }
+
+        return static_cast<size_type>(res);
+    }
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    json_pointer top() const
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+        }
+
+        json_pointer result = *this;
+        result.reference_tokens = {reference_tokens[0]};
+        return result;
+    }
+
+  private:
+    /*!
+    @brief create and return a reference to the pointed to value
+
+    @complexity Linear in the number of reference tokens.
+
+    @throw parse_error.109 if array index is not a number
+    @throw type_error.313 if value cannot be unflattened
+    */
+    BasicJsonType& get_and_create(BasicJsonType& j) const
+    {
+        auto* result = &j;
+
+        // in case no reference tokens exist, return a reference to the JSON value
+        // j which will be overwritten by a primitive value
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (result->type())
+            {
+                case detail::value_t::null:
+                {
+                    if (reference_token == "0")
+                    {
+                        // start a new array if reference token is 0
+                        result = &result->operator[](0);
+                    }
+                    else
+                    {
+                        // start a new object otherwise
+                        result = &result->operator[](reference_token);
+                    }
+                    break;
+                }
+
+                case detail::value_t::object:
+                {
+                    // create an entry in the object
+                    result = &result->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    // create an entry in the array
+                    result = &result->operator[](array_index(reference_token));
+                    break;
+                }
+
+                /*
+                The following code is only reached if there exists a reference
+                token _and_ the current value is primitive. In this case, we have
+                an error situation, because primitive values may only occur as
+                single value; that is, with an empty list of reference tokens.
+                */
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
+            }
+        }
+
+        return *result;
+    }
+
+    /*!
+    @brief return a reference to the pointed to value
+
+    @note This version does not throw if a value is not present, but tries to
+          create nested values instead. For instance, calling this function
+          with pointer `"/this/that"` on a null value is equivalent to calling
+          `operator[]("this").operator[]("that")` on that value, effectively
+          changing the null value to an object.
+
+    @param[in] ptr  a JSON value
+
+    @return reference to the JSON value pointed to by the JSON pointer
+
+    @complexity Linear in the length of the JSON pointer.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            // convert null values to arrays or objects before continuing
+            if (ptr->is_null())
+            {
+                // check if reference token is a number
+                const bool nums =
+                    std::all_of(reference_token.begin(), reference_token.end(),
+                                [](const unsigned char x)
+                {
+                    return std::isdigit(x);
+                });
+
+                // change value to array for numbers or "-" or to object otherwise
+                *ptr = (nums || reference_token == "-")
+                       ? detail::value_t::array
+                       : detail::value_t::object;
+            }
+
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // use unchecked object access
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (reference_token == "-")
+                    {
+                        // explicitly treat "-" as index beyond the end
+                        ptr = &ptr->operator[](ptr->m_value.array->size());
+                    }
+                    else
+                    {
+                        // convert array index to number; unchecked access
+                        ptr = &ptr->operator[](array_index(reference_token));
+                    }
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    BasicJsonType& get_checked(BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // note: at performs range check
+                    ptr = &ptr->at(reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        JSON_THROW(detail::out_of_range::create(402,
+                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+                                                                ") is out of range", *ptr));
+                    }
+
+                    // note: at performs range check
+                    ptr = &ptr->at(array_index(reference_token));
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @brief return a const reference to the pointed to value
+
+    @param[in] ptr  a JSON value
+
+    @return const reference to the JSON value pointed to by the JSON
+    pointer
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // use unchecked object access
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" cannot be used for const access
+                        JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
+                    }
+
+                    // use unchecked array access
+                    ptr = &ptr->operator[](array_index(reference_token));
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // note: at performs range check
+                    ptr = &ptr->at(reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        JSON_THROW(detail::out_of_range::create(402,
+                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+                                                                ") is out of range", *ptr));
+                    }
+
+                    // note: at performs range check
+                    ptr = &ptr->at(array_index(reference_token));
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    */
+    bool contains(const BasicJsonType* ptr) const
+    {
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    if (!ptr->contains(reference_token))
+                    {
+                        // we did not find the key in the object
+                        return false;
+                    }
+
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
+                    {
+                        // invalid char
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
+                        {
+                            // first char should be between '1' and '9'
+                            return false;
+                        }
+                        for (std::size_t i = 1; i < reference_token.size(); i++)
+                        {
+                            if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
+                            {
+                                // other char should be between '0' and '9'
+                                return false;
+                            }
+                        }
+                    }
+
+                    const auto idx = array_index(reference_token);
+                    if (idx >= ptr->size())
+                    {
+                        // index out of range
+                        return false;
+                    }
+
+                    ptr = &ptr->operator[](idx);
+                    break;
+                }
+
+                case detail::value_t::null:
+                case detail::value_t::string:
+                case detail::value_t::boolean:
+                case detail::value_t::number_integer:
+                case detail::value_t::number_unsigned:
+                case detail::value_t::number_float:
+                case detail::value_t::binary:
+                case detail::value_t::discarded:
+                default:
+                {
+                    // we do not expect primitive values if there is still a
+                    // reference token to process
+                    return false;
+                }
+            }
+        }
+
+        // no reference token left means we found a primitive value
+        return true;
+    }
+
+    /*!
+    @brief split the string input to reference tokens
+
+    @note This function is only called by the json_pointer constructor.
+          All exceptions below are documented there.
+
+    @throw parse_error.107  if the pointer is not empty or begins with '/'
+    @throw parse_error.108  if character '~' is not followed by '0' or '1'
+    */
+    static std::vector<std::string> split(const std::string& reference_string)
+    {
+        std::vector<std::string> result;
+
+        // special case: empty reference string -> no reference tokens
+        if (reference_string.empty())
+        {
+            return result;
+        }
+
+        // check if nonempty reference string begins with slash
+        if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
+        {
+            JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
+        }
+
+        // extract the reference tokens:
+        // - slash: position of the last read slash (or end of string)
+        // - start: position after the previous slash
+        for (
+            // search for the first slash after the first character
+            std::size_t slash = reference_string.find_first_of('/', 1),
+            // set the beginning of the first reference token
+            start = 1;
+            // we can stop if start == 0 (if slash == std::string::npos)
+            start != 0;
+            // set the beginning of the next reference token
+            // (will eventually be 0 if slash == std::string::npos)
+            start = (slash == std::string::npos) ? 0 : slash + 1,
+            // find next slash
+            slash = reference_string.find_first_of('/', start))
+        {
+            // use the text between the beginning of the reference token
+            // (start) and the last slash (slash).
+            auto reference_token = reference_string.substr(start, slash - start);
+
+            // check reference tokens are properly escaped
+            for (std::size_t pos = reference_token.find_first_of('~');
+                    pos != std::string::npos;
+                    pos = reference_token.find_first_of('~', pos + 1))
+            {
+                JSON_ASSERT(reference_token[pos] == '~');
+
+                // ~ must be followed by 0 or 1
+                if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
+                                         (reference_token[pos + 1] != '0' &&
+                                          reference_token[pos + 1] != '1')))
+                {
+                    JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
+                }
+            }
+
+            // finally, store the reference token
+            detail::unescape(reference_token);
+            result.push_back(reference_token);
+        }
+
+        return result;
+    }
+
+  private:
+    /*!
+    @param[in] reference_string  the reference string to the current value
+    @param[in] value             the value to consider
+    @param[in,out] result        the result object to insert values to
+
+    @note Empty objects or arrays are flattened to `null`.
+    */
+    static void flatten(const std::string& reference_string,
+                        const BasicJsonType& value,
+                        BasicJsonType& result)
+    {
+        switch (value.type())
+        {
+            case detail::value_t::array:
+            {
+                if (value.m_value.array->empty())
+                {
+                    // flatten empty array as null
+                    result[reference_string] = nullptr;
+                }
+                else
+                {
+                    // iterate array and use index as reference string
+                    for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
+                    {
+                        flatten(reference_string + "/" + std::to_string(i),
+                                value.m_value.array->operator[](i), result);
+                    }
+                }
+                break;
+            }
+
+            case detail::value_t::object:
+            {
+                if (value.m_value.object->empty())
+                {
+                    // flatten empty object as null
+                    result[reference_string] = nullptr;
+                }
+                else
+                {
+                    // iterate object and use keys as reference string
+                    for (const auto& element : *value.m_value.object)
+                    {
+                        flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
+                    }
+                }
+                break;
+            }
+
+            case detail::value_t::null:
+            case detail::value_t::string:
+            case detail::value_t::boolean:
+            case detail::value_t::number_integer:
+            case detail::value_t::number_unsigned:
+            case detail::value_t::number_float:
+            case detail::value_t::binary:
+            case detail::value_t::discarded:
+            default:
+            {
+                // add primitive value with its reference string
+                result[reference_string] = value;
+                break;
+            }
+        }
+    }
+
+    /*!
+    @param[in] value  flattened JSON
+
+    @return unflattened JSON
+
+    @throw parse_error.109 if array index is not a number
+    @throw type_error.314  if value is not an object
+    @throw type_error.315  if object values are not primitive
+    @throw type_error.313  if value cannot be unflattened
+    */
+    static BasicJsonType
+    unflatten(const BasicJsonType& value)
+    {
+        if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
+        {
+            JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
+        }
+
+        BasicJsonType result;
+
+        // iterate the JSON object values
+        for (const auto& element : *value.m_value.object)
+        {
+            if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
+            {
+                JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
+            }
+
+            // assign value to reference pointed to by JSON pointer; Note that if
+            // the JSON pointer is "" (i.e., points to the whole value), function
+            // get_and_create returns a reference to result itself. An assignment
+            // will then create a primitive value.
+            json_pointer(element.first).get_and_create(result) = element.second;
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief compares two JSON pointers for equality
+
+    @param[in] lhs  JSON pointer to compare
+    @param[in] rhs  JSON pointer to compare
+    @return whether @a lhs is equal to @a rhs
+
+    @complexity Linear in the length of the JSON pointer
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+    */
+    friend bool operator==(json_pointer const& lhs,
+                           json_pointer const& rhs) noexcept
+    {
+        return lhs.reference_tokens == rhs.reference_tokens;
+    }
+
+    /*!
+    @brief compares two JSON pointers for inequality
+
+    @param[in] lhs  JSON pointer to compare
+    @param[in] rhs  JSON pointer to compare
+    @return whether @a lhs is not equal @a rhs
+
+    @complexity Linear in the length of the JSON pointer
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+    */
+    friend bool operator!=(json_pointer const& lhs,
+                           json_pointer const& rhs) noexcept
+    {
+        return !(lhs == rhs);
+    }
+
+    /// the reference tokens
+    std::vector<std::string> reference_tokens;
+};
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/json_ref.hpp>
+
+
+#include <initializer_list>
+#include <utility>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename BasicJsonType>
+class json_ref
+{
+  public:
+    using value_type = BasicJsonType;
+
+    json_ref(value_type&& value)
+        : owned_value(std::move(value))
+    {}
+
+    json_ref(const value_type& value)
+        : value_ref(&value)
+    {}
+
+    json_ref(std::initializer_list<json_ref> init)
+        : owned_value(init)
+    {}
+
+    template <
+        class... Args,
+        enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
+    json_ref(Args && ... args)
+        : owned_value(std::forward<Args>(args)...)
+    {}
+
+    // class should be movable only
+    json_ref(json_ref&&) noexcept = default;
+    json_ref(const json_ref&) = delete;
+    json_ref& operator=(const json_ref&) = delete;
+    json_ref& operator=(json_ref&&) = delete;
+    ~json_ref() = default;
+
+    value_type moved_or_copied() const
+    {
+        if (value_ref == nullptr)
+        {
+            return std::move(owned_value);
+        }
+        return *value_ref;
+    }
+
+    value_type const& operator*() const
+    {
+        return value_ref ? *value_ref : owned_value;
+    }
+
+    value_type const* operator->() const
+    {
+        return &** this;
+    }
+
+  private:
+    mutable value_type owned_value = nullptr;
+    value_type const* value_ref = nullptr;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/string_escape.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/output/binary_writer.hpp>
+
+
+#include <algorithm> // reverse
+#include <array> // array
+#include <cmath> // isnan, isinf
+#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstring> // memcpy
+#include <limits> // numeric_limits
+#include <string> // string
+#include <utility> // move
+
+// #include <nlohmann/detail/input/binary_reader.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+
+#include <algorithm> // copy
+#include <cstddef> // size_t
+#include <iterator> // back_inserter
+#include <memory> // shared_ptr, make_shared
+#include <string> // basic_string
+#include <vector> // vector
+
+#ifndef JSON_NO_IO
+    #include <ios>      // streamsize
+    #include <ostream>  // basic_ostream
+#endif  // JSON_NO_IO
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/// abstract output adapter interface
+template<typename CharType> struct output_adapter_protocol
+{
+    virtual void write_character(CharType c) = 0;
+    virtual void write_characters(const CharType* s, std::size_t length) = 0;
+    virtual ~output_adapter_protocol() = default;
+
+    output_adapter_protocol() = default;
+    output_adapter_protocol(const output_adapter_protocol&) = default;
+    output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
+    output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
+    output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
+};
+
+/// a type to simplify interfaces
+template<typename CharType>
+using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
+
+/// output adapter for byte vectors
+template<typename CharType, typename AllocatorType = std::allocator<CharType>>
+class output_vector_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
+        : v(vec)
+    {}
+
+    void write_character(CharType c) override
+    {
+        v.push_back(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        std::copy(s, s + length, std::back_inserter(v));
+    }
+
+  private:
+    std::vector<CharType, AllocatorType>& v;
+};
+
+#ifndef JSON_NO_IO
+/// output adapter for output streams
+template<typename CharType>
+class output_stream_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
+        : stream(s)
+    {}
+
+    void write_character(CharType c) override
+    {
+        stream.put(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        stream.write(s, static_cast<std::streamsize>(length));
+    }
+
+  private:
+    std::basic_ostream<CharType>& stream;
+};
+#endif  // JSON_NO_IO
+
+/// output adapter for basic_string
+template<typename CharType, typename StringType = std::basic_string<CharType>>
+class output_string_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_string_adapter(StringType& s) noexcept
+        : str(s)
+    {}
+
+    void write_character(CharType c) override
+    {
+        str.push_back(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        str.append(s, length);
+    }
+
+  private:
+    StringType& str;
+};
+
+template<typename CharType, typename StringType = std::basic_string<CharType>>
+class output_adapter
+{
+  public:
+    template<typename AllocatorType = std::allocator<CharType>>
+    output_adapter(std::vector<CharType, AllocatorType>& vec)
+        : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
+
+#ifndef JSON_NO_IO
+    output_adapter(std::basic_ostream<CharType>& s)
+        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
+#endif  // JSON_NO_IO
+
+    output_adapter(StringType& s)
+        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
+
+    operator output_adapter_t<CharType>()
+    {
+        return oa;
+    }
+
+  private:
+    output_adapter_t<CharType> oa = nullptr;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////
+// binary writer //
+///////////////////
+
+/*!
+@brief serialization to CBOR and MessagePack values
+*/
+template<typename BasicJsonType, typename CharType>
+class binary_writer
+{
+    using string_t = typename BasicJsonType::string_t;
+    using binary_t = typename BasicJsonType::binary_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+
+  public:
+    /*!
+    @brief create a binary writer
+
+    @param[in] adapter  output adapter to write to
+    */
+    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
+    {
+        JSON_ASSERT(oa);
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    @pre       j.type() == value_t::object
+    */
+    void write_bson(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::object:
+            {
+                write_bson_object(*j.m_value.object);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::array:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));
+            }
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    */
+    void write_cbor(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                oa->write_character(to_char_type(0xF6));
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                oa->write_character(j.m_value.boolean
+                                    ? to_char_type(0xF5)
+                                    : to_char_type(0xF4));
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // CBOR does not differentiate between positive signed
+                    // integers and unsigned integers. Therefore, we used the
+                    // code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_integer <= 0x17)
+                    {
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x18));
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x19));
+                        write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x1A));
+                        write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                    }
+                    else
+                    {
+                        oa->write_character(to_char_type(0x1B));
+                        write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                    }
+                }
+                else
+                {
+                    // The conversions below encode the sign in the first
+                    // byte, and the value is converted to a positive number.
+                    const auto positive_number = -1 - j.m_value.number_integer;
+                    if (j.m_value.number_integer >= -24)
+                    {
+                        write_number(static_cast<std::uint8_t>(0x20 + positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x38));
+                        write_number(static_cast<std::uint8_t>(positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x39));
+                        write_number(static_cast<std::uint16_t>(positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x3A));
+                        write_number(static_cast<std::uint32_t>(positive_number));
+                    }
+                    else
+                    {
+                        oa->write_character(to_char_type(0x3B));
+                        write_number(static_cast<std::uint64_t>(positive_number));
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x18));
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x19));
+                    write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x1A));
+                    write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
+                }
+                else
+                {
+                    oa->write_character(to_char_type(0x1B));
+                    write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                if (std::isnan(j.m_value.number_float))
+                {
+                    // NaN is 0xf97e00 in CBOR
+                    oa->write_character(to_char_type(0xF9));
+                    oa->write_character(to_char_type(0x7E));
+                    oa->write_character(to_char_type(0x00));
+                }
+                else if (std::isinf(j.m_value.number_float))
+                {
+                    // Infinity is 0xf97c00, -Infinity is 0xf9fc00
+                    oa->write_character(to_char_type(0xf9));
+                    oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
+                    oa->write_character(to_char_type(0x00));
+                }
+                else
+                {
+                    write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
+                }
+                break;
+            }
+
+            case value_t::string:
+            {
+                // step 1: write control byte and the string length
+                const auto N = j.m_value.string->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0x60 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x78));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x79));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x7A));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x7B));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write the string
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                // step 1: write control byte and the array size
+                const auto N = j.m_value.array->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0x80 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x98));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x99));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x9A));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x9B));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_cbor(el);
+                }
+                break;
+            }
+
+            case value_t::binary:
+            {
+                if (j.m_value.binary->has_subtype())
+                {
+                    if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        write_number(static_cast<std::uint8_t>(0xd8));
+                        write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
+                    }
+                    else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        write_number(static_cast<std::uint8_t>(0xd9));
+                        write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
+                    }
+                    else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        write_number(static_cast<std::uint8_t>(0xda));
+                        write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
+                    }
+                    else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
+                    {
+                        write_number(static_cast<std::uint8_t>(0xdb));
+                        write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
+                    }
+                }
+
+                // step 1: write control byte and the binary array size
+                const auto N = j.m_value.binary->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0x40 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x58));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x59));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x5A));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x5B));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write each element
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+                    N);
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                // step 1: write control byte and the object size
+                const auto N = j.m_value.object->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0xA0 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xB8));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xB9));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xBA));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xBB));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_cbor(el.first);
+                    write_cbor(el.second);
+                }
+                break;
+            }
+
+            case value_t::discarded:
+            default:
+                break;
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    */
+    void write_msgpack(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::null: // nil
+            {
+                oa->write_character(to_char_type(0xC0));
+                break;
+            }
+
+            case value_t::boolean: // true and false
+            {
+                oa->write_character(j.m_value.boolean
+                                    ? to_char_type(0xC3)
+                                    : to_char_type(0xC2));
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // MessagePack does not differentiate between positive
+                    // signed integers and unsigned integers. Therefore, we used
+                    // the code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_unsigned < 128)
+                    {
+                        // positive fixnum
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        // uint 8
+                        oa->write_character(to_char_type(0xCC));
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        // uint 16
+                        oa->write_character(to_char_type(0xCD));
+                        write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        // uint 32
+                        oa->write_character(to_char_type(0xCE));
+                        write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+                    {
+                        // uint 64
+                        oa->write_character(to_char_type(0xCF));
+                        write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                    }
+                }
+                else
+                {
+                    if (j.m_value.number_integer >= -32)
+                    {
+                        // negative fixnum
+                        write_number(static_cast<std::int8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
+                             j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
+                    {
+                        // int 8
+                        oa->write_character(to_char_type(0xD0));
+                        write_number(static_cast<std::int8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
+                             j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
+                    {
+                        // int 16
+                        oa->write_character(to_char_type(0xD1));
+                        write_number(static_cast<std::int16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
+                             j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
+                    {
+                        // int 32
+                        oa->write_character(to_char_type(0xD2));
+                        write_number(static_cast<std::int32_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
+                             j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
+                    {
+                        // int 64
+                        oa->write_character(to_char_type(0xD3));
+                        write_number(static_cast<std::int64_t>(j.m_value.number_integer));
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned < 128)
+                {
+                    // positive fixnum
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    // uint 8
+                    oa->write_character(to_char_type(0xCC));
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // uint 16
+                    oa->write_character(to_char_type(0xCD));
+                    write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // uint 32
+                    oa->write_character(to_char_type(0xCE));
+                    write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    // uint 64
+                    oa->write_character(to_char_type(0xCF));
+                    write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
+                break;
+            }
+
+            case value_t::string:
+            {
+                // step 1: write control byte and the string length
+                const auto N = j.m_value.string->size();
+                if (N <= 31)
+                {
+                    // fixstr
+                    write_number(static_cast<std::uint8_t>(0xA0 | N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    // str 8
+                    oa->write_character(to_char_type(0xD9));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // str 16
+                    oa->write_character(to_char_type(0xDA));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // str 32
+                    oa->write_character(to_char_type(0xDB));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write the string
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                // step 1: write control byte and the array size
+                const auto N = j.m_value.array->size();
+                if (N <= 15)
+                {
+                    // fixarray
+                    write_number(static_cast<std::uint8_t>(0x90 | N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // array 16
+                    oa->write_character(to_char_type(0xDC));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // array 32
+                    oa->write_character(to_char_type(0xDD));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_msgpack(el);
+                }
+                break;
+            }
+
+            case value_t::binary:
+            {
+                // step 0: determine if the binary type has a set subtype to
+                // determine whether or not to use the ext or fixext types
+                const bool use_ext = j.m_value.binary->has_subtype();
+
+                // step 1: write control byte and the byte string length
+                const auto N = j.m_value.binary->size();
+                if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    std::uint8_t output_type{};
+                    bool fixed = true;
+                    if (use_ext)
+                    {
+                        switch (N)
+                        {
+                            case 1:
+                                output_type = 0xD4; // fixext 1
+                                break;
+                            case 2:
+                                output_type = 0xD5; // fixext 2
+                                break;
+                            case 4:
+                                output_type = 0xD6; // fixext 4
+                                break;
+                            case 8:
+                                output_type = 0xD7; // fixext 8
+                                break;
+                            case 16:
+                                output_type = 0xD8; // fixext 16
+                                break;
+                            default:
+                                output_type = 0xC7; // ext 8
+                                fixed = false;
+                                break;
+                        }
+
+                    }
+                    else
+                    {
+                        output_type = 0xC4; // bin 8
+                        fixed = false;
+                    }
+
+                    oa->write_character(to_char_type(output_type));
+                    if (!fixed)
+                    {
+                        write_number(static_cast<std::uint8_t>(N));
+                    }
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    std::uint8_t output_type = use_ext
+                                               ? 0xC8 // ext 16
+                                               : 0xC5; // bin 16
+
+                    oa->write_character(to_char_type(output_type));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    std::uint8_t output_type = use_ext
+                                               ? 0xC9 // ext 32
+                                               : 0xC6; // bin 32
+
+                    oa->write_character(to_char_type(output_type));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 1.5: if this is an ext type, write the subtype
+                if (use_ext)
+                {
+                    write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
+                }
+
+                // step 2: write the byte string
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+                    N);
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                // step 1: write control byte and the object size
+                const auto N = j.m_value.object->size();
+                if (N <= 15)
+                {
+                    // fixmap
+                    write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // map 16
+                    oa->write_character(to_char_type(0xDE));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // map 32
+                    oa->write_character(to_char_type(0xDF));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_msgpack(el.first);
+                    write_msgpack(el.second);
+                }
+                break;
+            }
+
+            case value_t::discarded:
+            default:
+                break;
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    @param[in] use_count   whether to use '#' prefixes (optimized format)
+    @param[in] use_type    whether to use '$' prefixes (optimized format)
+    @param[in] add_prefix  whether prefixes need to be used for this value
+    */
+    void write_ubjson(const BasicJsonType& j, const bool use_count,
+                      const bool use_type, const bool add_prefix = true)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('Z'));
+                }
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(j.m_value.boolean
+                                        ? to_char_type('T')
+                                        : to_char_type('F'));
+                }
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
+                break;
+            }
+
+            case value_t::string:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('S'));
+                }
+                write_number_with_ubjson_prefix(j.m_value.string->size(), true);
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('['));
+                }
+
+                bool prefix_required = true;
+                if (use_type && !j.m_value.array->empty())
+                {
+                    JSON_ASSERT(use_count);
+                    const CharType first_prefix = ubjson_prefix(j.front());
+                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
+                                                         [this, first_prefix](const BasicJsonType & v)
+                    {
+                        return ubjson_prefix(v) == first_prefix;
+                    });
+
+                    if (same_prefix)
+                    {
+                        prefix_required = false;
+                        oa->write_character(to_char_type('$'));
+                        oa->write_character(first_prefix);
+                    }
+                }
+
+                if (use_count)
+                {
+                    oa->write_character(to_char_type('#'));
+                    write_number_with_ubjson_prefix(j.m_value.array->size(), true);
+                }
+
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_ubjson(el, use_count, use_type, prefix_required);
+                }
+
+                if (!use_count)
+                {
+                    oa->write_character(to_char_type(']'));
+                }
+
+                break;
+            }
+
+            case value_t::binary:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('['));
+                }
+
+                if (use_type && !j.m_value.binary->empty())
+                {
+                    JSON_ASSERT(use_count);
+                    oa->write_character(to_char_type('$'));
+                    oa->write_character('U');
+                }
+
+                if (use_count)
+                {
+                    oa->write_character(to_char_type('#'));
+                    write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
+                }
+
+                if (use_type)
+                {
+                    oa->write_characters(
+                        reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+                        j.m_value.binary->size());
+                }
+                else
+                {
+                    for (size_t i = 0; i < j.m_value.binary->size(); ++i)
+                    {
+                        oa->write_character(to_char_type('U'));
+                        oa->write_character(j.m_value.binary->data()[i]);
+                    }
+                }
+
+                if (!use_count)
+                {
+                    oa->write_character(to_char_type(']'));
+                }
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('{'));
+                }
+
+                bool prefix_required = true;
+                if (use_type && !j.m_value.object->empty())
+                {
+                    JSON_ASSERT(use_count);
+                    const CharType first_prefix = ubjson_prefix(j.front());
+                    const bool same_prefix = std::all_of(j.begin(), j.end(),
+                                                         [this, first_prefix](const BasicJsonType & v)
+                    {
+                        return ubjson_prefix(v) == first_prefix;
+                    });
+
+                    if (same_prefix)
+                    {
+                        prefix_required = false;
+                        oa->write_character(to_char_type('$'));
+                        oa->write_character(first_prefix);
+                    }
+                }
+
+                if (use_count)
+                {
+                    oa->write_character(to_char_type('#'));
+                    write_number_with_ubjson_prefix(j.m_value.object->size(), true);
+                }
+
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_number_with_ubjson_prefix(el.first.size(), true);
+                    oa->write_characters(
+                        reinterpret_cast<const CharType*>(el.first.c_str()),
+                        el.first.size());
+                    write_ubjson(el.second, use_count, use_type, prefix_required);
+                }
+
+                if (!use_count)
+                {
+                    oa->write_character(to_char_type('}'));
+                }
+
+                break;
+            }
+
+            case value_t::discarded:
+            default:
+                break;
+        }
+    }
+
+  private:
+    //////////
+    // BSON //
+    //////////
+
+    /*!
+    @return The size of a BSON document entry header, including the id marker
+            and the entry name size (and its null-terminator).
+    */
+    static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
+    {
+        const auto it = name.find(static_cast<typename string_t::value_type>(0));
+        if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
+        {
+            JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
+            static_cast<void>(j);
+        }
+
+        return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
+    }
+
+    /*!
+    @brief Writes the given @a element_type and @a name to the output adapter
+    */
+    void write_bson_entry_header(const string_t& name,
+                                 const std::uint8_t element_type)
+    {
+        oa->write_character(to_char_type(element_type)); // boolean
+        oa->write_characters(
+            reinterpret_cast<const CharType*>(name.c_str()),
+            name.size() + 1u);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and boolean value @a value
+    */
+    void write_bson_boolean(const string_t& name,
+                            const bool value)
+    {
+        write_bson_entry_header(name, 0x08);
+        oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and double value @a value
+    */
+    void write_bson_double(const string_t& name,
+                           const double value)
+    {
+        write_bson_entry_header(name, 0x01);
+        write_number<double, true>(value);
+    }
+
+    /*!
+    @return The size of the BSON-encoded string in @a value
+    */
+    static std::size_t calc_bson_string_size(const string_t& value)
+    {
+        return sizeof(std::int32_t) + value.size() + 1ul;
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and string value @a value
+    */
+    void write_bson_string(const string_t& name,
+                           const string_t& value)
+    {
+        write_bson_entry_header(name, 0x02);
+
+        write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
+        oa->write_characters(
+            reinterpret_cast<const CharType*>(value.c_str()),
+            value.size() + 1);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and null value
+    */
+    void write_bson_null(const string_t& name)
+    {
+        write_bson_entry_header(name, 0x0A);
+    }
+
+    /*!
+    @return The size of the BSON-encoded integer @a value
+    */
+    static std::size_t calc_bson_integer_size(const std::int64_t value)
+    {
+        return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
+               ? sizeof(std::int32_t)
+               : sizeof(std::int64_t);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and integer @a value
+    */
+    void write_bson_integer(const string_t& name,
+                            const std::int64_t value)
+    {
+        if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
+        {
+            write_bson_entry_header(name, 0x10); // int32
+            write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
+        }
+        else
+        {
+            write_bson_entry_header(name, 0x12); // int64
+            write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
+        }
+    }
+
+    /*!
+    @return The size of the BSON-encoded unsigned integer in @a j
+    */
+    static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
+    {
+        return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+               ? sizeof(std::int32_t)
+               : sizeof(std::int64_t);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and unsigned @a value
+    */
+    void write_bson_unsigned(const string_t& name,
+                             const BasicJsonType& j)
+    {
+        if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+        {
+            write_bson_entry_header(name, 0x10 /* int32 */);
+            write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
+        }
+        else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+        {
+            write_bson_entry_header(name, 0x12 /* int64 */);
+            write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
+        }
+        else
+        {
+            JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
+        }
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and object @a value
+    */
+    void write_bson_object_entry(const string_t& name,
+                                 const typename BasicJsonType::object_t& value)
+    {
+        write_bson_entry_header(name, 0x03); // object
+        write_bson_object(value);
+    }
+
+    /*!
+    @return The size of the BSON-encoded array @a value
+    */
+    static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
+    {
+        std::size_t array_index = 0ul;
+
+        const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
+        {
+            return result + calc_bson_element_size(std::to_string(array_index++), el);
+        });
+
+        return sizeof(std::int32_t) + embedded_document_size + 1ul;
+    }
+
+    /*!
+    @return The size of the BSON-encoded binary array @a value
+    */
+    static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
+    {
+        return sizeof(std::int32_t) + value.size() + 1ul;
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and array @a value
+    */
+    void write_bson_array(const string_t& name,
+                          const typename BasicJsonType::array_t& value)
+    {
+        write_bson_entry_header(name, 0x04); // array
+        write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
+
+        std::size_t array_index = 0ul;
+
+        for (const auto& el : value)
+        {
+            write_bson_element(std::to_string(array_index++), el);
+        }
+
+        oa->write_character(to_char_type(0x00));
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and binary value @a value
+    */
+    void write_bson_binary(const string_t& name,
+                           const binary_t& value)
+    {
+        write_bson_entry_header(name, 0x05);
+
+        write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
+        write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : std::uint8_t(0x00));
+
+        oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
+    }
+
+    /*!
+    @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
+    @return The calculated size for the BSON document entry for @a j with the given @a name.
+    */
+    static std::size_t calc_bson_element_size(const string_t& name,
+            const BasicJsonType& j)
+    {
+        const auto header_size = calc_bson_entry_header_size(name, j);
+        switch (j.type())
+        {
+            case value_t::object:
+                return header_size + calc_bson_object_size(*j.m_value.object);
+
+            case value_t::array:
+                return header_size + calc_bson_array_size(*j.m_value.array);
+
+            case value_t::binary:
+                return header_size + calc_bson_binary_size(*j.m_value.binary);
+
+            case value_t::boolean:
+                return header_size + 1ul;
+
+            case value_t::number_float:
+                return header_size + 8ul;
+
+            case value_t::number_integer:
+                return header_size + calc_bson_integer_size(j.m_value.number_integer);
+
+            case value_t::number_unsigned:
+                return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
+
+            case value_t::string:
+                return header_size + calc_bson_string_size(*j.m_value.string);
+
+            case value_t::null:
+                return header_size + 0ul;
+
+            // LCOV_EXCL_START
+            case value_t::discarded:
+            default:
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
+                return 0ul;
+                // LCOV_EXCL_STOP
+        }
+    }
+
+    /*!
+    @brief Serializes the JSON value @a j to BSON and associates it with the
+           key @a name.
+    @param name The name to associate with the JSON entity @a j within the
+                current BSON document
+    */
+    void write_bson_element(const string_t& name,
+                            const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::object:
+                return write_bson_object_entry(name, *j.m_value.object);
+
+            case value_t::array:
+                return write_bson_array(name, *j.m_value.array);
+
+            case value_t::binary:
+                return write_bson_binary(name, *j.m_value.binary);
+
+            case value_t::boolean:
+                return write_bson_boolean(name, j.m_value.boolean);
+
+            case value_t::number_float:
+                return write_bson_double(name, j.m_value.number_float);
+
+            case value_t::number_integer:
+                return write_bson_integer(name, j.m_value.number_integer);
+
+            case value_t::number_unsigned:
+                return write_bson_unsigned(name, j);
+
+            case value_t::string:
+                return write_bson_string(name, *j.m_value.string);
+
+            case value_t::null:
+                return write_bson_null(name);
+
+            // LCOV_EXCL_START
+            case value_t::discarded:
+            default:
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
+                return;
+                // LCOV_EXCL_STOP
+        }
+    }
+
+    /*!
+    @brief Calculates the size of the BSON serialization of the given
+           JSON-object @a j.
+    @param[in] value  JSON value to serialize
+    @pre       value.type() == value_t::object
+    */
+    static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
+    {
+        std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0),
+                                    [](size_t result, const typename BasicJsonType::object_t::value_type & el)
+        {
+            return result += calc_bson_element_size(el.first, el.second);
+        });
+
+        return sizeof(std::int32_t) + document_size + 1ul;
+    }
+
+    /*!
+    @param[in] value  JSON value to serialize
+    @pre       value.type() == value_t::object
+    */
+    void write_bson_object(const typename BasicJsonType::object_t& value)
+    {
+        write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
+
+        for (const auto& el : value)
+        {
+            write_bson_element(el.first, el.second);
+        }
+
+        oa->write_character(to_char_type(0x00));
+    }
+
+    //////////
+    // CBOR //
+    //////////
+
+    static constexpr CharType get_cbor_float_prefix(float /*unused*/)
+    {
+        return to_char_type(0xFA);  // Single-Precision Float
+    }
+
+    static constexpr CharType get_cbor_float_prefix(double /*unused*/)
+    {
+        return to_char_type(0xFB);  // Double-Precision Float
+    }
+
+    /////////////
+    // MsgPack //
+    /////////////
+
+    static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
+    {
+        return to_char_type(0xCA);  // float 32
+    }
+
+    static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
+    {
+        return to_char_type(0xCB);  // float 64
+    }
+
+    ////////////
+    // UBJSON //
+    ////////////
+
+    // UBJSON: write number (floating point)
+    template<typename NumberType, typename std::enable_if<
+                 std::is_floating_point<NumberType>::value, int>::type = 0>
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix)
+    {
+        if (add_prefix)
+        {
+            oa->write_character(get_ubjson_float_prefix(n));
+        }
+        write_number(n);
+    }
+
+    // UBJSON: write number (unsigned integer)
+    template<typename NumberType, typename std::enable_if<
+                 std::is_unsigned<NumberType>::value, int>::type = 0>
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix)
+    {
+        if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('i'));  // int8
+            }
+            write_number(static_cast<std::uint8_t>(n));
+        }
+        else if (n <= (std::numeric_limits<std::uint8_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('U'));  // uint8
+            }
+            write_number(static_cast<std::uint8_t>(n));
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('I'));  // int16
+            }
+            write_number(static_cast<std::int16_t>(n));
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('l'));  // int32
+            }
+            write_number(static_cast<std::int32_t>(n));
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('L'));  // int64
+            }
+            write_number(static_cast<std::int64_t>(n));
+        }
+        else
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('H'));  // high-precision number
+            }
+
+            const auto number = BasicJsonType(n).dump();
+            write_number_with_ubjson_prefix(number.size(), true);
+            for (std::size_t i = 0; i < number.size(); ++i)
+            {
+                oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
+            }
+        }
+    }
+
+    // UBJSON: write number (signed integer)
+    template < typename NumberType, typename std::enable_if <
+                   std::is_signed<NumberType>::value&&
+                   !std::is_floating_point<NumberType>::value, int >::type = 0 >
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix)
+    {
+        if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('i'));  // int8
+            }
+            write_number(static_cast<std::int8_t>(n));
+        }
+        else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('U'));  // uint8
+            }
+            write_number(static_cast<std::uint8_t>(n));
+        }
+        else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('I'));  // int16
+            }
+            write_number(static_cast<std::int16_t>(n));
+        }
+        else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('l'));  // int32
+            }
+            write_number(static_cast<std::int32_t>(n));
+        }
+        else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('L'));  // int64
+            }
+            write_number(static_cast<std::int64_t>(n));
+        }
+        // LCOV_EXCL_START
+        else
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('H'));  // high-precision number
+            }
+
+            const auto number = BasicJsonType(n).dump();
+            write_number_with_ubjson_prefix(number.size(), true);
+            for (std::size_t i = 0; i < number.size(); ++i)
+            {
+                oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
+            }
+        }
+        // LCOV_EXCL_STOP
+    }
+
+    /*!
+    @brief determine the type prefix of container values
+    */
+    CharType ubjson_prefix(const BasicJsonType& j) const noexcept
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+                return 'Z';
+
+            case value_t::boolean:
+                return j.m_value.boolean ? 'T' : 'F';
+
+            case value_t::number_integer:
+            {
+                if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
+                {
+                    return 'i';
+                }
+                if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    return 'U';
+                }
+                if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
+                {
+                    return 'I';
+                }
+                if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
+                {
+                    return 'l';
+                }
+                if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
+                {
+                    return 'L';
+                }
+                // anything else is treated as high-precision number
+                return 'H'; // LCOV_EXCL_LINE
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
+                {
+                    return 'i';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
+                {
+                    return 'U';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
+                {
+                    return 'I';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+                {
+                    return 'l';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+                {
+                    return 'L';
+                }
+                // anything else is treated as high-precision number
+                return 'H'; // LCOV_EXCL_LINE
+            }
+
+            case value_t::number_float:
+                return get_ubjson_float_prefix(j.m_value.number_float);
+
+            case value_t::string:
+                return 'S';
+
+            case value_t::array: // fallthrough
+            case value_t::binary:
+                return '[';
+
+            case value_t::object:
+                return '{';
+
+            case value_t::discarded:
+            default:  // discarded values
+                return 'N';
+        }
+    }
+
+    static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
+    {
+        return 'd';  // float 32
+    }
+
+    static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
+    {
+        return 'D';  // float 64
+    }
+
+    ///////////////////////
+    // Utility functions //
+    ///////////////////////
+
+    /*
+    @brief write a number to output input
+    @param[in] n number of type @a NumberType
+    @tparam NumberType the type of the number
+    @tparam OutputIsLittleEndian Set to true if output data is
+                                 required to be little endian
+
+    @note This function needs to respect the system's endianness, because bytes
+          in CBOR, MessagePack, and UBJSON are stored in network order (big
+          endian) and therefore need reordering on little endian systems.
+    */
+    template<typename NumberType, bool OutputIsLittleEndian = false>
+    void write_number(const NumberType n)
+    {
+        // step 1: write number to array of length NumberType
+        std::array<CharType, sizeof(NumberType)> vec{};
+        std::memcpy(vec.data(), &n, sizeof(NumberType));
+
+        // step 2: write array to output (with possible reordering)
+        if (is_little_endian != OutputIsLittleEndian)
+        {
+            // reverse byte order prior to conversion if necessary
+            std::reverse(vec.begin(), vec.end());
+        }
+
+        oa->write_characters(vec.data(), sizeof(NumberType));
+    }
+
+    void write_compact_float(const number_float_t n, detail::input_format_t format)
+    {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+        if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
+                static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
+                static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
+        {
+            oa->write_character(format == detail::input_format_t::cbor
+                                ? get_cbor_float_prefix(static_cast<float>(n))
+                                : get_msgpack_float_prefix(static_cast<float>(n)));
+            write_number(static_cast<float>(n));
+        }
+        else
+        {
+            oa->write_character(format == detail::input_format_t::cbor
+                                ? get_cbor_float_prefix(n)
+                                : get_msgpack_float_prefix(n));
+            write_number(n);
+        }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+    }
+
+  public:
+    // The following to_char_type functions are implement the conversion
+    // between uint8_t and CharType. In case CharType is not unsigned,
+    // such a conversion is required to allow values greater than 128.
+    // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
+    template < typename C = CharType,
+               enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
+    static constexpr CharType to_char_type(std::uint8_t x) noexcept
+    {
+        return *reinterpret_cast<char*>(&x);
+    }
+
+    template < typename C = CharType,
+               enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
+    static CharType to_char_type(std::uint8_t x) noexcept
+    {
+        static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
+        static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
+        CharType result;
+        std::memcpy(&result, &x, sizeof(x));
+        return result;
+    }
+
+    template<typename C = CharType,
+             enable_if_t<std::is_unsigned<C>::value>* = nullptr>
+    static constexpr CharType to_char_type(std::uint8_t x) noexcept
+    {
+        return x;
+    }
+
+    template < typename InputCharType, typename C = CharType,
+               enable_if_t <
+                   std::is_signed<C>::value &&
+                   std::is_signed<char>::value &&
+                   std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
+                   > * = nullptr >
+    static constexpr CharType to_char_type(InputCharType x) noexcept
+    {
+        return x;
+    }
+
+  private:
+    /// whether we can assume little endianness
+    const bool is_little_endian = little_endianness();
+
+    /// the output
+    output_adapter_t<CharType> oa = nullptr;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+// #include <nlohmann/detail/output/serializer.hpp>
+
+
+#include <algorithm> // reverse, remove, fill, find, none_of
+#include <array> // array
+#include <clocale> // localeconv, lconv
+#include <cmath> // labs, isfinite, isnan, signbit
+#include <cstddef> // size_t, ptrdiff_t
+#include <cstdint> // uint8_t
+#include <cstdio> // snprintf
+#include <limits> // numeric_limits
+#include <string> // string, char_traits
+#include <iomanip> // setfill, setw
+#include <sstream> // stringstream
+#include <type_traits> // is_same
+#include <utility> // move
+
+// #include <nlohmann/detail/conversions/to_chars.hpp>
+
+
+#include <array> // array
+#include <cmath>   // signbit, isfinite
+#include <cstdint> // intN_t, uintN_t
+#include <cstring> // memcpy, memmove
+#include <limits> // numeric_limits
+#include <type_traits> // conditional
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+/*!
+@brief implements the Grisu2 algorithm for binary to decimal floating-point
+conversion.
+
+This implementation is a slightly modified version of the reference
+implementation which may be obtained from
+http://florian.loitsch.com/publications (bench.tar.gz).
+
+The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
+
+For a detailed description of the algorithm see:
+
+[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
+    Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
+    Language Design and Implementation, PLDI 2010
+[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
+    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
+    Design and Implementation, PLDI 1996
+*/
+namespace dtoa_impl
+{
+
+template<typename Target, typename Source>
+Target reinterpret_bits(const Source source)
+{
+    static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
+
+    Target target;
+    std::memcpy(&target, &source, sizeof(Source));
+    return target;
+}
+
+struct diyfp // f * 2^e
+{
+    static constexpr int kPrecision = 64; // = q
+
+    std::uint64_t f = 0;
+    int e = 0;
+
+    constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
+
+    /*!
+    @brief returns x - y
+    @pre x.e == y.e and x.f >= y.f
+    */
+    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
+    {
+        JSON_ASSERT(x.e == y.e);
+        JSON_ASSERT(x.f >= y.f);
+
+        return {x.f - y.f, x.e};
+    }
+
+    /*!
+    @brief returns x * y
+    @note The result is rounded. (Only the upper q bits are returned.)
+    */
+    static diyfp mul(const diyfp& x, const diyfp& y) noexcept
+    {
+        static_assert(kPrecision == 64, "internal error");
+
+        // Computes:
+        //  f = round((x.f * y.f) / 2^q)
+        //  e = x.e + y.e + q
+
+        // Emulate the 64-bit * 64-bit multiplication:
+        //
+        // p = u * v
+        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
+        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
+        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
+        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
+        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
+        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
+        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
+        //
+        // (Since Q might be larger than 2^32 - 1)
+        //
+        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
+        //
+        // (Q_hi + H does not overflow a 64-bit int)
+        //
+        //   = p_lo + 2^64 p_hi
+
+        const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
+        const std::uint64_t u_hi = x.f >> 32u;
+        const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
+        const std::uint64_t v_hi = y.f >> 32u;
+
+        const std::uint64_t p0 = u_lo * v_lo;
+        const std::uint64_t p1 = u_lo * v_hi;
+        const std::uint64_t p2 = u_hi * v_lo;
+        const std::uint64_t p3 = u_hi * v_hi;
+
+        const std::uint64_t p0_hi = p0 >> 32u;
+        const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
+        const std::uint64_t p1_hi = p1 >> 32u;
+        const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
+        const std::uint64_t p2_hi = p2 >> 32u;
+
+        std::uint64_t Q = p0_hi + p1_lo + p2_lo;
+
+        // The full product might now be computed as
+        //
+        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
+        // p_lo = p0_lo + (Q << 32)
+        //
+        // But in this particular case here, the full p_lo is not required.
+        // Effectively we only need to add the highest bit in p_lo to p_hi (and
+        // Q_hi + 1 does not overflow).
+
+        Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
+
+        const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
+
+        return {h, x.e + y.e + 64};
+    }
+
+    /*!
+    @brief normalize x such that the significand is >= 2^(q-1)
+    @pre x.f != 0
+    */
+    static diyfp normalize(diyfp x) noexcept
+    {
+        JSON_ASSERT(x.f != 0);
+
+        while ((x.f >> 63u) == 0)
+        {
+            x.f <<= 1u;
+            x.e--;
+        }
+
+        return x;
+    }
+
+    /*!
+    @brief normalize x such that the result has the exponent E
+    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
+    */
+    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
+    {
+        const int delta = x.e - target_exponent;
+
+        JSON_ASSERT(delta >= 0);
+        JSON_ASSERT(((x.f << delta) >> delta) == x.f);
+
+        return {x.f << delta, target_exponent};
+    }
+};
+
+struct boundaries
+{
+    diyfp w;
+    diyfp minus;
+    diyfp plus;
+};
+
+/*!
+Compute the (normalized) diyfp representing the input number 'value' and its
+boundaries.
+
+@pre value must be finite and positive
+*/
+template<typename FloatType>
+boundaries compute_boundaries(FloatType value)
+{
+    JSON_ASSERT(std::isfinite(value));
+    JSON_ASSERT(value > 0);
+
+    // Convert the IEEE representation into a diyfp.
+    //
+    // If v is denormal:
+    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
+    // If v is normalized:
+    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
+
+    static_assert(std::numeric_limits<FloatType>::is_iec559,
+                  "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
+
+    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
+    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
+    constexpr int      kMinExp    = 1 - kBias;
+    constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
+
+    using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
+
+    const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
+    const std::uint64_t E = bits >> (kPrecision - 1);
+    const std::uint64_t F = bits & (kHiddenBit - 1);
+
+    const bool is_denormal = E == 0;
+    const diyfp v = is_denormal
+                    ? diyfp(F, kMinExp)
+                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
+
+    // Compute the boundaries m- and m+ of the floating-point value
+    // v = f * 2^e.
+    //
+    // Determine v- and v+, the floating-point predecessor and successor if v,
+    // respectively.
+    //
+    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
+    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
+    //
+    //      v+ = v + 2^e
+    //
+    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
+    // between m- and m+ round to v, regardless of how the input rounding
+    // algorithm breaks ties.
+    //
+    //      ---+-------------+-------------+-------------+-------------+---  (A)
+    //         v-            m-            v             m+            v+
+    //
+    //      -----------------+------+------+-------------+-------------+---  (B)
+    //                       v-     m-     v             m+            v+
+
+    const bool lower_boundary_is_closer = F == 0 && E > 1;
+    const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
+    const diyfp m_minus = lower_boundary_is_closer
+                          ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
+                          : diyfp(2 * v.f - 1, v.e - 1); // (A)
+
+    // Determine the normalized w+ = m+.
+    const diyfp w_plus = diyfp::normalize(m_plus);
+
+    // Determine w- = m- such that e_(w-) = e_(w+).
+    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
+
+    return {diyfp::normalize(v), w_minus, w_plus};
+}
+
+// Given normalized diyfp w, Grisu needs to find a (normalized) cached
+// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
+// within a certain range [alpha, gamma] (Definition 3.2 from [1])
+//
+//      alpha <= e = e_c + e_w + q <= gamma
+//
+// or
+//
+//      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
+//                          <= f_c * f_w * 2^gamma
+//
+// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
+//
+//      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
+//
+// or
+//
+//      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
+//
+// The choice of (alpha,gamma) determines the size of the table and the form of
+// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
+// in practice:
+//
+// The idea is to cut the number c * w = f * 2^e into two parts, which can be
+// processed independently: An integral part p1, and a fractional part p2:
+//
+//      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
+//              = (f div 2^-e) + (f mod 2^-e) * 2^e
+//              = p1 + p2 * 2^e
+//
+// The conversion of p1 into decimal form requires a series of divisions and
+// modulos by (a power of) 10. These operations are faster for 32-bit than for
+// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
+// achieved by choosing
+//
+//      -e >= 32   or   e <= -32 := gamma
+//
+// In order to convert the fractional part
+//
+//      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
+//
+// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
+// d[-i] are extracted in order:
+//
+//      (10 * p2) div 2^-e = d[-1]
+//      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
+//
+// The multiplication by 10 must not overflow. It is sufficient to choose
+//
+//      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
+//
+// Since p2 = f mod 2^-e < 2^-e,
+//
+//      -e <= 60   or   e >= -60 := alpha
+
+constexpr int kAlpha = -60;
+constexpr int kGamma = -32;
+
+struct cached_power // c = f * 2^e ~= 10^k
+{
+    std::uint64_t f;
+    int e;
+    int k;
+};
+
+/*!
+For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
+power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
+satisfies (Definition 3.2 from [1])
+
+     alpha <= e_c + e + q <= gamma.
+*/
+inline cached_power get_cached_power_for_binary_exponent(int e)
+{
+    // Now
+    //
+    //      alpha <= e_c + e + q <= gamma                                    (1)
+    //      ==> f_c * 2^alpha <= c * 2^e * 2^q
+    //
+    // and since the c's are normalized, 2^(q-1) <= f_c,
+    //
+    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
+    //      ==> 2^(alpha - e - 1) <= c
+    //
+    // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
+    //
+    //      k = ceil( log_10( 2^(alpha - e - 1) ) )
+    //        = ceil( (alpha - e - 1) * log_10(2) )
+    //
+    // From the paper:
+    // "In theory the result of the procedure could be wrong since c is rounded,
+    //  and the computation itself is approximated [...]. In practice, however,
+    //  this simple function is sufficient."
+    //
+    // For IEEE double precision floating-point numbers converted into
+    // normalized diyfp's w = f * 2^e, with q = 64,
+    //
+    //      e >= -1022      (min IEEE exponent)
+    //           -52        (p - 1)
+    //           -52        (p - 1, possibly normalize denormal IEEE numbers)
+    //           -11        (normalize the diyfp)
+    //         = -1137
+    //
+    // and
+    //
+    //      e <= +1023      (max IEEE exponent)
+    //           -52        (p - 1)
+    //           -11        (normalize the diyfp)
+    //         = 960
+    //
+    // This binary exponent range [-1137,960] results in a decimal exponent
+    // range [-307,324]. One does not need to store a cached power for each
+    // k in this range. For each such k it suffices to find a cached power
+    // such that the exponent of the product lies in [alpha,gamma].
+    // This implies that the difference of the decimal exponents of adjacent
+    // table entries must be less than or equal to
+    //
+    //      floor( (gamma - alpha) * log_10(2) ) = 8.
+    //
+    // (A smaller distance gamma-alpha would require a larger table.)
+
+    // NB:
+    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
+
+    constexpr int kCachedPowersMinDecExp = -300;
+    constexpr int kCachedPowersDecStep = 8;
+
+    static constexpr std::array<cached_power, 79> kCachedPowers =
+    {
+        {
+            { 0xAB70FE17C79AC6CA, -1060, -300 },
+            { 0xFF77B1FCBEBCDC4F, -1034, -292 },
+            { 0xBE5691EF416BD60C, -1007, -284 },
+            { 0x8DD01FAD907FFC3C,  -980, -276 },
+            { 0xD3515C2831559A83,  -954, -268 },
+            { 0x9D71AC8FADA6C9B5,  -927, -260 },
+            { 0xEA9C227723EE8BCB,  -901, -252 },
+            { 0xAECC49914078536D,  -874, -244 },
+            { 0x823C12795DB6CE57,  -847, -236 },
+            { 0xC21094364DFB5637,  -821, -228 },
+            { 0x9096EA6F3848984F,  -794, -220 },
+            { 0xD77485CB25823AC7,  -768, -212 },
+            { 0xA086CFCD97BF97F4,  -741, -204 },
+            { 0xEF340A98172AACE5,  -715, -196 },
+            { 0xB23867FB2A35B28E,  -688, -188 },
+            { 0x84C8D4DFD2C63F3B,  -661, -180 },
+            { 0xC5DD44271AD3CDBA,  -635, -172 },
+            { 0x936B9FCEBB25C996,  -608, -164 },
+            { 0xDBAC6C247D62A584,  -582, -156 },
+            { 0xA3AB66580D5FDAF6,  -555, -148 },
+            { 0xF3E2F893DEC3F126,  -529, -140 },
+            { 0xB5B5ADA8AAFF80B8,  -502, -132 },
+            { 0x87625F056C7C4A8B,  -475, -124 },
+            { 0xC9BCFF6034C13053,  -449, -116 },
+            { 0x964E858C91BA2655,  -422, -108 },
+            { 0xDFF9772470297EBD,  -396, -100 },
+            { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
+            { 0xF8A95FCF88747D94,  -343,  -84 },
+            { 0xB94470938FA89BCF,  -316,  -76 },
+            { 0x8A08F0F8BF0F156B,  -289,  -68 },
+            { 0xCDB02555653131B6,  -263,  -60 },
+            { 0x993FE2C6D07B7FAC,  -236,  -52 },
+            { 0xE45C10C42A2B3B06,  -210,  -44 },
+            { 0xAA242499697392D3,  -183,  -36 },
+            { 0xFD87B5F28300CA0E,  -157,  -28 },
+            { 0xBCE5086492111AEB,  -130,  -20 },
+            { 0x8CBCCC096F5088CC,  -103,  -12 },
+            { 0xD1B71758E219652C,   -77,   -4 },
+            { 0x9C40000000000000,   -50,    4 },
+            { 0xE8D4A51000000000,   -24,   12 },
+            { 0xAD78EBC5AC620000,     3,   20 },
+            { 0x813F3978F8940984,    30,   28 },
+            { 0xC097CE7BC90715B3,    56,   36 },
+            { 0x8F7E32CE7BEA5C70,    83,   44 },
+            { 0xD5D238A4ABE98068,   109,   52 },
+            { 0x9F4F2726179A2245,   136,   60 },
+            { 0xED63A231D4C4FB27,   162,   68 },
+            { 0xB0DE65388CC8ADA8,   189,   76 },
+            { 0x83C7088E1AAB65DB,   216,   84 },
+            { 0xC45D1DF942711D9A,   242,   92 },
+            { 0x924D692CA61BE758,   269,  100 },
+            { 0xDA01EE641A708DEA,   295,  108 },
+            { 0xA26DA3999AEF774A,   322,  116 },
+            { 0xF209787BB47D6B85,   348,  124 },
+            { 0xB454E4A179DD1877,   375,  132 },
+            { 0x865B86925B9BC5C2,   402,  140 },
+            { 0xC83553C5C8965D3D,   428,  148 },
+            { 0x952AB45CFA97A0B3,   455,  156 },
+            { 0xDE469FBD99A05FE3,   481,  164 },
+            { 0xA59BC234DB398C25,   508,  172 },
+            { 0xF6C69A72A3989F5C,   534,  180 },
+            { 0xB7DCBF5354E9BECE,   561,  188 },
+            { 0x88FCF317F22241E2,   588,  196 },
+            { 0xCC20CE9BD35C78A5,   614,  204 },
+            { 0x98165AF37B2153DF,   641,  212 },
+            { 0xE2A0B5DC971F303A,   667,  220 },
+            { 0xA8D9D1535CE3B396,   694,  228 },
+            { 0xFB9B7CD9A4A7443C,   720,  236 },
+            { 0xBB764C4CA7A44410,   747,  244 },
+            { 0x8BAB8EEFB6409C1A,   774,  252 },
+            { 0xD01FEF10A657842C,   800,  260 },
+            { 0x9B10A4E5E9913129,   827,  268 },
+            { 0xE7109BFBA19C0C9D,   853,  276 },
+            { 0xAC2820D9623BF429,   880,  284 },
+            { 0x80444B5E7AA7CF85,   907,  292 },
+            { 0xBF21E44003ACDD2D,   933,  300 },
+            { 0x8E679C2F5E44FF8F,   960,  308 },
+            { 0xD433179D9C8CB841,   986,  316 },
+            { 0x9E19DB92B4E31BA9,  1013,  324 },
+        }
+    };
+
+    // This computation gives exactly the same results for k as
+    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
+    // for |e| <= 1500, but doesn't require floating-point operations.
+    // NB: log_10(2) ~= 78913 / 2^18
+    JSON_ASSERT(e >= -1500);
+    JSON_ASSERT(e <=  1500);
+    const int f = kAlpha - e - 1;
+    const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
+
+    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
+    JSON_ASSERT(index >= 0);
+    JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
+
+    const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
+    JSON_ASSERT(kAlpha <= cached.e + e + 64);
+    JSON_ASSERT(kGamma >= cached.e + e + 64);
+
+    return cached;
+}
+
+/*!
+For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
+For n == 0, returns 1 and sets pow10 := 1.
+*/
+inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
+{
+    // LCOV_EXCL_START
+    if (n >= 1000000000)
+    {
+        pow10 = 1000000000;
+        return 10;
+    }
+    // LCOV_EXCL_STOP
+    if (n >= 100000000)
+    {
+        pow10 = 100000000;
+        return  9;
+    }
+    if (n >= 10000000)
+    {
+        pow10 = 10000000;
+        return  8;
+    }
+    if (n >= 1000000)
+    {
+        pow10 = 1000000;
+        return  7;
+    }
+    if (n >= 100000)
+    {
+        pow10 = 100000;
+        return  6;
+    }
+    if (n >= 10000)
+    {
+        pow10 = 10000;
+        return  5;
+    }
+    if (n >= 1000)
+    {
+        pow10 = 1000;
+        return  4;
+    }
+    if (n >= 100)
+    {
+        pow10 = 100;
+        return  3;
+    }
+    if (n >= 10)
+    {
+        pow10 = 10;
+        return  2;
+    }
+
+    pow10 = 1;
+    return 1;
+}
+
+inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
+                         std::uint64_t rest, std::uint64_t ten_k)
+{
+    JSON_ASSERT(len >= 1);
+    JSON_ASSERT(dist <= delta);
+    JSON_ASSERT(rest <= delta);
+    JSON_ASSERT(ten_k > 0);
+
+    //               <--------------------------- delta ---->
+    //                                  <---- dist --------->
+    // --------------[------------------+-------------------]--------------
+    //               M-                 w                   M+
+    //
+    //                                  ten_k
+    //                                <------>
+    //                                       <---- rest ---->
+    // --------------[------------------+----+--------------]--------------
+    //                                  w    V
+    //                                       = buf * 10^k
+    //
+    // ten_k represents a unit-in-the-last-place in the decimal representation
+    // stored in buf.
+    // Decrement buf by ten_k while this takes buf closer to w.
+
+    // The tests are written in this order to avoid overflow in unsigned
+    // integer arithmetic.
+
+    while (rest < dist
+            && delta - rest >= ten_k
+            && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
+    {
+        JSON_ASSERT(buf[len - 1] != '0');
+        buf[len - 1]--;
+        rest += ten_k;
+    }
+}
+
+/*!
+Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
+M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
+*/
+inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
+                             diyfp M_minus, diyfp w, diyfp M_plus)
+{
+    static_assert(kAlpha >= -60, "internal error");
+    static_assert(kGamma <= -32, "internal error");
+
+    // Generates the digits (and the exponent) of a decimal floating-point
+    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
+    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
+    //
+    //               <--------------------------- delta ---->
+    //                                  <---- dist --------->
+    // --------------[------------------+-------------------]--------------
+    //               M-                 w                   M+
+    //
+    // Grisu2 generates the digits of M+ from left to right and stops as soon as
+    // V is in [M-,M+].
+
+    JSON_ASSERT(M_plus.e >= kAlpha);
+    JSON_ASSERT(M_plus.e <= kGamma);
+
+    std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
+    std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
+
+    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
+    //
+    //      M+ = f * 2^e
+    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
+    //         = ((p1        ) * 2^-e + (p2        )) * 2^e
+    //         = p1 + p2 * 2^e
+
+    const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
+
+    auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
+    std::uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
+
+    // 1)
+    //
+    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
+
+    JSON_ASSERT(p1 > 0);
+
+    std::uint32_t pow10{};
+    const int k = find_largest_pow10(p1, pow10);
+
+    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
+    //
+    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
+    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
+    //
+    //      M+ = p1                                             + p2 * 2^e
+    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
+    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
+    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
+    //
+    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
+    //
+    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
+    //
+    // but stop as soon as
+    //
+    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
+
+    int n = k;
+    while (n > 0)
+    {
+        // Invariants:
+        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
+        //      pow10 = 10^(n-1) <= p1 < 10^n
+        //
+        const std::uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
+        const std::uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
+        //
+        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
+        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
+        //
+        JSON_ASSERT(d <= 9);
+        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
+        //
+        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
+        //
+        p1 = r;
+        n--;
+        //
+        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
+        //      pow10 = 10^n
+        //
+
+        // Now check if enough digits have been generated.
+        // Compute
+        //
+        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
+        //
+        // Note:
+        // Since rest and delta share the same exponent e, it suffices to
+        // compare the significands.
+        const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
+        if (rest <= delta)
+        {
+            // V = buffer * 10^n, with M- <= V <= M+.
+
+            decimal_exponent += n;
+
+            // We may now just stop. But instead look if the buffer could be
+            // decremented to bring V closer to w.
+            //
+            // pow10 = 10^n is now 1 ulp in the decimal representation V.
+            // The rounding procedure works with diyfp's with an implicit
+            // exponent of e.
+            //
+            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
+            //
+            const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
+            grisu2_round(buffer, length, dist, delta, rest, ten_n);
+
+            return;
+        }
+
+        pow10 /= 10;
+        //
+        //      pow10 = 10^(n-1) <= p1 < 10^n
+        // Invariants restored.
+    }
+
+    // 2)
+    //
+    // The digits of the integral part have been generated:
+    //
+    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
+    //         = buffer            + p2 * 2^e
+    //
+    // Now generate the digits of the fractional part p2 * 2^e.
+    //
+    // Note:
+    // No decimal point is generated: the exponent is adjusted instead.
+    //
+    // p2 actually represents the fraction
+    //
+    //      p2 * 2^e
+    //          = p2 / 2^-e
+    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
+    //
+    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
+    //
+    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
+    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
+    //
+    // using
+    //
+    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
+    //                = (                   d) * 2^-e + (                   r)
+    //
+    // or
+    //      10^m * p2 * 2^e = d + r * 2^e
+    //
+    // i.e.
+    //
+    //      M+ = buffer + p2 * 2^e
+    //         = buffer + 10^-m * (d + r * 2^e)
+    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
+    //
+    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
+
+    JSON_ASSERT(p2 > delta);
+
+    int m = 0;
+    for (;;)
+    {
+        // Invariant:
+        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
+        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
+        //
+        JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
+        p2 *= 10;
+        const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
+        const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
+        //
+        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
+        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
+        //
+        JSON_ASSERT(d <= 9);
+        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
+        //
+        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
+        //
+        p2 = r;
+        m++;
+        //
+        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
+        // Invariant restored.
+
+        // Check if enough digits have been generated.
+        //
+        //      10^-m * p2 * 2^e <= delta * 2^e
+        //              p2 * 2^e <= 10^m * delta * 2^e
+        //                    p2 <= 10^m * delta
+        delta *= 10;
+        dist  *= 10;
+        if (p2 <= delta)
+        {
+            break;
+        }
+    }
+
+    // V = buffer * 10^-m, with M- <= V <= M+.
+
+    decimal_exponent -= m;
+
+    // 1 ulp in the decimal representation is now 10^-m.
+    // Since delta and dist are now scaled by 10^m, we need to do the
+    // same with ulp in order to keep the units in sync.
+    //
+    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
+    //
+    const std::uint64_t ten_m = one.f;
+    grisu2_round(buffer, length, dist, delta, p2, ten_m);
+
+    // By construction this algorithm generates the shortest possible decimal
+    // number (Loitsch, Theorem 6.2) which rounds back to w.
+    // For an input number of precision p, at least
+    //
+    //      N = 1 + ceil(p * log_10(2))
+    //
+    // decimal digits are sufficient to identify all binary floating-point
+    // numbers (Matula, "In-and-Out conversions").
+    // This implies that the algorithm does not produce more than N decimal
+    // digits.
+    //
+    //      N = 17 for p = 53 (IEEE double precision)
+    //      N = 9  for p = 24 (IEEE single precision)
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline void grisu2(char* buf, int& len, int& decimal_exponent,
+                   diyfp m_minus, diyfp v, diyfp m_plus)
+{
+    JSON_ASSERT(m_plus.e == m_minus.e);
+    JSON_ASSERT(m_plus.e == v.e);
+
+    //  --------(-----------------------+-----------------------)--------    (A)
+    //          m-                      v                       m+
+    //
+    //  --------------------(-----------+-----------------------)--------    (B)
+    //                      m-          v                       m+
+    //
+    // First scale v (and m- and m+) such that the exponent is in the range
+    // [alpha, gamma].
+
+    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
+
+    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
+
+    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
+    const diyfp w       = diyfp::mul(v,       c_minus_k);
+    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
+    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
+
+    //  ----(---+---)---------------(---+---)---------------(---+---)----
+    //          w-                      w                       w+
+    //          = c*m-                  = c*v                   = c*m+
+    //
+    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
+    // w+ are now off by a small amount.
+    // In fact:
+    //
+    //      w - v * 10^k < 1 ulp
+    //
+    // To account for this inaccuracy, add resp. subtract 1 ulp.
+    //
+    //  --------+---[---------------(---+---)---------------]---+--------
+    //          w-  M-                  w                   M+  w+
+    //
+    // Now any number in [M-, M+] (bounds included) will round to w when input,
+    // regardless of how the input rounding algorithm breaks ties.
+    //
+    // And digit_gen generates the shortest possible such number in [M-, M+].
+    // Note that this does not mean that Grisu2 always generates the shortest
+    // possible number in the interval (m-, m+).
+    const diyfp M_minus(w_minus.f + 1, w_minus.e);
+    const diyfp M_plus (w_plus.f  - 1, w_plus.e );
+
+    decimal_exponent = -cached.k; // = -(-k) = k
+
+    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+template<typename FloatType>
+JSON_HEDLEY_NON_NULL(1)
+void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
+{
+    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
+                  "internal error: not enough precision");
+
+    JSON_ASSERT(std::isfinite(value));
+    JSON_ASSERT(value > 0);
+
+    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
+    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
+    // decimal representations are not exactly "short".
+    //
+    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
+    // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
+    // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
+    // does.
+    // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
+    // representation using the corresponding std::from_chars function recovers value exactly". That
+    // indicates that single precision floating-point numbers should be recovered using
+    // 'std::strtof'.
+    //
+    // NB: If the neighbors are computed for single-precision numbers, there is a single float
+    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
+    //     value is off by 1 ulp.
+#if 0
+    const boundaries w = compute_boundaries(static_cast<double>(value));
+#else
+    const boundaries w = compute_boundaries(value);
+#endif
+
+    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
+}
+
+/*!
+@brief appends a decimal representation of e to buf
+@return a pointer to the element following the exponent.
+@pre -1000 < e < 1000
+*/
+JSON_HEDLEY_NON_NULL(1)
+JSON_HEDLEY_RETURNS_NON_NULL
+inline char* append_exponent(char* buf, int e)
+{
+    JSON_ASSERT(e > -1000);
+    JSON_ASSERT(e <  1000);
+
+    if (e < 0)
+    {
+        e = -e;
+        *buf++ = '-';
+    }
+    else
+    {
+        *buf++ = '+';
+    }
+
+    auto k = static_cast<std::uint32_t>(e);
+    if (k < 10)
+    {
+        // Always print at least two digits in the exponent.
+        // This is for compatibility with printf("%g").
+        *buf++ = '0';
+        *buf++ = static_cast<char>('0' + k);
+    }
+    else if (k < 100)
+    {
+        *buf++ = static_cast<char>('0' + k / 10);
+        k %= 10;
+        *buf++ = static_cast<char>('0' + k);
+    }
+    else
+    {
+        *buf++ = static_cast<char>('0' + k / 100);
+        k %= 100;
+        *buf++ = static_cast<char>('0' + k / 10);
+        k %= 10;
+        *buf++ = static_cast<char>('0' + k);
+    }
+
+    return buf;
+}
+
+/*!
+@brief prettify v = buf * 10^decimal_exponent
+
+If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
+notation. Otherwise it will be printed in exponential notation.
+
+@pre min_exp < 0
+@pre max_exp > 0
+*/
+JSON_HEDLEY_NON_NULL(1)
+JSON_HEDLEY_RETURNS_NON_NULL
+inline char* format_buffer(char* buf, int len, int decimal_exponent,
+                           int min_exp, int max_exp)
+{
+    JSON_ASSERT(min_exp < 0);
+    JSON_ASSERT(max_exp > 0);
+
+    const int k = len;
+    const int n = len + decimal_exponent;
+
+    // v = buf * 10^(n-k)
+    // k is the length of the buffer (number of decimal digits)
+    // n is the position of the decimal point relative to the start of the buffer.
+
+    if (k <= n && n <= max_exp)
+    {
+        // digits[000]
+        // len <= max_exp + 2
+
+        std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
+        // Make it look like a floating-point number (#362, #378)
+        buf[n + 0] = '.';
+        buf[n + 1] = '0';
+        return buf + (static_cast<size_t>(n) + 2);
+    }
+
+    if (0 < n && n <= max_exp)
+    {
+        // dig.its
+        // len <= max_digits10 + 1
+
+        JSON_ASSERT(k > n);
+
+        std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
+        buf[n] = '.';
+        return buf + (static_cast<size_t>(k) + 1U);
+    }
+
+    if (min_exp < n && n <= 0)
+    {
+        // 0.[000]digits
+        // len <= 2 + (-min_exp - 1) + max_digits10
+
+        std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
+        buf[0] = '0';
+        buf[1] = '.';
+        std::memset(buf + 2, '0', static_cast<size_t>(-n));
+        return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
+    }
+
+    if (k == 1)
+    {
+        // dE+123
+        // len <= 1 + 5
+
+        buf += 1;
+    }
+    else
+    {
+        // d.igitsE+123
+        // len <= max_digits10 + 1 + 5
+
+        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
+        buf[1] = '.';
+        buf += 1 + static_cast<size_t>(k);
+    }
+
+    *buf++ = 'e';
+    return append_exponent(buf, n - 1);
+}
+
+} // namespace dtoa_impl
+
+/*!
+@brief generates a decimal representation of the floating-point number value in [first, last).
+
+The format of the resulting decimal representation is similar to printf's %g
+format. Returns an iterator pointing past-the-end of the decimal representation.
+
+@note The input number must be finite, i.e. NaN's and Inf's are not supported.
+@note The buffer must be large enough.
+@note The result is NOT null-terminated.
+*/
+template<typename FloatType>
+JSON_HEDLEY_NON_NULL(1, 2)
+JSON_HEDLEY_RETURNS_NON_NULL
+char* to_chars(char* first, const char* last, FloatType value)
+{
+    static_cast<void>(last); // maybe unused - fix warning
+    JSON_ASSERT(std::isfinite(value));
+
+    // Use signbit(value) instead of (value < 0) since signbit works for -0.
+    if (std::signbit(value))
+    {
+        value = -value;
+        *first++ = '-';
+    }
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+    if (value == 0) // +-0
+    {
+        *first++ = '0';
+        // Make it look like a floating-point number (#362, #378)
+        *first++ = '.';
+        *first++ = '0';
+        return first;
+    }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
+
+    // Compute v = buffer * 10^decimal_exponent.
+    // The decimal digits are stored in the buffer, which needs to be interpreted
+    // as an unsigned decimal integer.
+    // len is the length of the buffer, i.e. the number of decimal digits.
+    int len = 0;
+    int decimal_exponent = 0;
+    dtoa_impl::grisu2(first, len, decimal_exponent, value);
+
+    JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
+
+    // Format the buffer like printf("%.*g", prec, value)
+    constexpr int kMinExp = -4;
+    // Use digits10 here to increase compatibility with version 2.
+    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
+
+    JSON_ASSERT(last - first >= kMaxExp + 2);
+    JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
+    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
+
+    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
+}
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/output/binary_writer.hpp>
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////
+// serialization //
+///////////////////
+
+/// how to treat decoding errors
+enum class error_handler_t
+{
+    strict,  ///< throw a type_error exception in case of invalid UTF-8
+    replace, ///< replace invalid UTF-8 sequences with U+FFFD
+    ignore   ///< ignore invalid UTF-8 sequences
+};
+
+template<typename BasicJsonType>
+class serializer
+{
+    using string_t = typename BasicJsonType::string_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using binary_char_t = typename BasicJsonType::binary_t::value_type;
+    static constexpr std::uint8_t UTF8_ACCEPT = 0;
+    static constexpr std::uint8_t UTF8_REJECT = 1;
+
+  public:
+    /*!
+    @param[in] s  output stream to serialize to
+    @param[in] ichar  indentation character to use
+    @param[in] error_handler_  how to react on decoding errors
+    */
+    serializer(output_adapter_t<char> s, const char ichar,
+               error_handler_t error_handler_ = error_handler_t::strict)
+        : o(std::move(s))
+        , loc(std::localeconv())
+        , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
+        , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
+        , indent_char(ichar)
+        , indent_string(512, indent_char)
+        , error_handler(error_handler_)
+    {}
+
+    // delete because of pointer members
+    serializer(const serializer&) = delete;
+    serializer& operator=(const serializer&) = delete;
+    serializer(serializer&&) = delete;
+    serializer& operator=(serializer&&) = delete;
+    ~serializer() = default;
+
+    /*!
+    @brief internal implementation of the serialization function
+
+    This function is called by the public member function dump and organizes
+    the serialization internally. The indentation level is propagated as
+    additional parameter. In case of arrays and objects, the function is
+    called recursively.
+
+    - strings and object keys are escaped using `escape_string()`
+    - integer numbers are converted implicitly via `operator<<`
+    - floating-point numbers are converted to a string using `"%g"` format
+    - binary values are serialized as objects containing the subtype and the
+      byte array
+
+    @param[in] val               value to serialize
+    @param[in] pretty_print      whether the output shall be pretty-printed
+    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
+    in the output are escaped with `\uXXXX` sequences, and the result consists
+    of ASCII characters only.
+    @param[in] indent_step       the indent level
+    @param[in] current_indent    the current indent level (only used internally)
+    */
+    void dump(const BasicJsonType& val,
+              const bool pretty_print,
+              const bool ensure_ascii,
+              const unsigned int indent_step,
+              const unsigned int current_indent = 0)
+    {
+        switch (val.m_type)
+        {
+            case value_t::object:
+            {
+                if (val.m_value.object->empty())
+                {
+                    o->write_characters("{}", 2);
+                    return;
+                }
+
+                if (pretty_print)
+                {
+                    o->write_characters("{\n", 2);
+
+                    // variable to hold indentation for recursive calls
+                    const auto new_indent = current_indent + indent_step;
+                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+                    {
+                        indent_string.resize(indent_string.size() * 2, ' ');
+                    }
+
+                    // first n-1 elements
+                    auto i = val.m_value.object->cbegin();
+                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+                    {
+                        o->write_characters(indent_string.c_str(), new_indent);
+                        o->write_character('\"');
+                        dump_escaped(i->first, ensure_ascii);
+                        o->write_characters("\": ", 3);
+                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
+                        o->write_characters(",\n", 2);
+                    }
+
+                    // last element
+                    JSON_ASSERT(i != val.m_value.object->cend());
+                    JSON_ASSERT(std::next(i) == val.m_value.object->cend());
+                    o->write_characters(indent_string.c_str(), new_indent);
+                    o->write_character('\"');
+                    dump_escaped(i->first, ensure_ascii);
+                    o->write_characters("\": ", 3);
+                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
+
+                    o->write_character('\n');
+                    o->write_characters(indent_string.c_str(), current_indent);
+                    o->write_character('}');
+                }
+                else
+                {
+                    o->write_character('{');
+
+                    // first n-1 elements
+                    auto i = val.m_value.object->cbegin();
+                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+                    {
+                        o->write_character('\"');
+                        dump_escaped(i->first, ensure_ascii);
+                        o->write_characters("\":", 2);
+                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
+                        o->write_character(',');
+                    }
+
+                    // last element
+                    JSON_ASSERT(i != val.m_value.object->cend());
+                    JSON_ASSERT(std::next(i) == val.m_value.object->cend());
+                    o->write_character('\"');
+                    dump_escaped(i->first, ensure_ascii);
+                    o->write_characters("\":", 2);
+                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
+
+                    o->write_character('}');
+                }
+
+                return;
+            }
+
+            case value_t::array:
+            {
+                if (val.m_value.array->empty())
+                {
+                    o->write_characters("[]", 2);
+                    return;
+                }
+
+                if (pretty_print)
+                {
+                    o->write_characters("[\n", 2);
+
+                    // variable to hold indentation for recursive calls
+                    const auto new_indent = current_indent + indent_step;
+                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+                    {
+                        indent_string.resize(indent_string.size() * 2, ' ');
+                    }
+
+                    // first n-1 elements
+                    for (auto i = val.m_value.array->cbegin();
+                            i != val.m_value.array->cend() - 1; ++i)
+                    {
+                        o->write_characters(indent_string.c_str(), new_indent);
+                        dump(*i, true, ensure_ascii, indent_step, new_indent);
+                        o->write_characters(",\n", 2);
+                    }
+
+                    // last element
+                    JSON_ASSERT(!val.m_value.array->empty());
+                    o->write_characters(indent_string.c_str(), new_indent);
+                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
+
+                    o->write_character('\n');
+                    o->write_characters(indent_string.c_str(), current_indent);
+                    o->write_character(']');
+                }
+                else
+                {
+                    o->write_character('[');
+
+                    // first n-1 elements
+                    for (auto i = val.m_value.array->cbegin();
+                            i != val.m_value.array->cend() - 1; ++i)
+                    {
+                        dump(*i, false, ensure_ascii, indent_step, current_indent);
+                        o->write_character(',');
+                    }
+
+                    // last element
+                    JSON_ASSERT(!val.m_value.array->empty());
+                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
+
+                    o->write_character(']');
+                }
+
+                return;
+            }
+
+            case value_t::string:
+            {
+                o->write_character('\"');
+                dump_escaped(*val.m_value.string, ensure_ascii);
+                o->write_character('\"');
+                return;
+            }
+
+            case value_t::binary:
+            {
+                if (pretty_print)
+                {
+                    o->write_characters("{\n", 2);
+
+                    // variable to hold indentation for recursive calls
+                    const auto new_indent = current_indent + indent_step;
+                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+                    {
+                        indent_string.resize(indent_string.size() * 2, ' ');
+                    }
+
+                    o->write_characters(indent_string.c_str(), new_indent);
+
+                    o->write_characters("\"bytes\": [", 10);
+
+                    if (!val.m_value.binary->empty())
+                    {
+                        for (auto i = val.m_value.binary->cbegin();
+                                i != val.m_value.binary->cend() - 1; ++i)
+                        {
+                            dump_integer(*i);
+                            o->write_characters(", ", 2);
+                        }
+                        dump_integer(val.m_value.binary->back());
+                    }
+
+                    o->write_characters("],\n", 3);
+                    o->write_characters(indent_string.c_str(), new_indent);
+
+                    o->write_characters("\"subtype\": ", 11);
+                    if (val.m_value.binary->has_subtype())
+                    {
+                        dump_integer(val.m_value.binary->subtype());
+                    }
+                    else
+                    {
+                        o->write_characters("null", 4);
+                    }
+                    o->write_character('\n');
+                    o->write_characters(indent_string.c_str(), current_indent);
+                    o->write_character('}');
+                }
+                else
+                {
+                    o->write_characters("{\"bytes\":[", 10);
+
+                    if (!val.m_value.binary->empty())
+                    {
+                        for (auto i = val.m_value.binary->cbegin();
+                                i != val.m_value.binary->cend() - 1; ++i)
+                        {
+                            dump_integer(*i);
+                            o->write_character(',');
+                        }
+                        dump_integer(val.m_value.binary->back());
+                    }
+
+                    o->write_characters("],\"subtype\":", 12);
+                    if (val.m_value.binary->has_subtype())
+                    {
+                        dump_integer(val.m_value.binary->subtype());
+                        o->write_character('}');
+                    }
+                    else
+                    {
+                        o->write_characters("null}", 5);
+                    }
+                }
+                return;
+            }
+
+            case value_t::boolean:
+            {
+                if (val.m_value.boolean)
+                {
+                    o->write_characters("true", 4);
+                }
+                else
+                {
+                    o->write_characters("false", 5);
+                }
+                return;
+            }
+
+            case value_t::number_integer:
+            {
+                dump_integer(val.m_value.number_integer);
+                return;
+            }
+
+            case value_t::number_unsigned:
+            {
+                dump_integer(val.m_value.number_unsigned);
+                return;
+            }
+
+            case value_t::number_float:
+            {
+                dump_float(val.m_value.number_float);
+                return;
+            }
+
+            case value_t::discarded:
+            {
+                o->write_characters("<discarded>", 11);
+                return;
+            }
+
+            case value_t::null:
+            {
+                o->write_characters("null", 4);
+                return;
+            }
+
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+    }
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /*!
+    @brief dump escaped string
+
+    Escape a string by replacing certain special characters by a sequence of an
+    escape character (backslash) and another character and other control
+    characters by a sequence of "\u" followed by a four-digit hex
+    representation. The escaped string is written to output stream @a o.
+
+    @param[in] s  the string to escape
+    @param[in] ensure_ascii  whether to escape non-ASCII characters with
+                             \uXXXX sequences
+
+    @complexity Linear in the length of string @a s.
+    */
+    void dump_escaped(const string_t& s, const bool ensure_ascii)
+    {
+        std::uint32_t codepoint{};
+        std::uint8_t state = UTF8_ACCEPT;
+        std::size_t bytes = 0;  // number of bytes written to string_buffer
+
+        // number of bytes written at the point of the last valid byte
+        std::size_t bytes_after_last_accept = 0;
+        std::size_t undumped_chars = 0;
+
+        for (std::size_t i = 0; i < s.size(); ++i)
+        {
+            const auto byte = static_cast<std::uint8_t>(s[i]);
+
+            switch (decode(state, codepoint, byte))
+            {
+                case UTF8_ACCEPT:  // decode found a new code point
+                {
+                    switch (codepoint)
+                    {
+                        case 0x08: // backspace
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'b';
+                            break;
+                        }
+
+                        case 0x09: // horizontal tab
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 't';
+                            break;
+                        }
+
+                        case 0x0A: // newline
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'n';
+                            break;
+                        }
+
+                        case 0x0C: // formfeed
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'f';
+                            break;
+                        }
+
+                        case 0x0D: // carriage return
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'r';
+                            break;
+                        }
+
+                        case 0x22: // quotation mark
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = '\"';
+                            break;
+                        }
+
+                        case 0x5C: // reverse solidus
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = '\\';
+                            break;
+                        }
+
+                        default:
+                        {
+                            // escape control characters (0x00..0x1F) or, if
+                            // ensure_ascii parameter is used, non-ASCII characters
+                            if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
+                            {
+                                if (codepoint <= 0xFFFF)
+                                {
+                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+                                    (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
+                                                    static_cast<std::uint16_t>(codepoint));
+                                    bytes += 6;
+                                }
+                                else
+                                {
+                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+                                    (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
+                                                    static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
+                                                    static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
+                                    bytes += 12;
+                                }
+                            }
+                            else
+                            {
+                                // copy byte to buffer (all previous bytes
+                                // been copied have in default case above)
+                                string_buffer[bytes++] = s[i];
+                            }
+                            break;
+                        }
+                    }
+
+                    // write buffer and reset index; there must be 13 bytes
+                    // left, as this is the maximal number of bytes to be
+                    // written ("\uxxxx\uxxxx\0") for one code point
+                    if (string_buffer.size() - bytes < 13)
+                    {
+                        o->write_characters(string_buffer.data(), bytes);
+                        bytes = 0;
+                    }
+
+                    // remember the byte position of this accept
+                    bytes_after_last_accept = bytes;
+                    undumped_chars = 0;
+                    break;
+                }
+
+                case UTF8_REJECT:  // decode found invalid UTF-8 byte
+                {
+                    switch (error_handler)
+                    {
+                        case error_handler_t::strict:
+                        {
+                            std::stringstream ss;
+                            ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (byte | 0);
+                            JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str(), BasicJsonType()));
+                        }
+
+                        case error_handler_t::ignore:
+                        case error_handler_t::replace:
+                        {
+                            // in case we saw this character the first time, we
+                            // would like to read it again, because the byte
+                            // may be OK for itself, but just not OK for the
+                            // previous sequence
+                            if (undumped_chars > 0)
+                            {
+                                --i;
+                            }
+
+                            // reset length buffer to the last accepted index;
+                            // thus removing/ignoring the invalid characters
+                            bytes = bytes_after_last_accept;
+
+                            if (error_handler == error_handler_t::replace)
+                            {
+                                // add a replacement character
+                                if (ensure_ascii)
+                                {
+                                    string_buffer[bytes++] = '\\';
+                                    string_buffer[bytes++] = 'u';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'd';
+                                }
+                                else
+                                {
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
+                                }
+
+                                // write buffer and reset index; there must be 13 bytes
+                                // left, as this is the maximal number of bytes to be
+                                // written ("\uxxxx\uxxxx\0") for one code point
+                                if (string_buffer.size() - bytes < 13)
+                                {
+                                    o->write_characters(string_buffer.data(), bytes);
+                                    bytes = 0;
+                                }
+
+                                bytes_after_last_accept = bytes;
+                            }
+
+                            undumped_chars = 0;
+
+                            // continue processing the string
+                            state = UTF8_ACCEPT;
+                            break;
+                        }
+
+                        default:            // LCOV_EXCL_LINE
+                            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+                    }
+                    break;
+                }
+
+                default:  // decode found yet incomplete multi-byte code point
+                {
+                    if (!ensure_ascii)
+                    {
+                        // code point will not be escaped - copy byte to buffer
+                        string_buffer[bytes++] = s[i];
+                    }
+                    ++undumped_chars;
+                    break;
+                }
+            }
+        }
+
+        // we finished processing the string
+        if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
+        {
+            // write buffer
+            if (bytes > 0)
+            {
+                o->write_characters(string_buffer.data(), bytes);
+            }
+        }
+        else
+        {
+            // we finish reading, but do not accept: string was incomplete
+            switch (error_handler)
+            {
+                case error_handler_t::strict:
+                {
+                    std::stringstream ss;
+                    ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (static_cast<std::uint8_t>(s.back()) | 0);
+                    JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str(), BasicJsonType()));
+                }
+
+                case error_handler_t::ignore:
+                {
+                    // write all accepted bytes
+                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
+                    break;
+                }
+
+                case error_handler_t::replace:
+                {
+                    // write all accepted bytes
+                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
+                    // add a replacement character
+                    if (ensure_ascii)
+                    {
+                        o->write_characters("\\ufffd", 6);
+                    }
+                    else
+                    {
+                        o->write_characters("\xEF\xBF\xBD", 3);
+                    }
+                    break;
+                }
+
+                default:            // LCOV_EXCL_LINE
+                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+            }
+        }
+    }
+
+  private:
+    /*!
+    @brief count digits
+
+    Count the number of decimal (base 10) digits for an input unsigned integer.
+
+    @param[in] x  unsigned integer number to count its digits
+    @return    number of decimal digits
+    */
+    inline unsigned int count_digits(number_unsigned_t x) noexcept
+    {
+        unsigned int n_digits = 1;
+        for (;;)
+        {
+            if (x < 10)
+            {
+                return n_digits;
+            }
+            if (x < 100)
+            {
+                return n_digits + 1;
+            }
+            if (x < 1000)
+            {
+                return n_digits + 2;
+            }
+            if (x < 10000)
+            {
+                return n_digits + 3;
+            }
+            x = x / 10000u;
+            n_digits += 4;
+        }
+    }
+
+    /*!
+    @brief dump an integer
+
+    Dump a given integer to output stream @a o. Works internally with
+    @a number_buffer.
+
+    @param[in] x  integer number (signed or unsigned) to dump
+    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
+    */
+    template < typename NumberType, detail::enable_if_t <
+                   std::is_integral<NumberType>::value ||
+                   std::is_same<NumberType, number_unsigned_t>::value ||
+                   std::is_same<NumberType, number_integer_t>::value ||
+                   std::is_same<NumberType, binary_char_t>::value,
+                   int > = 0 >
+    void dump_integer(NumberType x)
+    {
+        static constexpr std::array<std::array<char, 2>, 100> digits_to_99
+        {
+            {
+                {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
+                {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
+                {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
+                {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
+                {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
+                {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
+                {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
+                {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
+                {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
+                {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
+            }
+        };
+
+        // special case for "0"
+        if (x == 0)
+        {
+            o->write_character('0');
+            return;
+        }
+
+        // use a pointer to fill the buffer
+        auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+
+        const bool is_negative = std::is_signed<NumberType>::value && !(x >= 0); // see issue #755
+        number_unsigned_t abs_value;
+
+        unsigned int n_chars{};
+
+        if (is_negative)
+        {
+            *buffer_ptr = '-';
+            abs_value = remove_sign(static_cast<number_integer_t>(x));
+
+            // account one more byte for the minus sign
+            n_chars = 1 + count_digits(abs_value);
+        }
+        else
+        {
+            abs_value = static_cast<number_unsigned_t>(x);
+            n_chars = count_digits(abs_value);
+        }
+
+        // spare 1 byte for '\0'
+        JSON_ASSERT(n_chars < number_buffer.size() - 1);
+
+        // jump to the end to generate the string from backward
+        // so we later avoid reversing the result
+        buffer_ptr += n_chars;
+
+        // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
+        // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
+        while (abs_value >= 100)
+        {
+            const auto digits_index = static_cast<unsigned>((abs_value % 100));
+            abs_value /= 100;
+            *(--buffer_ptr) = digits_to_99[digits_index][1];
+            *(--buffer_ptr) = digits_to_99[digits_index][0];
+        }
+
+        if (abs_value >= 10)
+        {
+            const auto digits_index = static_cast<unsigned>(abs_value);
+            *(--buffer_ptr) = digits_to_99[digits_index][1];
+            *(--buffer_ptr) = digits_to_99[digits_index][0];
+        }
+        else
+        {
+            *(--buffer_ptr) = static_cast<char>('0' + abs_value);
+        }
+
+        o->write_characters(number_buffer.data(), n_chars);
+    }
+
+    /*!
+    @brief dump a floating-point number
+
+    Dump a given floating-point number to output stream @a o. Works internally
+    with @a number_buffer.
+
+    @param[in] x  floating-point number to dump
+    */
+    void dump_float(number_float_t x)
+    {
+        // NaN / inf
+        if (!std::isfinite(x))
+        {
+            o->write_characters("null", 4);
+            return;
+        }
+
+        // If number_float_t is an IEEE-754 single or double precision number,
+        // use the Grisu2 algorithm to produce short numbers which are
+        // guaranteed to round-trip, using strtof and strtod, resp.
+        //
+        // NB: The test below works if <long double> == <double>.
+        static constexpr bool is_ieee_single_or_double
+            = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
+              (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
+
+        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
+    }
+
+    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
+    {
+        auto* begin = number_buffer.data();
+        auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
+
+        o->write_characters(begin, static_cast<size_t>(end - begin));
+    }
+
+    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
+    {
+        // get number of digits for a float -> text -> float round-trip
+        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
+
+        // the actual conversion
+        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+        std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
+
+        // negative value indicates an error
+        JSON_ASSERT(len > 0);
+        // check if buffer was large enough
+        JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
+
+        // erase thousands separator
+        if (thousands_sep != '\0')
+        {
+            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
+            const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
+            std::fill(end, number_buffer.end(), '\0');
+            JSON_ASSERT((end - number_buffer.begin()) <= len);
+            len = (end - number_buffer.begin());
+        }
+
+        // convert decimal point to '.'
+        if (decimal_point != '\0' && decimal_point != '.')
+        {
+            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
+            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
+            if (dec_pos != number_buffer.end())
+            {
+                *dec_pos = '.';
+            }
+        }
+
+        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
+
+        // determine if need to append ".0"
+        const bool value_is_int_like =
+            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
+                         [](char c)
+        {
+            return c == '.' || c == 'e';
+        });
+
+        if (value_is_int_like)
+        {
+            o->write_characters(".0", 2);
+        }
+    }
+
+    /*!
+    @brief check whether a string is UTF-8 encoded
+
+    The function checks each byte of a string whether it is UTF-8 encoded. The
+    result of the check is stored in the @a state parameter. The function must
+    be called initially with state 0 (accept). State 1 means the string must
+    be rejected, because the current byte is not allowed. If the string is
+    completely processed, but the state is non-zero, the string ended
+    prematurely; that is, the last byte indicated more bytes should have
+    followed.
+
+    @param[in,out] state  the state of the decoding
+    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
+    @param[in] byte       next byte to decode
+    @return               new state
+
+    @note The function has been edited: a std::array is used.
+
+    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
+    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+    */
+    static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
+    {
+        static const std::array<std::uint8_t, 400> utf8d =
+        {
+            {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
+                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
+                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
+                8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
+                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
+                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
+                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
+                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
+                1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
+                1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
+                1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
+            }
+        };
+
+        JSON_ASSERT(byte < utf8d.size());
+        const std::uint8_t type = utf8d[byte];
+
+        codep = (state != UTF8_ACCEPT)
+                ? (byte & 0x3fu) | (codep << 6u)
+                : (0xFFu >> type) & (byte);
+
+        std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
+        JSON_ASSERT(index < 400);
+        state = utf8d[index];
+        return state;
+    }
+
+    /*
+     * Overload to make the compiler happy while it is instantiating
+     * dump_integer for number_unsigned_t.
+     * Must never be called.
+     */
+    number_unsigned_t remove_sign(number_unsigned_t x)
+    {
+        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        return x; // LCOV_EXCL_LINE
+    }
+
+    /*
+     * Helper function for dump_integer
+     *
+     * This function takes a negative signed integer and returns its absolute
+     * value as unsigned integer. The plus/minus shuffling is necessary as we can
+     * not directly remove the sign of an arbitrary signed integer as the
+     * absolute values of INT_MIN and INT_MAX are usually not the same. See
+     * #1708 for details.
+     */
+    inline number_unsigned_t remove_sign(number_integer_t x) noexcept
+    {
+        JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
+        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
+    }
+
+  private:
+    /// the output of the serializer
+    output_adapter_t<char> o = nullptr;
+
+    /// a (hopefully) large enough character buffer
+    std::array<char, 64> number_buffer{{}};
+
+    /// the locale
+    const std::lconv* loc = nullptr;
+    /// the locale's thousand separator character
+    const char thousands_sep = '\0';
+    /// the locale's decimal point character
+    const char decimal_point = '\0';
+
+    /// string buffer
+    std::array<char, 512> string_buffer{{}};
+
+    /// the indentation character
+    const char indent_char;
+    /// the indentation string
+    string_t indent_string;
+
+    /// error_handler how to react on decoding errors
+    const error_handler_t error_handler;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/value_t.hpp>
+
+// #include <nlohmann/json_fwd.hpp>
+
+// #include <nlohmann/ordered_map.hpp>
+
+
+#include <functional> // less
+#include <initializer_list> // initializer_list
+#include <iterator> // input_iterator_tag, iterator_traits
+#include <memory> // allocator
+#include <stdexcept> // for out_of_range
+#include <type_traits> // enable_if, is_convertible
+#include <utility> // pair
+#include <vector> // vector
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+
+/// ordered_map: a minimal map-like container that preserves insertion order
+/// for use within nlohmann::basic_json<ordered_map>
+template <class Key, class T, class IgnoredLess = std::less<Key>,
+          class Allocator = std::allocator<std::pair<const Key, T>>>
+                  struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
+{
+    using key_type = Key;
+    using mapped_type = T;
+    using Container = std::vector<std::pair<const Key, T>, Allocator>;
+    using typename Container::iterator;
+    using typename Container::const_iterator;
+    using typename Container::size_type;
+    using typename Container::value_type;
+
+    // Explicit constructors instead of `using Container::Container`
+    // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
+    ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
+    template <class It>
+    ordered_map(It first, It last, const Allocator& alloc = Allocator())
+        : Container{first, last, alloc} {}
+    ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
+        : Container{init, alloc} {}
+
+    std::pair<iterator, bool> emplace(const key_type& key, T&& t)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                return {it, false};
+            }
+        }
+        Container::emplace_back(key, t);
+        return {--this->end(), true};
+    }
+
+    T& operator[](const Key& key)
+    {
+        return emplace(key, T{}).first->second;
+    }
+
+    const T& operator[](const Key& key) const
+    {
+        return at(key);
+    }
+
+    T& at(const Key& key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                return it->second;
+            }
+        }
+
+        JSON_THROW(std::out_of_range("key not found"));
+    }
+
+    const T& at(const Key& key) const
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                return it->second;
+            }
+        }
+
+        JSON_THROW(std::out_of_range("key not found"));
+    }
+
+    size_type erase(const Key& key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                // Since we cannot move const Keys, re-construct them in place
+                for (auto next = it; ++next != this->end(); ++it)
+                {
+                    it->~value_type(); // Destroy but keep allocation
+                    new (&*it) value_type{std::move(*next)};
+                }
+                Container::pop_back();
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    iterator erase(iterator pos)
+    {
+        return erase(pos, std::next(pos));
+    }
+
+    iterator erase(iterator first, iterator last)
+    {
+        const auto elements_affected = std::distance(first, last);
+        const auto offset = std::distance(Container::begin(), first);
+
+        // This is the start situation. We need to delete elements_affected
+        // elements (3 in this example: e, f, g), and need to return an
+        // iterator past the last deleted element (h in this example).
+        // Note that offset is the distance from the start of the vector
+        // to first. We will need this later.
+
+        // [ a, b, c, d, e, f, g, h, i, j ]
+        //               ^        ^
+        //             first    last
+
+        // Since we cannot move const Keys, we re-construct them in place.
+        // We start at first and re-construct (viz. copy) the elements from
+        // the back of the vector. Example for first iteration:
+
+        //               ,--------.
+        //               v        |   destroy e and re-construct with h
+        // [ a, b, c, d, e, f, g, h, i, j ]
+        //               ^        ^
+        //               it       it + elements_affected
+
+        for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
+        {
+            it->~value_type(); // destroy but keep allocation
+            new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
+        }
+
+        // [ a, b, c, d, h, i, j, h, i, j ]
+        //               ^        ^
+        //             first    last
+
+        // remove the unneeded elements at the end of the vector
+        Container::resize(this->size() - static_cast<size_type>(elements_affected));
+
+        // [ a, b, c, d, h, i, j ]
+        //               ^        ^
+        //             first    last
+
+        // first is now pointing past the last deleted element, but we cannot
+        // use this iterator, because it may have been invalidated by the
+        // resize call. Instead, we can return begin() + offset.
+        return Container::begin() + offset;
+    }
+
+    size_type count(const Key& key) const
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    iterator find(const Key& key)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                return it;
+            }
+        }
+        return Container::end();
+    }
+
+    const_iterator find(const Key& key) const
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                return it;
+            }
+        }
+        return Container::end();
+    }
+
+    std::pair<iterator, bool> insert( value_type&& value )
+    {
+        return emplace(value.first, std::move(value.second));
+    }
+
+    std::pair<iterator, bool> insert( const value_type& value )
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == value.first)
+            {
+                return {it, false};
+            }
+        }
+        Container::push_back(value);
+        return {--this->end(), true};
+    }
+
+    template<typename InputIt>
+    using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
+            std::input_iterator_tag>::value>::type;
+
+    template<typename InputIt, typename = require_input_iter<InputIt>>
+    void insert(InputIt first, InputIt last)
+    {
+        for (auto it = first; it != last; ++it)
+        {
+            insert(*it);
+        }
+    }
+};
+
+}  // namespace nlohmann
+
+
+#if defined(JSON_HAS_CPP_17)
+    #include <string_view>
+#endif
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+namespace nlohmann
+{
+
+/*!
+@brief a class to store JSON values
+
+@tparam ObjectType type for JSON objects (`std::map` by default; will be used
+in @ref object_t)
+@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
+in @ref array_t)
+@tparam StringType type for JSON strings and object keys (`std::string` by
+default; will be used in @ref string_t)
+@tparam BooleanType type for JSON booleans (`bool` by default; will be used
+in @ref boolean_t)
+@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
+default; will be used in @ref number_integer_t)
+@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
+`uint64_t` by default; will be used in @ref number_unsigned_t)
+@tparam NumberFloatType type for JSON floating-point numbers (`double` by
+default; will be used in @ref number_float_t)
+@tparam BinaryType type for packed binary data for compatibility with binary
+serialization formats (`std::vector<std::uint8_t>` by default; will be used in
+@ref binary_t)
+@tparam AllocatorType type of the allocator to use (`std::allocator` by
+default)
+@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
+and `from_json()` (@ref adl_serializer by default)
+
+@requirement The class satisfies the following concept requirements:
+- Basic
+ - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
+   JSON values can be default constructed. The result will be a JSON null
+   value.
+ - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
+   A JSON value can be constructed from an rvalue argument.
+ - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
+   A JSON value can be copy-constructed from an lvalue expression.
+ - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
+   A JSON value van be assigned from an rvalue argument.
+ - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
+   A JSON value can be copy-assigned from an lvalue expression.
+ - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
+   JSON values can be destructed.
+- Layout
+ - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
+   JSON values have
+   [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
+   All non-static data members are private and standard layout types, the
+   class has no virtual functions or (virtual) base classes.
+- Library-wide
+ - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
+   JSON values can be compared with `==`, see @ref
+   operator==(const_reference,const_reference).
+ - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
+   JSON values can be compared with `<`, see @ref
+   operator<(const_reference,const_reference).
+ - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
+   Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
+   other compatible types, using unqualified function call @ref swap().
+ - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
+   JSON values can be compared against `std::nullptr_t` objects which are used
+   to model the `null` value.
+- Container
+ - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
+   JSON values can be used like STL containers and provide iterator access.
+ - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
+   JSON values can be used like STL containers and provide reverse iterator
+   access.
+
+@invariant The member variables @a m_value and @a m_type have the following
+relationship:
+- If `m_type == value_t::object`, then `m_value.object != nullptr`.
+- If `m_type == value_t::array`, then `m_value.array != nullptr`.
+- If `m_type == value_t::string`, then `m_value.string != nullptr`.
+The invariants are checked by member function assert_invariant().
+
+@internal
+@note ObjectType trick from https://stackoverflow.com/a/9860911
+@endinternal
+
+@see [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange
+Format](https://tools.ietf.org/html/rfc8259)
+
+@since version 1.0.0
+
+@nosubgrouping
+*/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+{
+  private:
+    template<detail::value_t> friend struct detail::external_constructor;
+    friend ::nlohmann::json_pointer<basic_json>;
+
+    template<typename BasicJsonType, typename InputType>
+    friend class ::nlohmann::detail::parser;
+    friend ::nlohmann::detail::serializer<basic_json>;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::iter_impl;
+    template<typename BasicJsonType, typename CharType>
+    friend class ::nlohmann::detail::binary_writer;
+    template<typename BasicJsonType, typename InputType, typename SAX>
+    friend class ::nlohmann::detail::binary_reader;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::json_sax_dom_parser;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::json_sax_dom_callback_parser;
+    friend class ::nlohmann::detail::exception;
+
+    /// workaround type for MSVC
+    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    // convenience aliases for types residing in namespace detail;
+    using lexer = ::nlohmann::detail::lexer_base<basic_json>;
+
+    template<typename InputAdapterType>
+    static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
+        InputAdapterType adapter,
+        detail::parser_callback_t<basic_json>cb = nullptr,
+        const bool allow_exceptions = true,
+        const bool ignore_comments = false
+                                 )
+    {
+        return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
+                std::move(cb), allow_exceptions, ignore_comments);
+    }
+
+  private:
+    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
+    template<typename BasicJsonType>
+    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
+    template<typename BasicJsonType>
+    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
+    template<typename Iterator>
+    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
+    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
+
+    template<typename CharType>
+    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
+
+    template<typename InputType>
+    using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
+    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    using serializer = ::nlohmann::detail::serializer<basic_json>;
+
+  public:
+    using value_t = detail::value_t;
+    /// JSON Pointer, see @ref nlohmann::json_pointer
+    using json_pointer = ::nlohmann::json_pointer<basic_json>;
+    template<typename T, typename SFINAE>
+    using json_serializer = JSONSerializer<T, SFINAE>;
+    /// how to treat decoding errors
+    using error_handler_t = detail::error_handler_t;
+    /// how to treat CBOR tags
+    using cbor_tag_handler_t = detail::cbor_tag_handler_t;
+    /// helper type for initializer lists of basic_json values
+    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
+
+    using input_format_t = detail::input_format_t;
+    /// SAX interface type, see @ref nlohmann::json_sax
+    using json_sax_t = json_sax<basic_json>;
+
+    ////////////////
+    // exceptions //
+    ////////////////
+
+    /// @name exceptions
+    /// Classes to implement user-defined exceptions.
+    /// @{
+
+    /// @copydoc detail::exception
+    using exception = detail::exception;
+    /// @copydoc detail::parse_error
+    using parse_error = detail::parse_error;
+    /// @copydoc detail::invalid_iterator
+    using invalid_iterator = detail::invalid_iterator;
+    /// @copydoc detail::type_error
+    using type_error = detail::type_error;
+    /// @copydoc detail::out_of_range
+    using out_of_range = detail::out_of_range;
+    /// @copydoc detail::other_error
+    using other_error = detail::other_error;
+
+    /// @}
+
+
+    /////////////////////
+    // container types //
+    /////////////////////
+
+    /// @name container types
+    /// The canonic container types to use @ref basic_json like any other STL
+    /// container.
+    /// @{
+
+    /// the type of elements in a basic_json container
+    using value_type = basic_json;
+
+    /// the type of an element reference
+    using reference = value_type&;
+    /// the type of an element const reference
+    using const_reference = const value_type&;
+
+    /// a type to represent differences between iterators
+    using difference_type = std::ptrdiff_t;
+    /// a type to represent container sizes
+    using size_type = std::size_t;
+
+    /// the allocator type
+    using allocator_type = AllocatorType<basic_json>;
+
+    /// the type of an element pointer
+    using pointer = typename std::allocator_traits<allocator_type>::pointer;
+    /// the type of an element const pointer
+    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
+
+    /// an iterator for a basic_json container
+    using iterator = iter_impl<basic_json>;
+    /// a const iterator for a basic_json container
+    using const_iterator = iter_impl<const basic_json>;
+    /// a reverse iterator for a basic_json container
+    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
+    /// a const reverse iterator for a basic_json container
+    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
+
+    /// @}
+
+
+    /*!
+    @brief returns the allocator associated with the container
+    */
+    static allocator_type get_allocator()
+    {
+        return allocator_type();
+    }
+
+    /*!
+    @brief returns version information on the library
+
+    This function returns a JSON object with information about the library,
+    including the version number and information on the platform and compiler.
+
+    @return JSON object holding version information
+    key         | description
+    ----------- | ---------------
+    `compiler`  | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
+    `copyright` | The copyright line for the library as string.
+    `name`      | The name of the library as string.
+    `platform`  | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
+    `url`       | The URL of the project as string.
+    `version`   | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
+
+    @liveexample{The following code shows an example output of the `meta()`
+    function.,meta}
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @complexity Constant.
+
+    @since 2.1.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json meta()
+    {
+        basic_json result;
+
+        result["copyright"] = "(C) 2013-2021 Niels Lohmann";
+        result["name"] = "JSON for Modern C++";
+        result["url"] = "https://github.com/nlohmann/json";
+        result["version"]["string"] =
+            std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
+            std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
+            std::to_string(NLOHMANN_JSON_VERSION_PATCH);
+        result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
+        result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
+        result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
+
+#ifdef _WIN32
+        result["platform"] = "win32";
+#elif defined __linux__
+        result["platform"] = "linux";
+#elif defined __APPLE__
+        result["platform"] = "apple";
+#elif defined __unix__
+        result["platform"] = "unix";
+#else
+        result["platform"] = "unknown";
+#endif
+
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+        result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
+#elif defined(__clang__)
+        result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
+#elif defined(__GNUC__) || defined(__GNUG__)
+        result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
+#elif defined(__HP_cc) || defined(__HP_aCC)
+        result["compiler"] = "hp"
+#elif defined(__IBMCPP__)
+        result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
+#elif defined(_MSC_VER)
+        result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
+#elif defined(__PGI)
+        result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
+#elif defined(__SUNPRO_CC)
+        result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
+#else
+        result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
+#endif
+
+#ifdef __cplusplus
+        result["compiler"]["c++"] = std::to_string(__cplusplus);
+#else
+        result["compiler"]["c++"] = "unknown";
+#endif
+        return result;
+    }
+
+
+    ///////////////////////////
+    // JSON value data types //
+    ///////////////////////////
+
+    /// @name JSON value data types
+    /// The data types to store a JSON value. These types are derived from
+    /// the template arguments passed to class @ref basic_json.
+    /// @{
+
+#if defined(JSON_HAS_CPP_14)
+    // Use transparent comparator if possible, combined with perfect forwarding
+    // on find() and count() calls prevents unnecessary string construction.
+    using object_comparator_t = std::less<>;
+#else
+    using object_comparator_t = std::less<StringType>;
+#endif
+
+    /*!
+    @brief a type for an object
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON objects as follows:
+    > An object is an unordered collection of zero or more name/value pairs,
+    > where a name is a string and a value is a string, number, boolean, null,
+    > object, or array.
+
+    To store objects in C++, a type is defined by the template parameters
+    described below.
+
+    @tparam ObjectType  the container to store objects (e.g., `std::map` or
+    `std::unordered_map`)
+    @tparam StringType the type of the keys or names (e.g., `std::string`).
+    The comparison function `std::less<StringType>` is used to order elements
+    inside the container.
+    @tparam AllocatorType the allocator to use for objects (e.g.,
+    `std::allocator`)
+
+    #### Default type
+
+    With the default values for @a ObjectType (`std::map`), @a StringType
+    (`std::string`), and @a AllocatorType (`std::allocator`), the default
+    value for @a object_t is:
+
+    @code {.cpp}
+    std::map<
+      std::string, // key_type
+      basic_json, // value_type
+      std::less<std::string>, // key_compare
+      std::allocator<std::pair<const std::string, basic_json>> // allocator_type
+    >
+    @endcode
+
+    #### Behavior
+
+    The choice of @a object_t influences the behavior of the JSON class. With
+    the default type, objects have the following behavior:
+
+    - When all names are unique, objects will be interoperable in the sense
+      that all software implementations receiving that object will agree on
+      the name-value mappings.
+    - When the names within an object are not unique, it is unspecified which
+      one of the values for a given key will be chosen. For instance,
+      `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
+      `{"key": 2}`.
+    - Internally, name/value pairs are stored in lexicographical order of the
+      names. Objects will also be serialized (see @ref dump) in this order.
+      For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
+      and serialized as `{"a": 2, "b": 1}`.
+    - When comparing objects, the order of the name/value pairs is irrelevant.
+      This makes objects interoperable in the sense that they will not be
+      affected by these differences. For instance, `{"b": 1, "a": 2}` and
+      `{"a": 2, "b": 1}` will be treated as equal.
+
+    #### Limits
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
+    > An implementation may set limits on the maximum depth of nesting.
+
+    In this class, the object's limit of nesting is not explicitly constrained.
+    However, a maximum depth of nesting may be introduced by the compiler or
+    runtime environment. A theoretical limit can be queried by calling the
+    @ref max_size function of a JSON object.
+
+    #### Storage
+
+    Objects are stored as pointers in a @ref basic_json type. That is, for any
+    access to object values, a pointer of type `object_t*` must be
+    dereferenced.
+
+    @sa see @ref array_t -- type for an array value
+
+    @since version 1.0.0
+
+    @note The order name/value pairs are added to the object is *not*
+    preserved by the library. Therefore, iterating an object may return
+    name/value pairs in a different order than they were originally stored. In
+    fact, keys will be traversed in alphabetical order as `std::map` with
+    `std::less` is used by default. Please note this behavior conforms to [RFC
+    8259](https://tools.ietf.org/html/rfc8259), because any order implements the
+    specified "unordered" nature of JSON objects.
+    */
+    using object_t = ObjectType<StringType,
+          basic_json,
+          object_comparator_t,
+          AllocatorType<std::pair<const StringType,
+          basic_json>>>;
+
+    /*!
+    @brief a type for an array
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON arrays as follows:
+    > An array is an ordered sequence of zero or more values.
+
+    To store objects in C++, a type is defined by the template parameters
+    explained below.
+
+    @tparam ArrayType  container type to store arrays (e.g., `std::vector` or
+    `std::list`)
+    @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
+
+    #### Default type
+
+    With the default values for @a ArrayType (`std::vector`) and @a
+    AllocatorType (`std::allocator`), the default value for @a array_t is:
+
+    @code {.cpp}
+    std::vector<
+      basic_json, // value_type
+      std::allocator<basic_json> // allocator_type
+    >
+    @endcode
+
+    #### Limits
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
+    > An implementation may set limits on the maximum depth of nesting.
+
+    In this class, the array's limit of nesting is not explicitly constrained.
+    However, a maximum depth of nesting may be introduced by the compiler or
+    runtime environment. A theoretical limit can be queried by calling the
+    @ref max_size function of a JSON array.
+
+    #### Storage
+
+    Arrays are stored as pointers in a @ref basic_json type. That is, for any
+    access to array values, a pointer of type `array_t*` must be dereferenced.
+
+    @sa see @ref object_t -- type for an object value
+
+    @since version 1.0.0
+    */
+    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
+
+    /*!
+    @brief a type for a string
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON strings as follows:
+    > A string is a sequence of zero or more Unicode characters.
+
+    To store objects in C++, a type is defined by the template parameter
+    described below. Unicode values are split by the JSON class into
+    byte-sized characters during deserialization.
+
+    @tparam StringType  the container to store strings (e.g., `std::string`).
+    Note this container is used for keys/names in objects, see @ref object_t.
+
+    #### Default type
+
+    With the default values for @a StringType (`std::string`), the default
+    value for @a string_t is:
+
+    @code {.cpp}
+    std::string
+    @endcode
+
+    #### Encoding
+
+    Strings are stored in UTF-8 encoding. Therefore, functions like
+    `std::string::size()` or `std::string::length()` return the number of
+    bytes in the string rather than the number of characters or glyphs.
+
+    #### String comparison
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) states:
+    > Software implementations are typically required to test names of object
+    > members for equality. Implementations that transform the textual
+    > representation into sequences of Unicode code units and then perform the
+    > comparison numerically, code unit by code unit, are interoperable in the
+    > sense that implementations will agree in all cases on equality or
+    > inequality of two strings. For example, implementations that compare
+    > strings with escaped characters unconverted may incorrectly find that
+    > `"a\\b"` and `"a\u005Cb"` are not equal.
+
+    This implementation is interoperable as it does compare strings code unit
+    by code unit.
+
+    #### Storage
+
+    String values are stored as pointers in a @ref basic_json type. That is,
+    for any access to string values, a pointer of type `string_t*` must be
+    dereferenced.
+
+    @since version 1.0.0
+    */
+    using string_t = StringType;
+
+    /*!
+    @brief a type for a boolean
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) implicitly describes a boolean as a
+    type which differentiates the two literals `true` and `false`.
+
+    To store objects in C++, a type is defined by the template parameter @a
+    BooleanType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a BooleanType (`bool`), the default value for
+    @a boolean_t is:
+
+    @code {.cpp}
+    bool
+    @endcode
+
+    #### Storage
+
+    Boolean values are stored directly inside a @ref basic_json type.
+
+    @since version 1.0.0
+    */
+    using boolean_t = BooleanType;
+
+    /*!
+    @brief a type for a number (integer)
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows:
+    > The representation of numbers is similar to that used in most
+    > programming languages. A number is represented in base 10 using decimal
+    > digits. It contains an integer component that may be prefixed with an
+    > optional minus sign, which may be followed by a fraction part and/or an
+    > exponent part. Leading zeros are not allowed. (...) Numeric values that
+    > cannot be represented in the grammar below (such as Infinity and NaN)
+    > are not permitted.
+
+    This description includes both integer and floating-point numbers.
+    However, C++ allows more precise storage if it is known whether the number
+    is a signed integer, an unsigned integer or a floating-point number.
+    Therefore, three different types, @ref number_integer_t, @ref
+    number_unsigned_t and @ref number_float_t are used.
+
+    To store integer numbers in C++, a type is defined by the template
+    parameter @a NumberIntegerType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a NumberIntegerType (`int64_t`), the default
+    value for @a number_integer_t is:
+
+    @code {.cpp}
+    int64_t
+    @endcode
+
+    #### Default behavior
+
+    - The restrictions about leading zeros is not enforced in C++. Instead,
+      leading zeros in integer literals lead to an interpretation as octal
+      number. Internally, the value will be stored as decimal number. For
+      instance, the C++ integer literal `010` will be serialized to `8`.
+      During deserialization, leading zeros yield an error.
+    - Not-a-number (NaN) values will be serialized to `null`.
+
+    #### Limits
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
+    > An implementation may set limits on the range and precision of numbers.
+
+    When the default type is used, the maximal integer number that can be
+    stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
+    that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
+    that are out of range will yield over/underflow when used in a
+    constructor. During deserialization, too large or small integer numbers
+    will be automatically be stored as @ref number_unsigned_t or @ref
+    number_float_t.
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
+    > Note that when such software is used, numbers that are integers and are
+    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+    > that implementations will agree exactly on their numeric values.
+
+    As this range is a subrange of the exactly supported range [INT64_MIN,
+    INT64_MAX], this class's integer type is interoperable.
+
+    #### Storage
+
+    Integer number values are stored directly inside a @ref basic_json type.
+
+    @sa see @ref number_float_t -- type for number values (floating-point)
+
+    @sa see @ref number_unsigned_t -- type for number values (unsigned integer)
+
+    @since version 1.0.0
+    */
+    using number_integer_t = NumberIntegerType;
+
+    /*!
+    @brief a type for a number (unsigned)
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows:
+    > The representation of numbers is similar to that used in most
+    > programming languages. A number is represented in base 10 using decimal
+    > digits. It contains an integer component that may be prefixed with an
+    > optional minus sign, which may be followed by a fraction part and/or an
+    > exponent part. Leading zeros are not allowed. (...) Numeric values that
+    > cannot be represented in the grammar below (such as Infinity and NaN)
+    > are not permitted.
+
+    This description includes both integer and floating-point numbers.
+    However, C++ allows more precise storage if it is known whether the number
+    is a signed integer, an unsigned integer or a floating-point number.
+    Therefore, three different types, @ref number_integer_t, @ref
+    number_unsigned_t and @ref number_float_t are used.
+
+    To store unsigned integer numbers in C++, a type is defined by the
+    template parameter @a NumberUnsignedType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a NumberUnsignedType (`uint64_t`), the
+    default value for @a number_unsigned_t is:
+
+    @code {.cpp}
+    uint64_t
+    @endcode
+
+    #### Default behavior
+
+    - The restrictions about leading zeros is not enforced in C++. Instead,
+      leading zeros in integer literals lead to an interpretation as octal
+      number. Internally, the value will be stored as decimal number. For
+      instance, the C++ integer literal `010` will be serialized to `8`.
+      During deserialization, leading zeros yield an error.
+    - Not-a-number (NaN) values will be serialized to `null`.
+
+    #### Limits
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
+    > An implementation may set limits on the range and precision of numbers.
+
+    When the default type is used, the maximal integer number that can be
+    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
+    number that can be stored is `0`. Integer numbers that are out of range
+    will yield over/underflow when used in a constructor. During
+    deserialization, too large or small integer numbers will be automatically
+    be stored as @ref number_integer_t or @ref number_float_t.
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
+    > Note that when such software is used, numbers that are integers and are
+    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+    > that implementations will agree exactly on their numeric values.
+
+    As this range is a subrange (when considered in conjunction with the
+    number_integer_t type) of the exactly supported range [0, UINT64_MAX],
+    this class's integer type is interoperable.
+
+    #### Storage
+
+    Integer number values are stored directly inside a @ref basic_json type.
+
+    @sa see @ref number_float_t -- type for number values (floating-point)
+    @sa see @ref number_integer_t -- type for number values (integer)
+
+    @since version 2.0.0
+    */
+    using number_unsigned_t = NumberUnsignedType;
+
+    /*!
+    @brief a type for a number (floating-point)
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows:
+    > The representation of numbers is similar to that used in most
+    > programming languages. A number is represented in base 10 using decimal
+    > digits. It contains an integer component that may be prefixed with an
+    > optional minus sign, which may be followed by a fraction part and/or an
+    > exponent part. Leading zeros are not allowed. (...) Numeric values that
+    > cannot be represented in the grammar below (such as Infinity and NaN)
+    > are not permitted.
+
+    This description includes both integer and floating-point numbers.
+    However, C++ allows more precise storage if it is known whether the number
+    is a signed integer, an unsigned integer or a floating-point number.
+    Therefore, three different types, @ref number_integer_t, @ref
+    number_unsigned_t and @ref number_float_t are used.
+
+    To store floating-point numbers in C++, a type is defined by the template
+    parameter @a NumberFloatType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a NumberFloatType (`double`), the default
+    value for @a number_float_t is:
+
+    @code {.cpp}
+    double
+    @endcode
+
+    #### Default behavior
+
+    - The restrictions about leading zeros is not enforced in C++. Instead,
+      leading zeros in floating-point literals will be ignored. Internally,
+      the value will be stored as decimal number. For instance, the C++
+      floating-point literal `01.2` will be serialized to `1.2`. During
+      deserialization, leading zeros yield an error.
+    - Not-a-number (NaN) values will be serialized to `null`.
+
+    #### Limits
+
+    [RFC 8259](https://tools.ietf.org/html/rfc8259) states:
+    > This specification allows implementations to set limits on the range and
+    > precision of numbers accepted. Since software that implements IEEE
+    > 754-2008 binary64 (double precision) numbers is generally available and
+    > widely used, good interoperability can be achieved by implementations
+    > that expect no more precision or range than these provide, in the sense
+    > that implementations will approximate JSON numbers within the expected
+    > precision.
+
+    This implementation does exactly follow this approach, as it uses double
+    precision floating-point numbers. Note values smaller than
+    `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
+    will be stored as NaN internally and be serialized to `null`.
+
+    #### Storage
+
+    Floating-point number values are stored directly inside a @ref basic_json
+    type.
+
+    @sa see @ref number_integer_t -- type for number values (integer)
+
+    @sa see @ref number_unsigned_t -- type for number values (unsigned integer)
+
+    @since version 1.0.0
+    */
+    using number_float_t = NumberFloatType;
+
+    /*!
+    @brief a type for a packed binary type
+
+    This type is a type designed to carry binary data that appears in various
+    serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and
+    BSON's generic binary subtype. This type is NOT a part of standard JSON and
+    exists solely for compatibility with these binary types. As such, it is
+    simply defined as an ordered sequence of zero or more byte values.
+
+    Additionally, as an implementation detail, the subtype of the binary data is
+    carried around as a `std::uint8_t`, which is compatible with both of the
+    binary data formats that use binary subtyping, (though the specific
+    numbering is incompatible with each other, and it is up to the user to
+    translate between them).
+
+    [CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type
+    as:
+    > Major type 2: a byte string. The string's length in bytes is represented
+    > following the rules for positive integers (major type 0).
+
+    [MessagePack's documentation on the bin type
+    family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family)
+    describes this type as:
+    > Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes
+    > in addition to the size of the byte array.
+
+    [BSON's specifications](http://bsonspec.org/spec.html) describe several
+    binary types; however, this type is intended to represent the generic binary
+    type which has the description:
+    > Generic binary subtype - This is the most commonly used binary subtype and
+    > should be the 'default' for drivers and tools.
+
+    None of these impose any limitations on the internal representation other
+    than the basic unit of storage be some type of array whose parts are
+    decomposable into bytes.
+
+    The default representation of this binary format is a
+    `std::vector<std::uint8_t>`, which is a very common way to represent a byte
+    array in modern C++.
+
+    #### Default type
+
+    The default values for @a BinaryType is `std::vector<std::uint8_t>`
+
+    #### Storage
+
+    Binary Arrays are stored as pointers in a @ref basic_json type. That is,
+    for any access to array values, a pointer of the type `binary_t*` must be
+    dereferenced.
+
+    #### Notes on subtypes
+
+    - CBOR
+       - Binary values are represented as byte strings. Subtypes are serialized
+         as tagged values.
+    - MessagePack
+       - If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
+         or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
+         is used. For other sizes, the ext family (ext8, ext16, ext32) is used.
+         The subtype is then added as signed 8-bit integer.
+       - If no subtype is given, the bin family (bin8, bin16, bin32) is used.
+    - BSON
+       - If a subtype is given, it is used and added as unsigned 8-bit integer.
+       - If no subtype is given, the generic binary subtype 0x00 is used.
+
+    @sa see @ref binary -- create a binary array
+
+    @since version 3.8.0
+    */
+    using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
+    /// @}
+
+  private:
+
+    /// helper for exception-safe object creation
+    template<typename T, typename... Args>
+    JSON_HEDLEY_RETURNS_NON_NULL
+    static T* create(Args&& ... args)
+    {
+        AllocatorType<T> alloc;
+        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
+
+        auto deleter = [&](T * obj)
+        {
+            AllocatorTraits::deallocate(alloc, obj, 1);
+        };
+        std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
+        AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
+        JSON_ASSERT(obj != nullptr);
+        return obj.release();
+    }
+
+    ////////////////////////
+    // JSON value storage //
+    ////////////////////////
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    /*!
+    @brief a JSON value
+
+    The actual storage for a JSON value of the @ref basic_json class. This
+    union combines the different storage types for the JSON value types
+    defined in @ref value_t.
+
+    JSON type | value_t type    | used type
+    --------- | --------------- | ------------------------
+    object    | object          | pointer to @ref object_t
+    array     | array           | pointer to @ref array_t
+    string    | string          | pointer to @ref string_t
+    boolean   | boolean         | @ref boolean_t
+    number    | number_integer  | @ref number_integer_t
+    number    | number_unsigned | @ref number_unsigned_t
+    number    | number_float    | @ref number_float_t
+    binary    | binary          | pointer to @ref binary_t
+    null      | null            | *no value is stored*
+
+    @note Variable-length types (objects, arrays, and strings) are stored as
+    pointers. The size of the union should not exceed 64 bits if the default
+    value types are used.
+
+    @since version 1.0.0
+    */
+    union json_value
+    {
+        /// object (stored with pointer to save storage)
+        object_t* object;
+        /// array (stored with pointer to save storage)
+        array_t* array;
+        /// string (stored with pointer to save storage)
+        string_t* string;
+        /// binary (stored with pointer to save storage)
+        binary_t* binary;
+        /// boolean
+        boolean_t boolean;
+        /// number (integer)
+        number_integer_t number_integer;
+        /// number (unsigned integer)
+        number_unsigned_t number_unsigned;
+        /// number (floating-point)
+        number_float_t number_float;
+
+        /// default constructor (for null values)
+        json_value() = default;
+        /// constructor for booleans
+        json_value(boolean_t v) noexcept : boolean(v) {}
+        /// constructor for numbers (integer)
+        json_value(number_integer_t v) noexcept : number_integer(v) {}
+        /// constructor for numbers (unsigned)
+        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
+        /// constructor for numbers (floating-point)
+        json_value(number_float_t v) noexcept : number_float(v) {}
+        /// constructor for empty values of a given type
+        json_value(value_t t)
+        {
+            switch (t)
+            {
+                case value_t::object:
+                {
+                    object = create<object_t>();
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    array = create<array_t>();
+                    break;
+                }
+
+                case value_t::string:
+                {
+                    string = create<string_t>("");
+                    break;
+                }
+
+                case value_t::binary:
+                {
+                    binary = create<binary_t>();
+                    break;
+                }
+
+                case value_t::boolean:
+                {
+                    boolean = boolean_t(false);
+                    break;
+                }
+
+                case value_t::number_integer:
+                {
+                    number_integer = number_integer_t(0);
+                    break;
+                }
+
+                case value_t::number_unsigned:
+                {
+                    number_unsigned = number_unsigned_t(0);
+                    break;
+                }
+
+                case value_t::number_float:
+                {
+                    number_float = number_float_t(0.0);
+                    break;
+                }
+
+                case value_t::null:
+                {
+                    object = nullptr;  // silence warning, see #821
+                    break;
+                }
+
+                case value_t::discarded:
+                default:
+                {
+                    object = nullptr;  // silence warning, see #821
+                    if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
+                    {
+                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.4", basic_json())); // LCOV_EXCL_LINE
+                    }
+                    break;
+                }
+            }
+        }
+
+        /// constructor for strings
+        json_value(const string_t& value) : string(create<string_t>(value)) {}
+
+        /// constructor for rvalue strings
+        json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
+
+        /// constructor for objects
+        json_value(const object_t& value) : object(create<object_t>(value)) {}
+
+        /// constructor for rvalue objects
+        json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
+
+        /// constructor for arrays
+        json_value(const array_t& value) : array(create<array_t>(value)) {}
+
+        /// constructor for rvalue arrays
+        json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
+
+        /// constructor for binary arrays
+        json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
+
+        /// constructor for rvalue binary arrays
+        json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
+
+        /// constructor for binary arrays (internal type)
+        json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
+
+        /// constructor for rvalue binary arrays (internal type)
+        json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
+
+        void destroy(value_t t)
+        {
+            if (t == value_t::array || t == value_t::object)
+            {
+                // flatten the current json_value to a heap-allocated stack
+                std::vector<basic_json> stack;
+
+                // move the top-level items to stack
+                if (t == value_t::array)
+                {
+                    stack.reserve(array->size());
+                    std::move(array->begin(), array->end(), std::back_inserter(stack));
+                }
+                else
+                {
+                    stack.reserve(object->size());
+                    for (auto&& it : *object)
+                    {
+                        stack.push_back(std::move(it.second));
+                    }
+                }
+
+                while (!stack.empty())
+                {
+                    // move the last item to local variable to be processed
+                    basic_json current_item(std::move(stack.back()));
+                    stack.pop_back();
+
+                    // if current_item is array/object, move
+                    // its children to the stack to be processed later
+                    if (current_item.is_array())
+                    {
+                        std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
+
+                        current_item.m_value.array->clear();
+                    }
+                    else if (current_item.is_object())
+                    {
+                        for (auto&& it : *current_item.m_value.object)
+                        {
+                            stack.push_back(std::move(it.second));
+                        }
+
+                        current_item.m_value.object->clear();
+                    }
+
+                    // it's now safe that current_item get destructed
+                    // since it doesn't have any children
+                }
+            }
+
+            switch (t)
+            {
+                case value_t::object:
+                {
+                    AllocatorType<object_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    AllocatorType<array_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
+                    break;
+                }
+
+                case value_t::string:
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
+                    break;
+                }
+
+                case value_t::binary:
+                {
+                    AllocatorType<binary_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
+                    break;
+                }
+
+                case value_t::null:
+                case value_t::boolean:
+                case value_t::number_integer:
+                case value_t::number_unsigned:
+                case value_t::number_float:
+                case value_t::discarded:
+                default:
+                {
+                    break;
+                }
+            }
+        }
+    };
+
+  private:
+    /*!
+    @brief checks the class invariants
+
+    This function asserts the class invariants. It needs to be called at the
+    end of every constructor to make sure that created objects respect the
+    invariant. Furthermore, it has to be called each time the type of a JSON
+    value is changed, because the invariant expresses a relationship between
+    @a m_type and @a m_value.
+
+    Furthermore, the parent relation is checked for arrays and objects: If
+    @a check_parents true and the value is an array or object, then the
+    container's elements must have the current value as parent.
+
+    @param[in] check_parents  whether the parent relation should be checked.
+               The value is true by default and should only be set to false
+               during destruction of objects when the invariant does not
+               need to hold.
+    */
+    void assert_invariant(bool check_parents = true) const noexcept
+    {
+        JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
+        JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
+        JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
+        JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
+
+#if JSON_DIAGNOSTICS
+        JSON_TRY
+        {
+            // cppcheck-suppress assertWithSideEffect
+            JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
+            {
+                return j.m_parent == this;
+            }));
+        }
+        JSON_CATCH(...) {} // LCOV_EXCL_LINE
+#endif
+        static_cast<void>(check_parents);
+    }
+
+    void set_parents()
+    {
+#if JSON_DIAGNOSTICS
+        switch (m_type)
+        {
+            case value_t::array:
+            {
+                for (auto& element : *m_value.array)
+                {
+                    element.m_parent = this;
+                }
+                break;
+            }
+
+            case value_t::object:
+            {
+                for (auto& element : *m_value.object)
+                {
+                    element.second.m_parent = this;
+                }
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                break;
+        }
+#endif
+    }
+
+    iterator set_parents(iterator it, typename iterator::difference_type count)
+    {
+#if JSON_DIAGNOSTICS
+        for (typename iterator::difference_type i = 0; i < count; ++i)
+        {
+            (it + i)->m_parent = this;
+        }
+#else
+        static_cast<void>(count);
+#endif
+        return it;
+    }
+
+    reference set_parent(reference j, std::size_t old_capacity = std::size_t(-1))
+    {
+#if JSON_DIAGNOSTICS
+        if (old_capacity != std::size_t(-1))
+        {
+            // see https://github.com/nlohmann/json/issues/2838
+            JSON_ASSERT(type() == value_t::array);
+            if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
+            {
+                // capacity has changed: update all parents
+                set_parents();
+                return j;
+            }
+        }
+
+        // ordered_json uses a vector internally, so pointers could have
+        // been invalidated; see https://github.com/nlohmann/json/issues/2962
+#ifdef JSON_HEDLEY_MSVC_VERSION
+#pragma warning(push )
+#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
+#endif
+        if (detail::is_ordered_map<object_t>::value)
+        {
+            set_parents();
+            return j;
+        }
+#ifdef JSON_HEDLEY_MSVC_VERSION
+#pragma warning( pop )
+#endif
+
+        j.m_parent = this;
+#else
+        static_cast<void>(j);
+        static_cast<void>(old_capacity);
+#endif
+        return j;
+    }
+
+  public:
+    //////////////////////////
+    // JSON parser callback //
+    //////////////////////////
+
+    /*!
+    @brief parser event types
+
+    The parser callback distinguishes the following events:
+    - `object_start`: the parser read `{` and started to process a JSON object
+    - `key`: the parser read a key of a value in an object
+    - `object_end`: the parser read `}` and finished processing a JSON object
+    - `array_start`: the parser read `[` and started to process a JSON array
+    - `array_end`: the parser read `]` and finished processing a JSON array
+    - `value`: the parser finished reading a JSON value
+
+    @image html callback_events.png "Example when certain parse events are triggered"
+
+    @sa see @ref parser_callback_t for more information and examples
+    */
+    using parse_event_t = detail::parse_event_t;
+
+    /*!
+    @brief per-element parser callback type
+
+    With a parser callback function, the result of parsing a JSON text can be
+    influenced. When passed to @ref parse, it is called on certain events
+    (passed as @ref parse_event_t via parameter @a event) with a set recursion
+    depth @a depth and context JSON value @a parsed. The return value of the
+    callback function is a boolean indicating whether the element that emitted
+    the callback shall be kept or not.
+
+    We distinguish six scenarios (determined by the event type) in which the
+    callback function can be called. The following table describes the values
+    of the parameters @a depth, @a event, and @a parsed.
+
+    parameter @a event | description | parameter @a depth | parameter @a parsed
+    ------------------ | ----------- | ------------------ | -------------------
+    parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
+    parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
+    parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
+    parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
+    parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
+    parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
+
+    @image html callback_events.png "Example when certain parse events are triggered"
+
+    Discarding a value (i.e., returning `false`) has different effects
+    depending on the context in which function was called:
+
+    - Discarded values in structured types are skipped. That is, the parser
+      will behave as if the discarded value was never read.
+    - In case a value outside a structured type is skipped, it is replaced
+      with `null`. This case happens if the top-level element is skipped.
+
+    @param[in] depth  the depth of the recursion during parsing
+
+    @param[in] event  an event of type parse_event_t indicating the context in
+    the callback function has been called
+
+    @param[in,out] parsed  the current intermediate parse result; note that
+    writing to this value has no effect for parse_event_t::key events
+
+    @return Whether the JSON value which called the function during parsing
+    should be kept (`true`) or not (`false`). In the latter case, it is either
+    skipped completely or replaced by an empty discarded object.
+
+    @sa see @ref parse for examples
+
+    @since version 1.0.0
+    */
+    using parser_callback_t = detail::parser_callback_t<basic_json>;
+
+    //////////////////
+    // constructors //
+    //////////////////
+
+    /// @name constructors and destructors
+    /// Constructors of class @ref basic_json, copy/move constructor, copy
+    /// assignment, static functions creating objects, and the destructor.
+    /// @{
+
+    /*!
+    @brief create an empty value with a given type
+
+    Create an empty JSON value with a given type. The value will be default
+    initialized with an empty value which depends on the type:
+
+    Value type  | initial value
+    ----------- | -------------
+    null        | `null`
+    boolean     | `false`
+    string      | `""`
+    number      | `0`
+    object      | `{}`
+    array       | `[]`
+    binary      | empty array
+
+    @param[in] v  the type of the value to create
+
+    @complexity Constant.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The following code shows the constructor for different @ref
+    value_t values,basic_json__value_t}
+
+    @sa see @ref clear() -- restores the postcondition of this constructor
+
+    @since version 1.0.0
+    */
+    basic_json(const value_t v)
+        : m_type(v), m_value(v)
+    {
+        assert_invariant();
+    }
+
+    /*!
+    @brief create a null object
+
+    Create a `null` JSON value. It either takes a null pointer as parameter
+    (explicitly creating `null`) or no parameter (implicitly creating `null`).
+    The passed null pointer itself is not read -- it is only used to choose
+    the right constructor.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this constructor never throws
+    exceptions.
+
+    @liveexample{The following code shows the constructor with and without a
+    null pointer parameter.,basic_json__nullptr_t}
+
+    @since version 1.0.0
+    */
+    basic_json(std::nullptr_t = nullptr) noexcept
+        : basic_json(value_t::null)
+    {
+        assert_invariant();
+    }
+
+    /*!
+    @brief create a JSON value
+
+    This is a "catch all" constructor for all compatible JSON types; that is,
+    types for which a `to_json()` method exists. The constructor forwards the
+    parameter @a val to that method (to `json_serializer<U>::to_json` method
+    with `U = uncvref_t<CompatibleType>`, to be exact).
+
+    Template type @a CompatibleType includes, but is not limited to, the
+    following types:
+    - **arrays**: @ref array_t and all kinds of compatible containers such as
+      `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
+      `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
+      `std::multiset`, and `std::unordered_multiset` with a `value_type` from
+      which a @ref basic_json value can be constructed.
+    - **objects**: @ref object_t and all kinds of compatible associative
+      containers such as `std::map`, `std::unordered_map`, `std::multimap`,
+      and `std::unordered_multimap` with a `key_type` compatible to
+      @ref string_t and a `value_type` from which a @ref basic_json value can
+      be constructed.
+    - **strings**: @ref string_t, string literals, and all compatible string
+      containers can be used.
+    - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
+      @ref number_float_t, and all convertible number types such as `int`,
+      `size_t`, `int64_t`, `float` or `double` can be used.
+    - **boolean**: @ref boolean_t / `bool` can be used.
+    - **binary**: @ref binary_t / `std::vector<std::uint8_t>` may be used,
+      unfortunately because string literals cannot be distinguished from binary
+      character arrays by the C++ type system, all types compatible with `const
+      char*` will be directed to the string constructor instead.  This is both
+      for backwards compatibility, and due to the fact that a binary type is not
+      a standard JSON type.
+
+    See the examples below.
+
+    @tparam CompatibleType a type such that:
+    - @a CompatibleType is not derived from `std::istream`,
+    - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
+         constructors),
+    - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
+    - @a CompatibleType is not a @ref basic_json nested type (e.g.,
+         @ref json_pointer, @ref iterator, etc ...)
+    - `json_serializer<U>` has a `to_json(basic_json_t&, CompatibleType&&)` method
+
+    @tparam U = `uncvref_t<CompatibleType>`
+
+    @param[in] val the value to be forwarded to the respective constructor
+
+    @complexity Usually linear in the size of the passed @a val, also
+                depending on the implementation of the called `to_json()`
+                method.
+
+    @exceptionsafety Depends on the called constructor. For types directly
+    supported by the library (i.e., all types for which no `to_json()` function
+    was provided), strong guarantee holds: if an exception is thrown, there are
+    no changes to any JSON value.
+
+    @liveexample{The following code shows the constructor with several
+    compatible types.,basic_json__CompatibleType}
+
+    @since version 2.1.0
+    */
+    template < typename CompatibleType,
+               typename U = detail::uncvref_t<CompatibleType>,
+               detail::enable_if_t <
+                   !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
+    basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
+                JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
+                                           std::forward<CompatibleType>(val))))
+    {
+        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
+        set_parents();
+        assert_invariant();
+    }
+
+    /*!
+    @brief create a JSON value from an existing one
+
+    This is a constructor for existing @ref basic_json types.
+    It does not hijack copy/move constructors, since the parameter has different
+    template arguments than the current ones.
+
+    The constructor tries to convert the internal @ref m_value of the parameter.
+
+    @tparam BasicJsonType a type such that:
+    - @a BasicJsonType is a @ref basic_json type.
+    - @a BasicJsonType has different template arguments than @ref basic_json_t.
+
+    @param[in] val the @ref basic_json value to be converted.
+
+    @complexity Usually linear in the size of the passed @a val, also
+                depending on the implementation of the called `to_json()`
+                method.
+
+    @exceptionsafety Depends on the called constructor. For types directly
+    supported by the library (i.e., all types for which no `to_json()` function
+    was provided), strong guarantee holds: if an exception is thrown, there are
+    no changes to any JSON value.
+
+    @since version 3.2.0
+    */
+    template < typename BasicJsonType,
+               detail::enable_if_t <
+                   detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
+    basic_json(const BasicJsonType& val)
+    {
+        using other_boolean_t = typename BasicJsonType::boolean_t;
+        using other_number_float_t = typename BasicJsonType::number_float_t;
+        using other_number_integer_t = typename BasicJsonType::number_integer_t;
+        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+        using other_string_t = typename BasicJsonType::string_t;
+        using other_object_t = typename BasicJsonType::object_t;
+        using other_array_t = typename BasicJsonType::array_t;
+        using other_binary_t = typename BasicJsonType::binary_t;
+
+        switch (val.type())
+        {
+            case value_t::boolean:
+                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
+                break;
+            case value_t::number_float:
+                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
+                break;
+            case value_t::number_integer:
+                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
+                break;
+            case value_t::number_unsigned:
+                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
+                break;
+            case value_t::string:
+                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
+                break;
+            case value_t::object:
+                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
+                break;
+            case value_t::array:
+                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
+                break;
+            case value_t::binary:
+                JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
+                break;
+            case value_t::null:
+                *this = nullptr;
+                break;
+            case value_t::discarded:
+                m_type = value_t::discarded;
+                break;
+            default:            // LCOV_EXCL_LINE
+                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+        }
+        set_parents();
+        assert_invariant();
+    }
+
+    /*!
+    @brief create a container (array or object) from an initializer list
+
+    Creates a JSON value of type array or object from the passed initializer
+    list @a init. In case @a type_deduction is `true` (default), the type of
+    the JSON value to be created is deducted from the initializer list @a init
+    according to the following rules:
+
+    1. If the list is empty, an empty JSON object value `{}` is created.
+    2. If the list consists of pairs whose first element is a string, a JSON
+       object value is created where the first elements of the pairs are
+       treated as keys and the second elements are as values.
+    3. In all other cases, an array is created.
+
+    The rules aim to create the best fit between a C++ initializer list and
+    JSON values. The rationale is as follows:
+
+    1. The empty initializer list is written as `{}` which is exactly an empty
+       JSON object.
+    2. C++ has no way of describing mapped types other than to list a list of
+       pairs. As JSON requires that keys must be of type string, rule 2 is the
+       weakest constraint one can pose on initializer lists to interpret them
+       as an object.
+    3. In all other cases, the initializer list could not be interpreted as
+       JSON object type, so interpreting it as JSON array type is safe.
+
+    With the rules described above, the following JSON values cannot be
+    expressed by an initializer list:
+
+    - the empty array (`[]`): use @ref array(initializer_list_t)
+      with an empty initializer list in this case
+    - arrays whose elements satisfy rule 2: use @ref
+      array(initializer_list_t) with the same initializer list
+      in this case
+
+    @note When used without parentheses around an empty initializer list, @ref
+    basic_json() is called instead of this function, yielding the JSON null
+    value.
+
+    @param[in] init  initializer list with JSON values
+
+    @param[in] type_deduction internal parameter; when set to `true`, the type
+    of the JSON value is deducted from the initializer list @a init; when set
+    to `false`, the type provided via @a manual_type is forced. This mode is
+    used by the functions @ref array(initializer_list_t) and
+    @ref object(initializer_list_t).
+
+    @param[in] manual_type internal parameter; when @a type_deduction is set
+    to `false`, the created JSON value will use the provided type (only @ref
+    value_t::array and @ref value_t::object are valid); when @a type_deduction
+    is set to `true`, this parameter has no effect
+
+    @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
+    `value_t::object`, but @a init contains an element which is not a pair
+    whose first element is a string. In this case, the constructor could not
+    create an object. If @a type_deduction would have be `true`, an array
+    would have been created. See @ref object(initializer_list_t)
+    for an example.
+
+    @complexity Linear in the size of the initializer list @a init.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The example below shows how JSON values are created from
+    initializer lists.,basic_json__list_init_t}
+
+    @sa see @ref array(initializer_list_t) -- create a JSON array
+    value from an initializer list
+    @sa see @ref object(initializer_list_t) -- create a JSON object
+    value from an initializer list
+
+    @since version 1.0.0
+    */
+    basic_json(initializer_list_t init,
+               bool type_deduction = true,
+               value_t manual_type = value_t::array)
+    {
+        // check if each element is an array with two elements whose first
+        // element is a string
+        bool is_an_object = std::all_of(init.begin(), init.end(),
+                                        [](const detail::json_ref<basic_json>& element_ref)
+        {
+            return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
+        });
+
+        // adjust type if type deduction is not wanted
+        if (!type_deduction)
+        {
+            // if array is wanted, do not create an object though possible
+            if (manual_type == value_t::array)
+            {
+                is_an_object = false;
+            }
+
+            // if object is wanted but impossible, throw an exception
+            if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
+            {
+                JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
+            }
+        }
+
+        if (is_an_object)
+        {
+            // the initializer list is a list of pairs -> create object
+            m_type = value_t::object;
+            m_value = value_t::object;
+
+            for (auto& element_ref : init)
+            {
+                auto element = element_ref.moved_or_copied();
+                m_value.object->emplace(
+                    std::move(*((*element.m_value.array)[0].m_value.string)),
+                    std::move((*element.m_value.array)[1]));
+            }
+        }
+        else
+        {
+            // the initializer list describes an array -> create array
+            m_type = value_t::array;
+            m_value.array = create<array_t>(init.begin(), init.end());
+        }
+
+        set_parents();
+        assert_invariant();
+    }
+
+    /*!
+    @brief explicitly create a binary array (without subtype)
+
+    Creates a JSON binary array value from a given binary container. Binary
+    values are part of various binary formats, such as CBOR, MessagePack, and
+    BSON. This constructor is used to create a value for serialization to those
+    formats.
+
+    @note Note, this function exists because of the difficulty in correctly
+    specifying the correct template overload in the standard value ctor, as both
+    JSON arrays and JSON binary arrays are backed with some form of a
+    `std::vector`. Because JSON binary arrays are a non-standard extension it
+    was decided that it would be best to prevent automatic initialization of a
+    binary array type, for backwards compatibility and so it does not happen on
+    accident.
+
+    @param[in] init container containing bytes to use as binary type
+
+    @return JSON binary array value
+
+    @complexity Linear in the size of @a init.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @since version 3.8.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json binary(const typename binary_t::container_type& init)
+    {
+        auto res = basic_json();
+        res.m_type = value_t::binary;
+        res.m_value = init;
+        return res;
+    }
+
+    /*!
+    @brief explicitly create a binary array (with subtype)
+
+    Creates a JSON binary array value from a given binary container. Binary
+    values are part of various binary formats, such as CBOR, MessagePack, and
+    BSON. This constructor is used to create a value for serialization to those
+    formats.
+
+    @note Note, this function exists because of the difficulty in correctly
+    specifying the correct template overload in the standard value ctor, as both
+    JSON arrays and JSON binary arrays are backed with some form of a
+    `std::vector`. Because JSON binary arrays are a non-standard extension it
+    was decided that it would be best to prevent automatic initialization of a
+    binary array type, for backwards compatibility and so it does not happen on
+    accident.
+
+    @param[in] init container containing bytes to use as binary type
+    @param[in] subtype subtype to use in MessagePack and BSON
+
+    @return JSON binary array value
+
+    @complexity Linear in the size of @a init.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @since version 3.8.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
+    {
+        auto res = basic_json();
+        res.m_type = value_t::binary;
+        res.m_value = binary_t(init, subtype);
+        return res;
+    }
+
+    /// @copydoc binary(const typename binary_t::container_type&)
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json binary(typename binary_t::container_type&& init)
+    {
+        auto res = basic_json();
+        res.m_type = value_t::binary;
+        res.m_value = std::move(init);
+        return res;
+    }
+
+    /// @copydoc binary(const typename binary_t::container_type&, typename binary_t::subtype_type)
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
+    {
+        auto res = basic_json();
+        res.m_type = value_t::binary;
+        res.m_value = binary_t(std::move(init), subtype);
+        return res;
+    }
+
+    /*!
+    @brief explicitly create an array from an initializer list
+
+    Creates a JSON array value from a given initializer list. That is, given a
+    list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
+    initializer list is empty, the empty array `[]` is created.
+
+    @note This function is only needed to express two edge cases that cannot
+    be realized with the initializer list constructor (@ref
+    basic_json(initializer_list_t, bool, value_t)). These cases
+    are:
+    1. creating an array whose elements are all pairs whose first element is a
+    string -- in this case, the initializer list constructor would create an
+    object, taking the first elements as keys
+    2. creating an empty array -- passing the empty initializer list to the
+    initializer list constructor yields an empty object
+
+    @param[in] init  initializer list with JSON values to create an array from
+    (optional)
+
+    @return JSON array value
+
+    @complexity Linear in the size of @a init.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The following code shows an example for the `array`
+    function.,array}
+
+    @sa see @ref basic_json(initializer_list_t, bool, value_t) --
+    create a JSON value from an initializer list
+    @sa see @ref object(initializer_list_t) -- create a JSON object
+    value from an initializer list
+
+    @since version 1.0.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json array(initializer_list_t init = {})
+    {
+        return basic_json(init, false, value_t::array);
+    }
+
+    /*!
+    @brief explicitly create an object from an initializer list
+
+    Creates a JSON object value from a given initializer list. The initializer
+    lists elements must be pairs, and their first elements must be strings. If
+    the initializer list is empty, the empty object `{}` is created.
+
+    @note This function is only added for symmetry reasons. In contrast to the
+    related function @ref array(initializer_list_t), there are
+    no cases which can only be expressed by this function. That is, any
+    initializer list @a init can also be passed to the initializer list
+    constructor @ref basic_json(initializer_list_t, bool, value_t).
+
+    @param[in] init  initializer list to create an object from (optional)
+
+    @return JSON object value
+
+    @throw type_error.301 if @a init is not a list of pairs whose first
+    elements are strings. In this case, no object can be created. When such a
+    value is passed to @ref basic_json(initializer_list_t, bool, value_t),
+    an array would have been created from the passed initializer list @a init.
+    See example below.
+
+    @complexity Linear in the size of @a init.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The following code shows an example for the `object`
+    function.,object}
+
+    @sa see @ref basic_json(initializer_list_t, bool, value_t) --
+    create a JSON value from an initializer list
+    @sa see @ref array(initializer_list_t) -- create a JSON array
+    value from an initializer list
+
+    @since version 1.0.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json object(initializer_list_t init = {})
+    {
+        return basic_json(init, false, value_t::object);
+    }
+
+    /*!
+    @brief construct an array with count copies of given value
+
+    Constructs a JSON array value by creating @a cnt copies of a passed value.
+    In case @a cnt is `0`, an empty array is created.
+
+    @param[in] cnt  the number of JSON copies of @a val to create
+    @param[in] val  the JSON value to copy
+
+    @post `std::distance(begin(),end()) == cnt` holds.
+
+    @complexity Linear in @a cnt.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The following code shows examples for the @ref
+    basic_json(size_type\, const basic_json&)
+    constructor.,basic_json__size_type_basic_json}
+
+    @since version 1.0.0
+    */
+    basic_json(size_type cnt, const basic_json& val)
+        : m_type(value_t::array)
+    {
+        m_value.array = create<array_t>(cnt, val);
+        set_parents();
+        assert_invariant();
+    }
+
+    /*!
+    @brief construct a JSON container given an iterator range
+
+    Constructs the JSON value with the contents of the range `[first, last)`.
+    The semantics depends on the different types a JSON value can have:
+    - In case of a null type, invalid_iterator.206 is thrown.
+    - In case of other primitive types (number, boolean, or string), @a first
+      must be `begin()` and @a last must be `end()`. In this case, the value is
+      copied. Otherwise, invalid_iterator.204 is thrown.
+    - In case of structured types (array, object), the constructor behaves as
+      similar versions for `std::vector` or `std::map`; that is, a JSON array
+      or object is constructed from the values in the range.
+
+    @tparam InputIT an input iterator type (@ref iterator or @ref
+    const_iterator)
+
+    @param[in] first begin of the range to copy from (included)
+    @param[in] last end of the range to copy from (excluded)
+
+    @pre Iterators @a first and @a last must be initialized. **This
+         precondition is enforced with an assertion (see warning).** If
+         assertions are switched off, a violation of this precondition yields
+         undefined behavior.
+
+    @pre Range `[first, last)` is valid. Usually, this precondition cannot be
+         checked efficiently. Only certain edge cases are detected; see the
+         description of the exceptions below. A violation of this precondition
+         yields undefined behavior.
+
+    @warning A precondition is enforced with a runtime assertion that will
+             result in calling `std::abort` if this precondition is not met.
+             Assertions can be disabled by defining `NDEBUG` at compile time.
+             See https://en.cppreference.com/w/cpp/error/assert for more
+             information.
+
+    @throw invalid_iterator.201 if iterators @a first and @a last are not
+    compatible (i.e., do not belong to the same JSON value). In this case,
+    the range `[first, last)` is undefined.
+    @throw invalid_iterator.204 if iterators @a first and @a last belong to a
+    primitive type (number, boolean, or string), but @a first does not point
+    to the first element any more. In this case, the range `[first, last)` is
+    undefined. See example code below.
+    @throw invalid_iterator.206 if iterators @a first and @a last belong to a
+    null value. In this case, the range `[first, last)` is undefined.
+
+    @complexity Linear in distance between @a first and @a last.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The example below shows several ways to create JSON values by
+    specifying a subrange with iterators.,basic_json__InputIt_InputIt}
+
+    @since version 1.0.0
+    */
+    template < class InputIT, typename std::enable_if <
+                   std::is_same<InputIT, typename basic_json_t::iterator>::value ||
+                   std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
+    basic_json(InputIT first, InputIT last)
+    {
+        JSON_ASSERT(first.m_object != nullptr);
+        JSON_ASSERT(last.m_object != nullptr);
+
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
+        }
+
+        // copy type from first iterator
+        m_type = first.m_object->m_type;
+
+        // check if iterator range is complete for primitive values
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            {
+                if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
+                                         || !last.m_it.primitive_iterator.is_end()))
+                {
+                    JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
+                }
+                break;
+            }
+
+            case value_t::null:
+            case value_t::object:
+            case value_t::array:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+                break;
+        }
+
+        switch (m_type)
+        {
+            case value_t::number_integer:
+            {
+                m_value.number_integer = first.m_object->m_value.number_integer;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value.number_unsigned = first.m_object->m_value.number_unsigned;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value.number_float = first.m_object->m_value.number_float;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value.boolean = first.m_object->m_value.boolean;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value = *first.m_object->m_value.string;
+                break;
+            }
+
+            case value_t::object:
+            {
+                m_value.object = create<object_t>(first.m_it.object_iterator,
+                                                  last.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value.array = create<array_t>(first.m_it.array_iterator,
+                                                last.m_it.array_iterator);
+                break;
+            }
+
+            case value_t::binary:
+            {
+                m_value = *first.m_object->m_value.binary;
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
+        }
+
+        set_parents();
+        assert_invariant();
+    }
+
+
+    ///////////////////////////////////////
+    // other constructors and destructor //
+    ///////////////////////////////////////
+
+    template<typename JsonRef,
+             detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
+                                 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
+    basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
+
+    /*!
+    @brief copy constructor
+
+    Creates a copy of a given JSON value.
+
+    @param[in] other  the JSON value to copy
+
+    @post `*this == other`
+
+    @complexity Linear in the size of @a other.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is linear.
+    - As postcondition, it holds: `other == basic_json(other)`.
+
+    @liveexample{The following code shows an example for the copy
+    constructor.,basic_json__basic_json}
+
+    @since version 1.0.0
+    */
+    basic_json(const basic_json& other)
+        : m_type(other.m_type)
+    {
+        // check of passed value is valid
+        other.assert_invariant();
+
+        switch (m_type)
+        {
+            case value_t::object:
+            {
+                m_value = *other.m_value.object;
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value = *other.m_value.array;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value = *other.m_value.string;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value = other.m_value.boolean;
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                m_value = other.m_value.number_integer;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value = other.m_value.number_unsigned;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value = other.m_value.number_float;
+                break;
+            }
+
+            case value_t::binary:
+            {
+                m_value = *other.m_value.binary;
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                break;
+        }
+
+        set_parents();
+        assert_invariant();
+    }
+
+    /*!
+    @brief move constructor
+
+    Move constructor. Constructs a JSON value with the contents of the given
+    value @a other using move semantics. It "steals" the resources from @a
+    other and leaves it as JSON null value.
+
+    @param[in,out] other  value to move to this object
+
+    @post `*this` has the same value as @a other before the call.
+    @post @a other is a JSON null value.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this constructor never throws
+    exceptions.
+
+    @requirement This function helps `basic_json` satisfying the
+    [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
+    requirements.
+
+    @liveexample{The code below shows the move constructor explicitly called
+    via std::move.,basic_json__moveconstructor}
+
+    @since version 1.0.0
+    */
+    basic_json(basic_json&& other) noexcept
+        : m_type(std::move(other.m_type)),
+          m_value(std::move(other.m_value))
+    {
+        // check that passed value is valid
+        other.assert_invariant(false);
+
+        // invalidate payload
+        other.m_type = value_t::null;
+        other.m_value = {};
+
+        set_parents();
+        assert_invariant();
+    }
+
+    /*!
+    @brief copy assignment
+
+    Copy assignment operator. Copies a JSON value via the "copy and swap"
+    strategy: It is expressed in terms of the copy constructor, destructor,
+    and the `swap()` member function.
+
+    @param[in] other  value to copy from
+
+    @complexity Linear.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is linear.
+
+    @liveexample{The code below shows and example for the copy assignment. It
+    creates a copy of value `a` which is then swapped with `b`. Finally\, the
+    copy of `a` (which is the null value after the swap) is
+    destroyed.,basic_json__copyassignment}
+
+    @since version 1.0.0
+    */
+    basic_json& operator=(basic_json other) noexcept (
+        std::is_nothrow_move_constructible<value_t>::value&&
+        std::is_nothrow_move_assignable<value_t>::value&&
+        std::is_nothrow_move_constructible<json_value>::value&&
+        std::is_nothrow_move_assignable<json_value>::value
+    )
+    {
+        // check that passed value is valid
+        other.assert_invariant();
+
+        using std::swap;
+        swap(m_type, other.m_type);
+        swap(m_value, other.m_value);
+
+        set_parents();
+        assert_invariant();
+        return *this;
+    }
+
+    /*!
+    @brief destructor
+
+    Destroys the JSON value and frees all allocated memory.
+
+    @complexity Linear.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is linear.
+    - All stored elements are destroyed and all memory is freed.
+
+    @since version 1.0.0
+    */
+    ~basic_json() noexcept
+    {
+        assert_invariant(false);
+        m_value.destroy(m_type);
+    }
+
+    /// @}
+
+  public:
+    ///////////////////////
+    // object inspection //
+    ///////////////////////
+
+    /// @name object inspection
+    /// Functions to inspect the type of a JSON value.
+    /// @{
+
+    /*!
+    @brief serialization
+
+    Serialization function for JSON values. The function tries to mimic
+    Python's `json.dumps()` function, and currently supports its @a indent
+    and @a ensure_ascii parameters.
+
+    @param[in] indent If indent is nonnegative, then array elements and object
+    members will be pretty-printed with that indent level. An indent level of
+    `0` will only insert newlines. `-1` (the default) selects the most compact
+    representation.
+    @param[in] indent_char The character to use for indentation if @a indent is
+    greater than `0`. The default is ` ` (space).
+    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
+    in the output are escaped with `\uXXXX` sequences, and the result consists
+    of ASCII characters only.
+    @param[in] error_handler  how to react on decoding errors; there are three
+    possible values: `strict` (throws and exception in case a decoding error
+    occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
+    and `ignore` (ignore invalid UTF-8 sequences during serialization; all
+    bytes are copied to the output unchanged).
+
+    @return string containing the serialization of the JSON value
+
+    @throw type_error.316 if a string stored inside the JSON value is not
+                          UTF-8 encoded and @a error_handler is set to strict
+
+    @note Binary values are serialized as object containing two keys:
+      - "bytes": an array of bytes as integers
+      - "subtype": the subtype as integer or "null" if the binary has no subtype
+
+    @complexity Linear.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @liveexample{The following example shows the effect of different @a indent\,
+    @a indent_char\, and @a ensure_ascii parameters to the result of the
+    serialization.,dump}
+
+    @see https://docs.python.org/2/library/json.html#json.dump
+
+    @since version 1.0.0; indentation character @a indent_char, option
+           @a ensure_ascii and exceptions added in version 3.0.0; error
+           handlers added in version 3.4.0; serialization of binary values added
+           in version 3.8.0.
+    */
+    string_t dump(const int indent = -1,
+                  const char indent_char = ' ',
+                  const bool ensure_ascii = false,
+                  const error_handler_t error_handler = error_handler_t::strict) const
+    {
+        string_t result;
+        serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
+
+        if (indent >= 0)
+        {
+            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
+        }
+        else
+        {
+            s.dump(*this, false, ensure_ascii, 0);
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief return the type of the JSON value (explicit)
+
+    Return the type of the JSON value as a value from the @ref value_t
+    enumeration.
+
+    @return the type of the JSON value
+            Value type                | return value
+            ------------------------- | -------------------------
+            null                      | value_t::null
+            boolean                   | value_t::boolean
+            string                    | value_t::string
+            number (integer)          | value_t::number_integer
+            number (unsigned integer) | value_t::number_unsigned
+            number (floating-point)   | value_t::number_float
+            object                    | value_t::object
+            array                     | value_t::array
+            binary                    | value_t::binary
+            discarded                 | value_t::discarded
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `type()` for all JSON
+    types.,type}
+
+    @sa see @ref operator value_t() -- return the type of the JSON value (implicit)
+    @sa see @ref type_name() -- return the type as string
+
+    @since version 1.0.0
+    */
+    constexpr value_t type() const noexcept
+    {
+        return m_type;
+    }
+
+    /*!
+    @brief return whether type is primitive
+
+    This function returns true if and only if the JSON type is primitive
+    (string, number, boolean, or null).
+
+    @return `true` if type is primitive (string, number, boolean, or null),
+    `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_primitive()` for all JSON
+    types.,is_primitive}
+
+    @sa see @ref is_structured() -- returns whether JSON value is structured
+    @sa see @ref is_null() -- returns whether JSON value is `null`
+    @sa see @ref is_string() -- returns whether JSON value is a string
+    @sa see @ref is_boolean() -- returns whether JSON value is a boolean
+    @sa see @ref is_number() -- returns whether JSON value is a number
+    @sa see @ref is_binary() -- returns whether JSON value is a binary array
+
+    @since version 1.0.0
+    */
+    constexpr bool is_primitive() const noexcept
+    {
+        return is_null() || is_string() || is_boolean() || is_number() || is_binary();
+    }
+
+    /*!
+    @brief return whether type is structured
+
+    This function returns true if and only if the JSON type is structured
+    (array or object).
+
+    @return `true` if type is structured (array or object), `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_structured()` for all JSON
+    types.,is_structured}
+
+    @sa see @ref is_primitive() -- returns whether value is primitive
+    @sa see @ref is_array() -- returns whether value is an array
+    @sa see @ref is_object() -- returns whether value is an object
+
+    @since version 1.0.0
+    */
+    constexpr bool is_structured() const noexcept
+    {
+        return is_array() || is_object();
+    }
+
+    /*!
+    @brief return whether value is null
+
+    This function returns true if and only if the JSON value is null.
+
+    @return `true` if type is null, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_null()` for all JSON
+    types.,is_null}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_null() const noexcept
+    {
+        return m_type == value_t::null;
+    }
+
+    /*!
+    @brief return whether value is a boolean
+
+    This function returns true if and only if the JSON value is a boolean.
+
+    @return `true` if type is boolean, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_boolean()` for all JSON
+    types.,is_boolean}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_boolean() const noexcept
+    {
+        return m_type == value_t::boolean;
+    }
+
+    /*!
+    @brief return whether value is a number
+
+    This function returns true if and only if the JSON value is a number. This
+    includes both integer (signed and unsigned) and floating-point values.
+
+    @return `true` if type is number (regardless whether integer, unsigned
+    integer or floating-type), `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_number()` for all JSON
+    types.,is_number}
+
+    @sa see @ref is_number_integer() -- check if value is an integer or unsigned
+    integer number
+    @sa see @ref is_number_unsigned() -- check if value is an unsigned integer
+    number
+    @sa see @ref is_number_float() -- check if value is a floating-point number
+
+    @since version 1.0.0
+    */
+    constexpr bool is_number() const noexcept
+    {
+        return is_number_integer() || is_number_float();
+    }
+
+    /*!
+    @brief return whether value is an integer number
+
+    This function returns true if and only if the JSON value is a signed or
+    unsigned integer number. This excludes floating-point values.
+
+    @return `true` if type is an integer or unsigned integer number, `false`
+    otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_number_integer()` for all
+    JSON types.,is_number_integer}
+
+    @sa see @ref is_number() -- check if value is a number
+    @sa see @ref is_number_unsigned() -- check if value is an unsigned integer
+    number
+    @sa see @ref is_number_float() -- check if value is a floating-point number
+
+    @since version 1.0.0
+    */
+    constexpr bool is_number_integer() const noexcept
+    {
+        return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
+    }
+
+    /*!
+    @brief return whether value is an unsigned integer number
+
+    This function returns true if and only if the JSON value is an unsigned
+    integer number. This excludes floating-point and signed integer values.
+
+    @return `true` if type is an unsigned integer number, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_number_unsigned()` for all
+    JSON types.,is_number_unsigned}
+
+    @sa see @ref is_number() -- check if value is a number
+    @sa see @ref is_number_integer() -- check if value is an integer or unsigned
+    integer number
+    @sa see @ref is_number_float() -- check if value is a floating-point number
+
+    @since version 2.0.0
+    */
+    constexpr bool is_number_unsigned() const noexcept
+    {
+        return m_type == value_t::number_unsigned;
+    }
+
+    /*!
+    @brief return whether value is a floating-point number
+
+    This function returns true if and only if the JSON value is a
+    floating-point number. This excludes signed and unsigned integer values.
+
+    @return `true` if type is a floating-point number, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_number_float()` for all
+    JSON types.,is_number_float}
+
+    @sa see @ref is_number() -- check if value is number
+    @sa see @ref is_number_integer() -- check if value is an integer number
+    @sa see @ref is_number_unsigned() -- check if value is an unsigned integer
+    number
+
+    @since version 1.0.0
+    */
+    constexpr bool is_number_float() const noexcept
+    {
+        return m_type == value_t::number_float;
+    }
+
+    /*!
+    @brief return whether value is an object
+
+    This function returns true if and only if the JSON value is an object.
+
+    @return `true` if type is object, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_object()` for all JSON
+    types.,is_object}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_object() const noexcept
+    {
+        return m_type == value_t::object;
+    }
+
+    /*!
+    @brief return whether value is an array
+
+    This function returns true if and only if the JSON value is an array.
+
+    @return `true` if type is array, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_array()` for all JSON
+    types.,is_array}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_array() const noexcept
+    {
+        return m_type == value_t::array;
+    }
+
+    /*!
+    @brief return whether value is a string
+
+    This function returns true if and only if the JSON value is a string.
+
+    @return `true` if type is string, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_string()` for all JSON
+    types.,is_string}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_string() const noexcept
+    {
+        return m_type == value_t::string;
+    }
+
+    /*!
+    @brief return whether value is a binary array
+
+    This function returns true if and only if the JSON value is a binary array.
+
+    @return `true` if type is binary array, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_binary()` for all JSON
+    types.,is_binary}
+
+    @since version 3.8.0
+    */
+    constexpr bool is_binary() const noexcept
+    {
+        return m_type == value_t::binary;
+    }
+
+    /*!
+    @brief return whether value is discarded
+
+    This function returns true if and only if the JSON value was discarded
+    during parsing with a callback function (see @ref parser_callback_t).
+
+    @note This function will always be `false` for JSON values after parsing.
+    That is, discarded values can only occur during parsing, but will be
+    removed when inside a structured value or replaced by null in other cases.
+
+    @return `true` if type is discarded, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_discarded()` for all JSON
+    types.,is_discarded}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_discarded() const noexcept
+    {
+        return m_type == value_t::discarded;
+    }
+
+    /*!
+    @brief return the type of the JSON value (implicit)
+
+    Implicitly return the type of the JSON value as a value from the @ref
+    value_t enumeration.
+
+    @return the type of the JSON value
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies the @ref value_t operator for
+    all JSON types.,operator__value_t}
+
+    @sa see @ref type() -- return the type of the JSON value (explicit)
+    @sa see @ref type_name() -- return the type as string
+
+    @since version 1.0.0
+    */
+    constexpr operator value_t() const noexcept
+    {
+        return m_type;
+    }
+
+    /// @}
+
+  private:
+    //////////////////
+    // value access //
+    //////////////////
+
+    /// get a boolean (explicit)
+    boolean_t get_impl(boolean_t* /*unused*/) const
+    {
+        if (JSON_HEDLEY_LIKELY(is_boolean()))
+        {
+            return m_value.boolean;
+        }
+
+        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
+    }
+
+    /// get a pointer to the value (object)
+    object_t* get_impl_ptr(object_t* /*unused*/) noexcept
+    {
+        return is_object() ? m_value.object : nullptr;
+    }
+
+    /// get a pointer to the value (object)
+    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
+    {
+        return is_object() ? m_value.object : nullptr;
+    }
+
+    /// get a pointer to the value (array)
+    array_t* get_impl_ptr(array_t* /*unused*/) noexcept
+    {
+        return is_array() ? m_value.array : nullptr;
+    }
+
+    /// get a pointer to the value (array)
+    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
+    {
+        return is_array() ? m_value.array : nullptr;
+    }
+
+    /// get a pointer to the value (string)
+    string_t* get_impl_ptr(string_t* /*unused*/) noexcept
+    {
+        return is_string() ? m_value.string : nullptr;
+    }
+
+    /// get a pointer to the value (string)
+    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
+    {
+        return is_string() ? m_value.string : nullptr;
+    }
+
+    /// get a pointer to the value (boolean)
+    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
+    {
+        return is_boolean() ? &m_value.boolean : nullptr;
+    }
+
+    /// get a pointer to the value (boolean)
+    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
+    {
+        return is_boolean() ? &m_value.boolean : nullptr;
+    }
+
+    /// get a pointer to the value (integer number)
+    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
+    {
+        return is_number_integer() ? &m_value.number_integer : nullptr;
+    }
+
+    /// get a pointer to the value (integer number)
+    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
+    {
+        return is_number_integer() ? &m_value.number_integer : nullptr;
+    }
+
+    /// get a pointer to the value (unsigned number)
+    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
+
+    /// get a pointer to the value (unsigned number)
+    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
+
+    /// get a pointer to the value (floating-point number)
+    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
+    {
+        return is_number_float() ? &m_value.number_float : nullptr;
+    }
+
+    /// get a pointer to the value (floating-point number)
+    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
+    {
+        return is_number_float() ? &m_value.number_float : nullptr;
+    }
+
+    /// get a pointer to the value (binary)
+    binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
+    {
+        return is_binary() ? m_value.binary : nullptr;
+    }
+
+    /// get a pointer to the value (binary)
+    constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
+    {
+        return is_binary() ? m_value.binary : nullptr;
+    }
+
+    /*!
+    @brief helper function to implement get_ref()
+
+    This function helps to implement get_ref() without code duplication for
+    const and non-const overloads
+
+    @tparam ThisType will be deduced as `basic_json` or `const basic_json`
+
+    @throw type_error.303 if ReferenceType does not match underlying value
+    type of the current JSON
+    */
+    template<typename ReferenceType, typename ThisType>
+    static ReferenceType get_ref_impl(ThisType& obj)
+    {
+        // delegate the call to get_ptr<>()
+        auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
+
+        if (JSON_HEDLEY_LIKELY(ptr != nullptr))
+        {
+            return *ptr;
+        }
+
+        JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
+    }
+
+  public:
+    /// @name value access
+    /// Direct access to the stored value of a JSON value.
+    /// @{
+
+    /*!
+    @brief get a pointer value (implicit)
+
+    Implicit pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning Writing data to the pointee of the result yields an undefined
+    state.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
+    @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
+    assertion.
+
+    @return pointer to the internally stored JSON value if the requested
+    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get_ptr}
+
+    @since version 1.0.0
+    */
+    template<typename PointerType, typename std::enable_if<
+                 std::is_pointer<PointerType>::value, int>::type = 0>
+    auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
+    {
+        // delegate the call to get_impl_ptr<>()
+        return get_impl_ptr(static_cast<PointerType>(nullptr));
+    }
+
+    /*!
+    @brief get a pointer value (implicit)
+    @copydoc get_ptr()
+    */
+    template < typename PointerType, typename std::enable_if <
+                   std::is_pointer<PointerType>::value&&
+                   std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
+    constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
+    {
+        // delegate the call to get_impl_ptr<>() const
+        return get_impl_ptr(static_cast<PointerType>(nullptr));
+    }
+
+  private:
+    /*!
+    @brief get a value (explicit)
+
+    Explicit type conversion between the JSON value and a compatible value
+    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
+    The value is converted by calling the @ref json_serializer<ValueType>
+    `from_json()` method.
+
+    The function is equivalent to executing
+    @code {.cpp}
+    ValueType ret;
+    JSONSerializer<ValueType>::from_json(*this, ret);
+    return ret;
+    @endcode
+
+    This overloads is chosen if:
+    - @a ValueType is not @ref basic_json,
+    - @ref json_serializer<ValueType> has a `from_json()` method of the form
+      `void from_json(const basic_json&, ValueType&)`, and
+    - @ref json_serializer<ValueType> does not have a `from_json()` method of
+      the form `ValueType from_json(const basic_json&)`
+
+    @tparam ValueType the returned value type
+
+    @return copy of the JSON value, converted to @a ValueType
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+    @liveexample{The example below shows several conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    associative containers such as `std::unordered_map<std::string\,
+    json>`.,get__ValueType_const}
+
+    @since version 2.1.0
+    */
+    template < typename ValueType,
+               detail::enable_if_t <
+                   detail::is_default_constructible<ValueType>::value&&
+                   detail::has_from_json<basic_json_t, ValueType>::value,
+                   int > = 0 >
+    ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
+                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
+    {
+        auto ret = ValueType();
+        JSONSerializer<ValueType>::from_json(*this, ret);
+        return ret;
+    }
+
+    /*!
+    @brief get a value (explicit); special case
+
+    Explicit type conversion between the JSON value and a compatible value
+    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
+    The value is converted by calling the @ref json_serializer<ValueType>
+    `from_json()` method.
+
+    The function is equivalent to executing
+    @code {.cpp}
+    return JSONSerializer<ValueType>::from_json(*this);
+    @endcode
+
+    This overloads is chosen if:
+    - @a ValueType is not @ref basic_json and
+    - @ref json_serializer<ValueType> has a `from_json()` method of the form
+      `ValueType from_json(const basic_json&)`
+
+    @note If @ref json_serializer<ValueType> has both overloads of
+    `from_json()`, this one is chosen.
+
+    @tparam ValueType the returned value type
+
+    @return copy of the JSON value, converted to @a ValueType
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+    @since version 2.1.0
+    */
+    template < typename ValueType,
+               detail::enable_if_t <
+                   detail::has_non_default_from_json<basic_json_t, ValueType>::value,
+                   int > = 0 >
+    ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
+                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
+    {
+        return JSONSerializer<ValueType>::from_json(*this);
+    }
+
+    /*!
+    @brief get special-case overload
+
+    This overloads converts the current @ref basic_json in a different
+    @ref basic_json type
+
+    @tparam BasicJsonType == @ref basic_json
+
+    @return a copy of *this, converted into @a BasicJsonType
+
+    @complexity Depending on the implementation of the called `from_json()`
+                method.
+
+    @since version 3.2.0
+    */
+    template < typename BasicJsonType,
+               detail::enable_if_t <
+                   detail::is_basic_json<BasicJsonType>::value,
+                   int > = 0 >
+    BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
+    {
+        return *this;
+    }
+
+    /*!
+    @brief get special-case overload
+
+    This overloads avoids a lot of template boilerplate, it can be seen as the
+    identity method
+
+    @tparam BasicJsonType == @ref basic_json
+
+    @return a copy of *this
+
+    @complexity Constant.
+
+    @since version 2.1.0
+    */
+    template<typename BasicJsonType,
+             detail::enable_if_t<
+                 std::is_same<BasicJsonType, basic_json_t>::value,
+                 int> = 0>
+    basic_json get_impl(detail::priority_tag<3> /*unused*/) const
+    {
+        return *this;
+    }
+
+    /*!
+    @brief get a pointer value (explicit)
+    @copydoc get()
+    */
+    template<typename PointerType,
+             detail::enable_if_t<
+                 std::is_pointer<PointerType>::value,
+                 int> = 0>
+    constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
+    -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
+    {
+        // delegate the call to get_ptr
+        return get_ptr<PointerType>();
+    }
+
+  public:
+    /*!
+    @brief get a (pointer) value (explicit)
+
+    Performs explicit type conversion between the JSON value and a compatible value if required.
+
+    - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
+    No copies are made.
+
+    - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
+    from the current @ref basic_json.
+
+    - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
+    method.
+
+    @tparam ValueTypeCV the provided value type
+    @tparam ValueType the returned value type
+
+    @return copy of the JSON value, converted to @tparam ValueType if necessary
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
+
+    @since version 2.1.0
+    */
+    template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
+#if defined(JSON_HAS_CPP_14)
+    constexpr
+#endif
+    auto get() const noexcept(
+    noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
+    -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
+    {
+        // we cannot static_assert on ValueTypeCV being non-const, because
+        // there is support for get<const basic_json_t>(), which is why we
+        // still need the uncvref
+        static_assert(!std::is_reference<ValueTypeCV>::value,
+                      "get() cannot be used with reference types, you might want to use get_ref()");
+        return get_impl<ValueType>(detail::priority_tag<4> {});
+    }
+
+    /*!
+    @brief get a pointer value (explicit)
+
+    Explicit pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning The pointer becomes invalid if the underlying JSON object
+    changes.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
+    @ref number_unsigned_t, or @ref number_float_t.
+
+    @return pointer to the internally stored JSON value if the requested
+    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get__PointerType}
+
+    @sa see @ref get_ptr() for explicit pointer-member access
+
+    @since version 1.0.0
+    */
+    template<typename PointerType, typename std::enable_if<
+                 std::is_pointer<PointerType>::value, int>::type = 0>
+    auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
+    {
+        // delegate the call to get_ptr
+        return get_ptr<PointerType>();
+    }
+
+    /*!
+    @brief get a value (explicit)
+
+    Explicit type conversion between the JSON value and a compatible value.
+    The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
+    `from_json()` method.
+
+    The function is equivalent to executing
+    @code {.cpp}
+    ValueType v;
+    JSONSerializer<ValueType>::from_json(*this, v);
+    @endcode
+
+    This overloads is chosen if:
+    - @a ValueType is not @ref basic_json,
+    - @ref json_serializer<ValueType> has a `from_json()` method of the form
+      `void from_json(const basic_json&, ValueType&)`, and
+
+    @tparam ValueType the input parameter type.
+
+    @return the input parameter, allowing chaining calls.
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+    @liveexample{The example below shows several conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    associative containers such as `std::unordered_map<std::string\,
+    json>`.,get_to}
+
+    @since version 3.3.0
+    */
+    template < typename ValueType,
+               detail::enable_if_t <
+                   !detail::is_basic_json<ValueType>::value&&
+                   detail::has_from_json<basic_json_t, ValueType>::value,
+                   int > = 0 >
+    ValueType & get_to(ValueType& v) const noexcept(noexcept(
+                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
+    {
+        JSONSerializer<ValueType>::from_json(*this, v);
+        return v;
+    }
+
+    // specialization to allow to call get_to with a basic_json value
+    // see https://github.com/nlohmann/json/issues/2175
+    template<typename ValueType,
+             detail::enable_if_t <
+                 detail::is_basic_json<ValueType>::value,
+                 int> = 0>
+    ValueType & get_to(ValueType& v) const
+    {
+        v = *this;
+        return v;
+    }
+
+    template <
+        typename T, std::size_t N,
+        typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+        detail::enable_if_t <
+            detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
+    Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+    noexcept(noexcept(JSONSerializer<Array>::from_json(
+                          std::declval<const basic_json_t&>(), v)))
+    {
+        JSONSerializer<Array>::from_json(*this, v);
+        return v;
+    }
+
+    /*!
+    @brief get a reference value (implicit)
+
+    Implicit reference access to the internally stored JSON value. No copies
+    are made.
+
+    @warning Writing data to the referee of the result yields an undefined
+    state.
+
+    @tparam ReferenceType reference type; must be a reference to @ref array_t,
+    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
+    @ref number_float_t. Enforced by static assertion.
+
+    @return reference to the internally stored JSON value if the requested
+    reference type @a ReferenceType fits to the JSON value; throws
+    type_error.303 otherwise
+
+    @throw type_error.303 in case passed type @a ReferenceType is incompatible
+    with the stored JSON value; see example below
+
+    @complexity Constant.
+
+    @liveexample{The example shows several calls to `get_ref()`.,get_ref}
+
+    @since version 1.1.0
+    */
+    template<typename ReferenceType, typename std::enable_if<
+                 std::is_reference<ReferenceType>::value, int>::type = 0>
+    ReferenceType get_ref()
+    {
+        // delegate call to get_ref_impl
+        return get_ref_impl<ReferenceType>(*this);
+    }
+
+    /*!
+    @brief get a reference value (implicit)
+    @copydoc get_ref()
+    */
+    template < typename ReferenceType, typename std::enable_if <
+                   std::is_reference<ReferenceType>::value&&
+                   std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
+    ReferenceType get_ref() const
+    {
+        // delegate call to get_ref_impl
+        return get_ref_impl<ReferenceType>(*this);
+    }
+
+    /*!
+    @brief get a value (implicit)
+
+    Implicit type conversion between the JSON value and a compatible value.
+    The call is realized by calling @ref get() const.
+
+    @tparam ValueType non-pointer type compatible to the JSON value, for
+    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+    `std::vector` types for JSON arrays. The character type of @ref string_t
+    as well as an initializer list of this type is excluded to avoid
+    ambiguities as these types implicitly convert to `std::string`.
+
+    @return copy of the JSON value, converted to type @a ValueType
+
+    @throw type_error.302 in case passed type @a ValueType is incompatible
+    to the JSON value type (e.g., the JSON value is of type boolean, but a
+    string is requested); see example below
+
+    @complexity Linear in the size of the JSON value.
+
+    @liveexample{The example below shows several conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    associative containers such as `std::unordered_map<std::string\,
+    json>`.,operator__ValueType}
+
+    @since version 1.0.0
+    */
+    template < typename ValueType, typename std::enable_if <
+                   detail::conjunction <
+                       detail::negation<std::is_pointer<ValueType>>,
+                       detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
+                                        detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
+                                        detail::negation<detail::is_basic_json<ValueType>>,
+                                        detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
+
+#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
+                                                detail::negation<std::is_same<ValueType, std::string_view>>,
+#endif
+                                                detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
+                                                >::value, int >::type = 0 >
+                                        JSON_EXPLICIT operator ValueType() const
+    {
+        // delegate the call to get<>() const
+        return get<ValueType>();
+    }
+
+    /*!
+    @return reference to the binary value
+
+    @throw type_error.302 if the value is not binary
+
+    @sa see @ref is_binary() to check if the value is binary
+
+    @since version 3.8.0
+    */
+    binary_t& get_binary()
+    {
+        if (!is_binary())
+        {
+            JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
+        }
+
+        return *get_ptr<binary_t*>();
+    }
+
+    /// @copydoc get_binary()
+    const binary_t& get_binary() const
+    {
+        if (!is_binary())
+        {
+            JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
+        }
+
+        return *get_ptr<const binary_t*>();
+    }
+
+    /// @}
+
+
+    ////////////////////
+    // element access //
+    ////////////////////
+
+    /// @name element access
+    /// Access to the JSON value.
+    /// @{
+
+    /*!
+    @brief access specified array element with bounds checking
+
+    Returns a reference to the element at specified location @a idx, with
+    bounds checking.
+
+    @param[in] idx  index of the element to access
+
+    @return reference to the element at index @a idx
+
+    @throw type_error.304 if the JSON value is not an array; in this case,
+    calling `at` with an index makes no sense. See example below.
+    @throw out_of_range.401 if the index @a idx is out of range of the array;
+    that is, `idx >= size()`. See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 1.0.0
+
+    @liveexample{The example below shows how array elements can be read and
+    written using `at()`. It also demonstrates the different exceptions that
+    can be thrown.,at__size_type}
+    */
+    reference at(size_type idx)
+    {
+        // at only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            JSON_TRY
+            {
+                return set_parent(m_value.array->at(idx));
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /*!
+    @brief access specified array element with bounds checking
+
+    Returns a const reference to the element at specified location @a idx,
+    with bounds checking.
+
+    @param[in] idx  index of the element to access
+
+    @return const reference to the element at index @a idx
+
+    @throw type_error.304 if the JSON value is not an array; in this case,
+    calling `at` with an index makes no sense. See example below.
+    @throw out_of_range.401 if the index @a idx is out of range of the array;
+    that is, `idx >= size()`. See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 1.0.0
+
+    @liveexample{The example below shows how array elements can be read using
+    `at()`. It also demonstrates the different exceptions that can be thrown.,
+    at__size_type_const}
+    */
+    const_reference at(size_type idx) const
+    {
+        // at only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            JSON_TRY
+            {
+                return m_value.array->at(idx);
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /*!
+    @brief access specified object element with bounds checking
+
+    Returns a reference to the element at with specified key @a key, with
+    bounds checking.
+
+    @param[in] key  key of the element to access
+
+    @return reference to the element at key @a key
+
+    @throw type_error.304 if the JSON value is not an object; in this case,
+    calling `at` with a key makes no sense. See example below.
+    @throw out_of_range.403 if the key @a key is is not stored in the object;
+    that is, `find(key) == end()`. See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Logarithmic in the size of the container.
+
+    @sa see @ref operator[](const typename object_t::key_type&) for unchecked
+    access by reference
+    @sa see @ref value() for access by value with a default value
+
+    @since version 1.0.0
+
+    @liveexample{The example below shows how object elements can be read and
+    written using `at()`. It also demonstrates the different exceptions that
+    can be thrown.,at__object_t_key_type}
+    */
+    reference at(const typename object_t::key_type& key)
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            JSON_TRY
+            {
+                return set_parent(m_value.object->at(key));
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /*!
+    @brief access specified object element with bounds checking
+
+    Returns a const reference to the element at with specified key @a key,
+    with bounds checking.
+
+    @param[in] key  key of the element to access
+
+    @return const reference to the element at key @a key
+
+    @throw type_error.304 if the JSON value is not an object; in this case,
+    calling `at` with a key makes no sense. See example below.
+    @throw out_of_range.403 if the key @a key is is not stored in the object;
+    that is, `find(key) == end()`. See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Logarithmic in the size of the container.
+
+    @sa see @ref operator[](const typename object_t::key_type&) for unchecked
+    access by reference
+    @sa see @ref value() for access by value with a default value
+
+    @since version 1.0.0
+
+    @liveexample{The example below shows how object elements can be read using
+    `at()`. It also demonstrates the different exceptions that can be thrown.,
+    at__object_t_key_type_const}
+    */
+    const_reference at(const typename object_t::key_type& key) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            JSON_TRY
+            {
+                return m_value.object->at(key);
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /*!
+    @brief access specified array element
+
+    Returns a reference to the element at specified location @a idx.
+
+    @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
+    then the array is silently filled up with `null` values to make `idx` a
+    valid reference to the last stored element.
+
+    @param[in] idx  index of the element to access
+
+    @return reference to the element at index @a idx
+
+    @throw type_error.305 if the JSON value is not an array or null; in that
+    cases, using the [] operator with an index makes no sense.
+
+    @complexity Constant if @a idx is in the range of the array. Otherwise
+    linear in `idx - size()`.
+
+    @liveexample{The example below shows how array elements can be read and
+    written using `[]` operator. Note the addition of `null`
+    values.,operatorarray__size_type}
+
+    @since version 1.0.0
+    */
+    reference operator[](size_type idx)
+    {
+        // implicitly convert null value to an empty array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value.array = create<array_t>();
+            assert_invariant();
+        }
+
+        // operator[] only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // fill up array with null values if given idx is outside range
+            if (idx >= m_value.array->size())
+            {
+#if JSON_DIAGNOSTICS
+                // remember array size & capacity before resizing
+                const auto old_size = m_value.array->size();
+                const auto old_capacity = m_value.array->capacity();
+#endif
+                m_value.array->resize(idx + 1);
+
+#if JSON_DIAGNOSTICS
+                if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
+                {
+                    // capacity has changed: update all parents
+                    set_parents();
+                }
+                else
+                {
+                    // set parent for values added above
+                    set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
+                }
+#endif
+                assert_invariant();
+            }
+
+            return m_value.array->operator[](idx);
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief access specified array element
+
+    Returns a const reference to the element at specified location @a idx.
+
+    @param[in] idx  index of the element to access
+
+    @return const reference to the element at index @a idx
+
+    @throw type_error.305 if the JSON value is not an array; in that case,
+    using the [] operator with an index makes no sense.
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how array elements can be read using
+    the `[]` operator.,operatorarray__size_type_const}
+
+    @since version 1.0.0
+    */
+    const_reference operator[](size_type idx) const
+    {
+        // const operator[] only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            return m_value.array->operator[](idx);
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief access specified object element
+
+    Returns a reference to the element at with specified key @a key.
+
+    @note If @a key is not found in the object, then it is silently added to
+    the object and filled with a `null` value to make `key` a valid reference.
+    In case the value was `null` before, it is converted to an object.
+
+    @param[in] key  key of the element to access
+
+    @return reference to the element at key @a key
+
+    @throw type_error.305 if the JSON value is not an object or null; in that
+    cases, using the [] operator with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be read and
+    written using the `[]` operator.,operatorarray__key_type}
+
+    @sa see @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa see @ref value() for access by value with a default value
+
+    @since version 1.0.0
+    */
+    reference operator[](const typename object_t::key_type& key)
+    {
+        // implicitly convert null value to an empty object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value.object = create<object_t>();
+            assert_invariant();
+        }
+
+        // operator[] only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            return set_parent(m_value.object->operator[](key));
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief read-only access specified object element
+
+    Returns a const reference to the element at with specified key @a key. No
+    bounds checking is performed.
+
+    @warning If the element with key @a key does not exist, the behavior is
+    undefined.
+
+    @param[in] key  key of the element to access
+
+    @return const reference to the element at key @a key
+
+    @pre The element with key @a key must exist. **This precondition is
+         enforced with an assertion.**
+
+    @throw type_error.305 if the JSON value is not an object; in that case,
+    using the [] operator with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be read using
+    the `[]` operator.,operatorarray__key_type_const}
+
+    @sa see @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa see @ref value() for access by value with a default value
+
+    @since version 1.0.0
+    */
+    const_reference operator[](const typename object_t::key_type& key) const
+    {
+        // const operator[] only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
+            return m_value.object->find(key)->second;
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief access specified object element
+
+    Returns a reference to the element at with specified key @a key.
+
+    @note If @a key is not found in the object, then it is silently added to
+    the object and filled with a `null` value to make `key` a valid reference.
+    In case the value was `null` before, it is converted to an object.
+
+    @param[in] key  key of the element to access
+
+    @return reference to the element at key @a key
+
+    @throw type_error.305 if the JSON value is not an object or null; in that
+    cases, using the [] operator with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be read and
+    written using the `[]` operator.,operatorarray__key_type}
+
+    @sa see @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa see @ref value() for access by value with a default value
+
+    @since version 1.1.0
+    */
+    template<typename T>
+    JSON_HEDLEY_NON_NULL(2)
+    reference operator[](T* key)
+    {
+        // implicitly convert null to object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            return set_parent(m_value.object->operator[](key));
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief read-only access specified object element
+
+    Returns a const reference to the element at with specified key @a key. No
+    bounds checking is performed.
+
+    @warning If the element with key @a key does not exist, the behavior is
+    undefined.
+
+    @param[in] key  key of the element to access
+
+    @return const reference to the element at key @a key
+
+    @pre The element with key @a key must exist. **This precondition is
+         enforced with an assertion.**
+
+    @throw type_error.305 if the JSON value is not an object; in that case,
+    using the [] operator with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be read using
+    the `[]` operator.,operatorarray__key_type_const}
+
+    @sa see @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa see @ref value() for access by value with a default value
+
+    @since version 1.1.0
+    */
+    template<typename T>
+    JSON_HEDLEY_NON_NULL(2)
+    const_reference operator[](T* key) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
+            return m_value.object->find(key)->second;
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief access specified object element with default value
+
+    Returns either a copy of an object's element at the specified key @a key
+    or a given default value if no element with key @a key exists.
+
+    The function is basically equivalent to executing
+    @code {.cpp}
+    try {
+        return at(key);
+    } catch(out_of_range) {
+        return default_value;
+    }
+    @endcode
+
+    @note Unlike @ref at(const typename object_t::key_type&), this function
+    does not throw if the given key @a key was not found.
+
+    @note Unlike @ref operator[](const typename object_t::key_type& key), this
+    function does not implicitly add an element to the position defined by @a
+    key. This function is furthermore also applicable to const objects.
+
+    @param[in] key  key of the element to access
+    @param[in] default_value  the value to return if @a key is not found
+
+    @tparam ValueType type compatible to JSON values, for instance `int` for
+    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
+    JSON arrays. Note the type of the expected value at @a key and the default
+    value @a default_value must be compatible.
+
+    @return copy of the element at key @a key or @a default_value if @a key
+    is not found
+
+    @throw type_error.302 if @a default_value does not match the type of the
+    value at @a key
+    @throw type_error.306 if the JSON value is not an object; in that case,
+    using `value()` with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be queried
+    with a default value.,basic_json__value}
+
+    @sa see @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa see @ref operator[](const typename object_t::key_type&) for unchecked
+    access by reference
+
+    @since version 1.0.0
+    */
+    // using std::is_convertible in a std::enable_if will fail when using explicit conversions
+    template < class ValueType, typename std::enable_if <
+                   detail::is_getable<basic_json_t, ValueType>::value
+                   && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
+    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if key is found, return value and given default value otherwise
+            const auto it = find(key);
+            if (it != end())
+            {
+                return it->template get<ValueType>();
+            }
+
+            return default_value;
+        }
+
+        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief overload for a default value of type const char*
+    @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const
+    */
+    string_t value(const typename object_t::key_type& key, const char* default_value) const
+    {
+        return value(key, string_t(default_value));
+    }
+
+    /*!
+    @brief access specified object element via JSON Pointer with default value
+
+    Returns either a copy of an object's element at the specified key @a key
+    or a given default value if no element with key @a key exists.
+
+    The function is basically equivalent to executing
+    @code {.cpp}
+    try {
+        return at(ptr);
+    } catch(out_of_range) {
+        return default_value;
+    }
+    @endcode
+
+    @note Unlike @ref at(const json_pointer&), this function does not throw
+    if the given key @a key was not found.
+
+    @param[in] ptr  a JSON pointer to the element to access
+    @param[in] default_value  the value to return if @a ptr found no value
+
+    @tparam ValueType type compatible to JSON values, for instance `int` for
+    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
+    JSON arrays. Note the type of the expected value at @a key and the default
+    value @a default_value must be compatible.
+
+    @return copy of the element at key @a key or @a default_value if @a key
+    is not found
+
+    @throw type_error.302 if @a default_value does not match the type of the
+    value at @a ptr
+    @throw type_error.306 if the JSON value is not an object; in that case,
+    using `value()` with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be queried
+    with a default value.,basic_json__value_ptr}
+
+    @sa see @ref operator[](const json_pointer&) for unchecked access by reference
+
+    @since version 2.0.2
+    */
+    template<class ValueType, typename std::enable_if<
+                 detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
+    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if pointer resolves a value, return it or use default value
+            JSON_TRY
+            {
+                return ptr.get_checked(this).template get<ValueType>();
+            }
+            JSON_INTERNAL_CATCH (out_of_range&)
+            {
+                return default_value;
+            }
+        }
+
+        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief overload for a default value of type const char*
+    @copydoc basic_json::value(const json_pointer&, ValueType) const
+    */
+    JSON_HEDLEY_NON_NULL(3)
+    string_t value(const json_pointer& ptr, const char* default_value) const
+    {
+        return value(ptr, string_t(default_value));
+    }
+
+    /*!
+    @brief access the first element
+
+    Returns a reference to the first element in the container. For a JSON
+    container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
+
+    @return In case of a structured type (array or object), a reference to the
+    first element is returned. In case of number, string, boolean, or binary
+    values, a reference to the value is returned.
+
+    @complexity Constant.
+
+    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
+    or an empty array or object (undefined behavior, **guarded by
+    assertions**).
+    @post The JSON value remains unchanged.
+
+    @throw invalid_iterator.214 when called on `null` value
+
+    @liveexample{The following code shows an example for `front()`.,front}
+
+    @sa see @ref back() -- access the last element
+
+    @since version 1.0.0
+    */
+    reference front()
+    {
+        return *begin();
+    }
+
+    /*!
+    @copydoc basic_json::front()
+    */
+    const_reference front() const
+    {
+        return *cbegin();
+    }
+
+    /*!
+    @brief access the last element
+
+    Returns a reference to the last element in the container. For a JSON
+    container `c`, the expression `c.back()` is equivalent to
+    @code {.cpp}
+    auto tmp = c.end();
+    --tmp;
+    return *tmp;
+    @endcode
+
+    @return In case of a structured type (array or object), a reference to the
+    last element is returned. In case of number, string, boolean, or binary
+    values, a reference to the value is returned.
+
+    @complexity Constant.
+
+    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
+    or an empty array or object (undefined behavior, **guarded by
+    assertions**).
+    @post The JSON value remains unchanged.
+
+    @throw invalid_iterator.214 when called on a `null` value. See example
+    below.
+
+    @liveexample{The following code shows an example for `back()`.,back}
+
+    @sa see @ref front() -- access the first element
+
+    @since version 1.0.0
+    */
+    reference back()
+    {
+        auto tmp = end();
+        --tmp;
+        return *tmp;
+    }
+
+    /*!
+    @copydoc basic_json::back()
+    */
+    const_reference back() const
+    {
+        auto tmp = cend();
+        --tmp;
+        return *tmp;
+    }
+
+    /*!
+    @brief remove element given an iterator
+
+    Removes the element specified by iterator @a pos. The iterator @a pos must
+    be valid and dereferenceable. Thus the `end()` iterator (which is valid,
+    but is not dereferenceable) cannot be used as a value for @a pos.
+
+    If called on a primitive type other than `null`, the resulting JSON value
+    will be `null`.
+
+    @param[in] pos iterator to the element to remove
+    @return Iterator following the last removed element. If the iterator @a
+    pos refers to the last element, the `end()` iterator is returned.
+
+    @tparam IteratorType an @ref iterator or @ref const_iterator
+
+    @post Invalidates iterators and references at or after the point of the
+    erase, including the `end()` iterator.
+
+    @throw type_error.307 if called on a `null` value; example: `"cannot use
+    erase() with null"`
+    @throw invalid_iterator.202 if called on an iterator which does not belong
+    to the current JSON value; example: `"iterator does not fit current
+    value"`
+    @throw invalid_iterator.205 if called on a primitive type with invalid
+    iterator (i.e., any iterator which is not `begin()`); example: `"iterator
+    out of range"`
+
+    @complexity The complexity depends on the type:
+    - objects: amortized constant
+    - arrays: linear in distance between @a pos and the end of the container
+    - strings and binary: linear in the length of the member
+    - other types: constant
+
+    @liveexample{The example shows the result of `erase()` for different JSON
+    types.,erase__IteratorType}
+
+    @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in
+    the given range
+    @sa see @ref erase(const typename object_t::key_type&) -- removes the element
+    from an object at the given key
+    @sa see @ref erase(const size_type) -- removes the element from an array at
+    the given index
+
+    @since version 1.0.0
+    */
+    template < class IteratorType, typename std::enable_if <
+                   std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
+                   std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
+               = 0 >
+    IteratorType erase(IteratorType pos)
+    {
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+        }
+
+        IteratorType result = end();
+
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            case value_t::binary:
+            {
+                if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
+                {
+                    JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
+                }
+
+                if (is_string())
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
+                    m_value.string = nullptr;
+                }
+                else if (is_binary())
+                {
+                    AllocatorType<binary_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
+                    m_value.binary = nullptr;
+                }
+
+                m_type = value_t::null;
+                assert_invariant();
+                break;
+            }
+
+            case value_t::object:
+            {
+                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief remove elements given an iterator range
+
+    Removes the element specified by the range `[first; last)`. The iterator
+    @a first does not need to be dereferenceable if `first == last`: erasing
+    an empty range is a no-op.
+
+    If called on a primitive type other than `null`, the resulting JSON value
+    will be `null`.
+
+    @param[in] first iterator to the beginning of the range to remove
+    @param[in] last iterator past the end of the range to remove
+    @return Iterator following the last removed element. If the iterator @a
+    second refers to the last element, the `end()` iterator is returned.
+
+    @tparam IteratorType an @ref iterator or @ref const_iterator
+
+    @post Invalidates iterators and references at or after the point of the
+    erase, including the `end()` iterator.
+
+    @throw type_error.307 if called on a `null` value; example: `"cannot use
+    erase() with null"`
+    @throw invalid_iterator.203 if called on iterators which does not belong
+    to the current JSON value; example: `"iterators do not fit current value"`
+    @throw invalid_iterator.204 if called on a primitive type with invalid
+    iterators (i.e., if `first != begin()` and `last != end()`); example:
+    `"iterators out of range"`
+
+    @complexity The complexity depends on the type:
+    - objects: `log(size()) + std::distance(first, last)`
+    - arrays: linear in the distance between @a first and @a last, plus linear
+      in the distance between @a last and end of the container
+    - strings and binary: linear in the length of the member
+    - other types: constant
+
+    @liveexample{The example shows the result of `erase()` for different JSON
+    types.,erase__IteratorType_IteratorType}
+
+    @sa see @ref erase(IteratorType) -- removes the element at a given position
+    @sa see @ref erase(const typename object_t::key_type&) -- removes the element
+    from an object at the given key
+    @sa see @ref erase(const size_type) -- removes the element from an array at
+    the given index
+
+    @since version 1.0.0
+    */
+    template < class IteratorType, typename std::enable_if <
+                   std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
+                   std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
+               = 0 >
+    IteratorType erase(IteratorType first, IteratorType last)
+    {
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
+        }
+
+        IteratorType result = end();
+
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            case value_t::binary:
+            {
+                if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
+                                       || !last.m_it.primitive_iterator.is_end()))
+                {
+                    JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
+                }
+
+                if (is_string())
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
+                    m_value.string = nullptr;
+                }
+                else if (is_binary())
+                {
+                    AllocatorType<binary_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
+                    m_value.binary = nullptr;
+                }
+
+                m_type = value_t::null;
+                assert_invariant();
+                break;
+            }
+
+            case value_t::object:
+            {
+                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
+                                              last.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
+                                             last.m_it.array_iterator);
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief remove element from a JSON object given a key
+
+    Removes elements from a JSON object with the key value @a key.
+
+    @param[in] key value of the elements to remove
+
+    @return Number of elements removed. If @a ObjectType is the default
+    `std::map` type, the return value will always be `0` (@a key was not
+    found) or `1` (@a key was found).
+
+    @post References and iterators to the erased elements are invalidated.
+    Other references and iterators are not affected.
+
+    @throw type_error.307 when called on a type other than JSON object;
+    example: `"cannot use erase() with null"`
+
+    @complexity `log(size()) + count(key)`
+
+    @liveexample{The example shows the effect of `erase()`.,erase__key_type}
+
+    @sa see @ref erase(IteratorType) -- removes the element at a given position
+    @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in
+    the given range
+    @sa see @ref erase(const size_type) -- removes the element from an array at
+    the given index
+
+    @since version 1.0.0
+    */
+    size_type erase(const typename object_t::key_type& key)
+    {
+        // this erase only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            return m_value.object->erase(key);
+        }
+
+        JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief remove element from a JSON array given an index
+
+    Removes element from a JSON array at the index @a idx.
+
+    @param[in] idx index of the element to remove
+
+    @throw type_error.307 when called on a type other than JSON object;
+    example: `"cannot use erase() with null"`
+    @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
+    is out of range"`
+
+    @complexity Linear in distance between @a idx and the end of the container.
+
+    @liveexample{The example shows the effect of `erase()`.,erase__size_type}
+
+    @sa see @ref erase(IteratorType) -- removes the element at a given position
+    @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in
+    the given range
+    @sa see @ref erase(const typename object_t::key_type&) -- removes the element
+    from an object at the given key
+
+    @since version 1.0.0
+    */
+    void erase(const size_type idx)
+    {
+        // this erase only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            if (JSON_HEDLEY_UNLIKELY(idx >= size()))
+            {
+                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+            }
+
+            m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
+        }
+        else
+        {
+            JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /// @}
+
+
+    ////////////
+    // lookup //
+    ////////////
+
+    /// @name lookup
+    /// @{
+
+    /*!
+    @brief find an element in a JSON object
+
+    Finds an element in a JSON object with key equivalent to @a key. If the
+    element is not found or the JSON value is not an object, end() is
+    returned.
+
+    @note This method always returns @ref end() when executed on a JSON type
+          that is not an object.
+
+    @param[in] key key value of the element to search for.
+
+    @return Iterator to an element with key equivalent to @a key. If no such
+    element is found or the JSON value is not an object, past-the-end (see
+    @ref end()) iterator is returned.
+
+    @complexity Logarithmic in the size of the JSON object.
+
+    @liveexample{The example shows how `find()` is used.,find__key_type}
+
+    @sa see @ref contains(KeyT&&) const -- checks whether a key exists
+
+    @since version 1.0.0
+    */
+    template<typename KeyT>
+    iterator find(KeyT&& key)
+    {
+        auto result = end();
+
+        if (is_object())
+        {
+            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief find an element in a JSON object
+    @copydoc find(KeyT&&)
+    */
+    template<typename KeyT>
+    const_iterator find(KeyT&& key) const
+    {
+        auto result = cend();
+
+        if (is_object())
+        {
+            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief returns the number of occurrences of a key in a JSON object
+
+    Returns the number of elements with key @a key. If ObjectType is the
+    default `std::map` type, the return value will always be `0` (@a key was
+    not found) or `1` (@a key was found).
+
+    @note This method always returns `0` when executed on a JSON type that is
+          not an object.
+
+    @param[in] key key value of the element to count
+
+    @return Number of elements with key @a key. If the JSON value is not an
+    object, the return value will be `0`.
+
+    @complexity Logarithmic in the size of the JSON object.
+
+    @liveexample{The example shows how `count()` is used.,count}
+
+    @since version 1.0.0
+    */
+    template<typename KeyT>
+    size_type count(KeyT&& key) const
+    {
+        // return 0 for all nonobject types
+        return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
+    }
+
+    /*!
+    @brief check the existence of an element in a JSON object
+
+    Check whether an element exists in a JSON object with key equivalent to
+    @a key. If the element is not found or the JSON value is not an object,
+    false is returned.
+
+    @note This method always returns false when executed on a JSON type
+          that is not an object.
+
+    @param[in] key key value to check its existence.
+
+    @return true if an element with specified @a key exists. If no such
+    element with such key is found or the JSON value is not an object,
+    false is returned.
+
+    @complexity Logarithmic in the size of the JSON object.
+
+    @liveexample{The following code shows an example for `contains()`.,contains}
+
+    @sa see @ref find(KeyT&&) -- returns an iterator to an object element
+    @sa see @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer
+
+    @since version 3.6.0
+    */
+    template < typename KeyT, typename std::enable_if <
+                   !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
+    bool contains(KeyT && key) const
+    {
+        return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
+    }
+
+    /*!
+    @brief check the existence of an element in a JSON object given a JSON pointer
+
+    Check whether the given JSON pointer @a ptr can be resolved in the current
+    JSON value.
+
+    @note This method can be executed on any JSON value type.
+
+    @param[in] ptr JSON pointer to check its existence.
+
+    @return true if the JSON pointer can be resolved to a stored value, false
+    otherwise.
+
+    @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+
+    @complexity Logarithmic in the size of the JSON object.
+
+    @liveexample{The following code shows an example for `contains()`.,contains_json_pointer}
+
+    @sa see @ref contains(KeyT &&) const -- checks the existence of a key
+
+    @since version 3.7.0
+    */
+    bool contains(const json_pointer& ptr) const
+    {
+        return ptr.contains(this);
+    }
+
+    /// @}
+
+
+    ///////////////
+    // iterators //
+    ///////////////
+
+    /// @name iterators
+    /// @{
+
+    /*!
+    @brief returns an iterator to the first element
+
+    Returns an iterator to the first element.
+
+    @image html range-begin-end.svg "Illustration from cppreference.com"
+
+    @return iterator to the first element
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+
+    @liveexample{The following code shows an example for `begin()`.,begin}
+
+    @sa see @ref cbegin() -- returns a const iterator to the beginning
+    @sa see @ref end() -- returns an iterator to the end
+    @sa see @ref cend() -- returns a const iterator to the end
+
+    @since version 1.0.0
+    */
+    iterator begin() noexcept
+    {
+        iterator result(this);
+        result.set_begin();
+        return result;
+    }
+
+    /*!
+    @copydoc basic_json::cbegin()
+    */
+    const_iterator begin() const noexcept
+    {
+        return cbegin();
+    }
+
+    /*!
+    @brief returns a const iterator to the first element
+
+    Returns a const iterator to the first element.
+
+    @image html range-begin-end.svg "Illustration from cppreference.com"
+
+    @return const iterator to the first element
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
+
+    @liveexample{The following code shows an example for `cbegin()`.,cbegin}
+
+    @sa see @ref begin() -- returns an iterator to the beginning
+    @sa see @ref end() -- returns an iterator to the end
+    @sa see @ref cend() -- returns a const iterator to the end
+
+    @since version 1.0.0
+    */
+    const_iterator cbegin() const noexcept
+    {
+        const_iterator result(this);
+        result.set_begin();
+        return result;
+    }
+
+    /*!
+    @brief returns an iterator to one past the last element
+
+    Returns an iterator to one past the last element.
+
+    @image html range-begin-end.svg "Illustration from cppreference.com"
+
+    @return iterator one past the last element
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+
+    @liveexample{The following code shows an example for `end()`.,end}
+
+    @sa see @ref cend() -- returns a const iterator to the end
+    @sa see @ref begin() -- returns an iterator to the beginning
+    @sa see @ref cbegin() -- returns a const iterator to the beginning
+
+    @since version 1.0.0
+    */
+    iterator end() noexcept
+    {
+        iterator result(this);
+        result.set_end();
+        return result;
+    }
+
+    /*!
+    @copydoc basic_json::cend()
+    */
+    const_iterator end() const noexcept
+    {
+        return cend();
+    }
+
+    /*!
+    @brief returns a const iterator to one past the last element
+
+    Returns a const iterator to one past the last element.
+
+    @image html range-begin-end.svg "Illustration from cppreference.com"
+
+    @return const iterator one past the last element
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
+
+    @liveexample{The following code shows an example for `cend()`.,cend}
+
+    @sa see @ref end() -- returns an iterator to the end
+    @sa see @ref begin() -- returns an iterator to the beginning
+    @sa see @ref cbegin() -- returns a const iterator to the beginning
+
+    @since version 1.0.0
+    */
+    const_iterator cend() const noexcept
+    {
+        const_iterator result(this);
+        result.set_end();
+        return result;
+    }
+
+    /*!
+    @brief returns an iterator to the reverse-beginning
+
+    Returns an iterator to the reverse-beginning; that is, the last element.
+
+    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `reverse_iterator(end())`.
+
+    @liveexample{The following code shows an example for `rbegin()`.,rbegin}
+
+    @sa see @ref crbegin() -- returns a const reverse iterator to the beginning
+    @sa see @ref rend() -- returns a reverse iterator to the end
+    @sa see @ref crend() -- returns a const reverse iterator to the end
+
+    @since version 1.0.0
+    */
+    reverse_iterator rbegin() noexcept
+    {
+        return reverse_iterator(end());
+    }
+
+    /*!
+    @copydoc basic_json::crbegin()
+    */
+    const_reverse_iterator rbegin() const noexcept
+    {
+        return crbegin();
+    }
+
+    /*!
+    @brief returns an iterator to the reverse-end
+
+    Returns an iterator to the reverse-end; that is, one before the first
+    element.
+
+    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `reverse_iterator(begin())`.
+
+    @liveexample{The following code shows an example for `rend()`.,rend}
+
+    @sa see @ref crend() -- returns a const reverse iterator to the end
+    @sa see @ref rbegin() -- returns a reverse iterator to the beginning
+    @sa see @ref crbegin() -- returns a const reverse iterator to the beginning
+
+    @since version 1.0.0
+    */
+    reverse_iterator rend() noexcept
+    {
+        return reverse_iterator(begin());
+    }
+
+    /*!
+    @copydoc basic_json::crend()
+    */
+    const_reverse_iterator rend() const noexcept
+    {
+        return crend();
+    }
+
+    /*!
+    @brief returns a const reverse iterator to the last element
+
+    Returns a const iterator to the reverse-beginning; that is, the last
+    element.
+
+    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
+
+    @liveexample{The following code shows an example for `crbegin()`.,crbegin}
+
+    @sa see @ref rbegin() -- returns a reverse iterator to the beginning
+    @sa see @ref rend() -- returns a reverse iterator to the end
+    @sa see @ref crend() -- returns a const reverse iterator to the end
+
+    @since version 1.0.0
+    */
+    const_reverse_iterator crbegin() const noexcept
+    {
+        return const_reverse_iterator(cend());
+    }
+
+    /*!
+    @brief returns a const reverse iterator to one before the first
+
+    Returns a const reverse iterator to the reverse-end; that is, one before
+    the first element.
+
+    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
+
+    @liveexample{The following code shows an example for `crend()`.,crend}
+
+    @sa see @ref rend() -- returns a reverse iterator to the end
+    @sa see @ref rbegin() -- returns a reverse iterator to the beginning
+    @sa see @ref crbegin() -- returns a const reverse iterator to the beginning
+
+    @since version 1.0.0
+    */
+    const_reverse_iterator crend() const noexcept
+    {
+        return const_reverse_iterator(cbegin());
+    }
+
+  public:
+    /*!
+    @brief wrapper to access iterator member functions in range-based for
+
+    This function allows to access @ref iterator::key() and @ref
+    iterator::value() during range-based for loops. In these loops, a
+    reference to the JSON values is returned, so there is no access to the
+    underlying iterator.
+
+    For loop without iterator_wrapper:
+
+    @code{cpp}
+    for (auto it = j_object.begin(); it != j_object.end(); ++it)
+    {
+        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+    }
+    @endcode
+
+    Range-based for loop without iterator proxy:
+
+    @code{cpp}
+    for (auto it : j_object)
+    {
+        // "it" is of type json::reference and has no key() member
+        std::cout << "value: " << it << '\n';
+    }
+    @endcode
+
+    Range-based for loop with iterator proxy:
+
+    @code{cpp}
+    for (auto it : json::iterator_wrapper(j_object))
+    {
+        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+    }
+    @endcode
+
+    @note When iterating over an array, `key()` will return the index of the
+          element as string (see example).
+
+    @param[in] ref  reference to a JSON value
+    @return iteration proxy object wrapping @a ref with an interface to use in
+            range-based for loops
+
+    @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @note The name of this function is not yet final and may change in the
+    future.
+
+    @deprecated This stream operator is deprecated and will be removed in
+                future 4.0.0 of the library. Please use @ref items() instead;
+                that is, replace `json::iterator_wrapper(j)` with `j.items()`.
+    */
+    JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
+    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
+    {
+        return ref.items();
+    }
+
+    /*!
+    @copydoc iterator_wrapper(reference)
+    */
+    JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
+    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
+    {
+        return ref.items();
+    }
+
+    /*!
+    @brief helper to access iterator member functions in range-based for
+
+    This function allows to access @ref iterator::key() and @ref
+    iterator::value() during range-based for loops. In these loops, a
+    reference to the JSON values is returned, so there is no access to the
+    underlying iterator.
+
+    For loop without `items()` function:
+
+    @code{cpp}
+    for (auto it = j_object.begin(); it != j_object.end(); ++it)
+    {
+        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+    }
+    @endcode
+
+    Range-based for loop without `items()` function:
+
+    @code{cpp}
+    for (auto it : j_object)
+    {
+        // "it" is of type json::reference and has no key() member
+        std::cout << "value: " << it << '\n';
+    }
+    @endcode
+
+    Range-based for loop with `items()` function:
+
+    @code{cpp}
+    for (auto& el : j_object.items())
+    {
+        std::cout << "key: " << el.key() << ", value:" << el.value() << '\n';
+    }
+    @endcode
+
+    The `items()` function also allows to use
+    [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding)
+    (C++17):
+
+    @code{cpp}
+    for (auto& [key, val] : j_object.items())
+    {
+        std::cout << "key: " << key << ", value:" << val << '\n';
+    }
+    @endcode
+
+    @note When iterating over an array, `key()` will return the index of the
+          element as string (see example). For primitive types (e.g., numbers),
+          `key()` returns an empty string.
+
+    @warning Using `items()` on temporary objects is dangerous. Make sure the
+             object's lifetime exceeds the iteration. See
+             <https://github.com/nlohmann/json/issues/2040> for more
+             information.
+
+    @return iteration proxy object wrapping @a ref with an interface to use in
+            range-based for loops
+
+    @liveexample{The following code shows how the function is used.,items}
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 3.1.0, structured bindings support since 3.5.0.
+    */
+    iteration_proxy<iterator> items() noexcept
+    {
+        return iteration_proxy<iterator>(*this);
+    }
+
+    /*!
+    @copydoc items()
+    */
+    iteration_proxy<const_iterator> items() const noexcept
+    {
+        return iteration_proxy<const_iterator>(*this);
+    }
+
+    /// @}
+
+
+    //////////////
+    // capacity //
+    //////////////
+
+    /// @name capacity
+    /// @{
+
+    /*!
+    @brief checks whether the container is empty.
+
+    Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
+
+    @return The return value depends on the different types and is
+            defined as follows:
+            Value type  | return value
+            ----------- | -------------
+            null        | `true`
+            boolean     | `false`
+            string      | `false`
+            number      | `false`
+            binary      | `false`
+            object      | result of function `object_t::empty()`
+            array       | result of function `array_t::empty()`
+
+    @liveexample{The following code uses `empty()` to check if a JSON
+    object contains any elements.,empty}
+
+    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+    the Container concept; that is, their `empty()` functions have constant
+    complexity.
+
+    @iterators No changes.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @note This function does not return whether a string stored as JSON value
+    is empty - it returns whether the JSON container itself is empty which is
+    false in the case of a string.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `begin() == end()`.
+
+    @sa see @ref size() -- returns the number of elements
+
+    @since version 1.0.0
+    */
+    bool empty() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::null:
+            {
+                // null values are empty
+                return true;
+            }
+
+            case value_t::array:
+            {
+                // delegate call to array_t::empty()
+                return m_value.array->empty();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::empty()
+                return m_value.object->empty();
+            }
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                // all other types are nonempty
+                return false;
+            }
+        }
+    }
+
+    /*!
+    @brief returns the number of elements
+
+    Returns the number of elements in a JSON value.
+
+    @return The return value depends on the different types and is
+            defined as follows:
+            Value type  | return value
+            ----------- | -------------
+            null        | `0`
+            boolean     | `1`
+            string      | `1`
+            number      | `1`
+            binary      | `1`
+            object      | result of function object_t::size()
+            array       | result of function array_t::size()
+
+    @liveexample{The following code calls `size()` on the different value
+    types.,size}
+
+    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+    the Container concept; that is, their size() functions have constant
+    complexity.
+
+    @iterators No changes.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @note This function does not return the length of a string stored as JSON
+    value - it returns the number of elements in the JSON value which is 1 in
+    the case of a string.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `std::distance(begin(), end())`.
+
+    @sa see @ref empty() -- checks whether the container is empty
+    @sa see @ref max_size() -- returns the maximal number of elements
+
+    @since version 1.0.0
+    */
+    size_type size() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::null:
+            {
+                // null values are empty
+                return 0;
+            }
+
+            case value_t::array:
+            {
+                // delegate call to array_t::size()
+                return m_value.array->size();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::size()
+                return m_value.object->size();
+            }
+
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                // all other types have size 1
+                return 1;
+            }
+        }
+    }
+
+    /*!
+    @brief returns the maximum possible number of elements
+
+    Returns the maximum number of elements a JSON value is able to hold due to
+    system or library implementation limitations, i.e. `std::distance(begin(),
+    end())` for the JSON value.
+
+    @return The return value depends on the different types and is
+            defined as follows:
+            Value type  | return value
+            ----------- | -------------
+            null        | `0` (same as `size()`)
+            boolean     | `1` (same as `size()`)
+            string      | `1` (same as `size()`)
+            number      | `1` (same as `size()`)
+            binary      | `1` (same as `size()`)
+            object      | result of function `object_t::max_size()`
+            array       | result of function `array_t::max_size()`
+
+    @liveexample{The following code calls `max_size()` on the different value
+    types. Note the output is implementation specific.,max_size}
+
+    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+    the Container concept; that is, their `max_size()` functions have constant
+    complexity.
+
+    @iterators No changes.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of returning `b.size()` where `b` is the largest
+      possible JSON value.
+
+    @sa see @ref size() -- returns the number of elements
+
+    @since version 1.0.0
+    */
+    size_type max_size() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::array:
+            {
+                // delegate call to array_t::max_size()
+                return m_value.array->max_size();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::max_size()
+                return m_value.object->max_size();
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                // all other types have max_size() == size()
+                return size();
+            }
+        }
+    }
+
+    /// @}
+
+
+    ///////////////
+    // modifiers //
+    ///////////////
+
+    /// @name modifiers
+    /// @{
+
+    /*!
+    @brief clears the contents
+
+    Clears the content of a JSON value and resets it to the default value as
+    if @ref basic_json(value_t) would have been called with the current value
+    type from @ref type():
+
+    Value type  | initial value
+    ----------- | -------------
+    null        | `null`
+    boolean     | `false`
+    string      | `""`
+    number      | `0`
+    binary      | An empty byte vector
+    object      | `{}`
+    array       | `[]`
+
+    @post Has the same effect as calling
+    @code {.cpp}
+    *this = basic_json(type());
+    @endcode
+
+    @liveexample{The example below shows the effect of `clear()` to different
+    JSON types.,clear}
+
+    @complexity Linear in the size of the JSON value.
+
+    @iterators All iterators, pointers and references related to this container
+               are invalidated.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @sa see @ref basic_json(value_t) -- constructor that creates an object with the
+        same value than calling `clear()`
+
+    @since version 1.0.0
+    */
+    void clear() noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::number_integer:
+            {
+                m_value.number_integer = 0;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value.number_unsigned = 0;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value.number_float = 0.0;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value.boolean = false;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value.string->clear();
+                break;
+            }
+
+            case value_t::binary:
+            {
+                m_value.binary->clear();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value.array->clear();
+                break;
+            }
+
+            case value_t::object:
+            {
+                m_value.object->clear();
+                break;
+            }
+
+            case value_t::null:
+            case value_t::discarded:
+            default:
+                break;
+        }
+    }
+
+    /*!
+    @brief add an object to an array
+
+    Appends the given element @a val to the end of the JSON value. If the
+    function is called on a JSON null value, an empty array is created before
+    appending @a val.
+
+    @param[in] val the value to add to the JSON array
+
+    @throw type_error.308 when called on a type other than JSON array or
+    null; example: `"cannot use push_back() with number"`
+
+    @complexity Amortized constant.
+
+    @liveexample{The example shows how `push_back()` and `+=` can be used to
+    add elements to a JSON array. Note how the `null` value was silently
+    converted to a JSON array.,push_back}
+
+    @since version 1.0.0
+    */
+    void push_back(basic_json&& val)
+    {
+        // push_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+        {
+            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array (move semantics)
+        const auto old_capacity = m_value.array->capacity();
+        m_value.array->push_back(std::move(val));
+        set_parent(m_value.array->back(), old_capacity);
+        // if val is moved from, basic_json move constructor marks it null so we do not call the destructor
+    }
+
+    /*!
+    @brief add an object to an array
+    @copydoc push_back(basic_json&&)
+    */
+    reference operator+=(basic_json&& val)
+    {
+        push_back(std::move(val));
+        return *this;
+    }
+
+    /*!
+    @brief add an object to an array
+    @copydoc push_back(basic_json&&)
+    */
+    void push_back(const basic_json& val)
+    {
+        // push_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+        {
+            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array
+        const auto old_capacity = m_value.array->capacity();
+        m_value.array->push_back(val);
+        set_parent(m_value.array->back(), old_capacity);
+    }
+
+    /*!
+    @brief add an object to an array
+    @copydoc push_back(basic_json&&)
+    */
+    reference operator+=(const basic_json& val)
+    {
+        push_back(val);
+        return *this;
+    }
+
+    /*!
+    @brief add an object to an object
+
+    Inserts the given element @a val to the JSON object. If the function is
+    called on a JSON null value, an empty object is created before inserting
+    @a val.
+
+    @param[in] val the value to add to the JSON object
+
+    @throw type_error.308 when called on a type other than JSON object or
+    null; example: `"cannot use push_back() with number"`
+
+    @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+    @liveexample{The example shows how `push_back()` and `+=` can be used to
+    add elements to a JSON object. Note how the `null` value was silently
+    converted to a JSON object.,push_back__object_t__value}
+
+    @since version 1.0.0
+    */
+    void push_back(const typename object_t::value_type& val)
+    {
+        // push_back only works for null objects or objects
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
+        {
+            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+        }
+
+        // transform null object into an object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // add element to object
+        auto res = m_value.object->insert(val);
+        set_parent(res.first->second);
+    }
+
+    /*!
+    @brief add an object to an object
+    @copydoc push_back(const typename object_t::value_type&)
+    */
+    reference operator+=(const typename object_t::value_type& val)
+    {
+        push_back(val);
+        return *this;
+    }
+
+    /*!
+    @brief add an object to an object
+
+    This function allows to use `push_back` with an initializer list. In case
+
+    1. the current value is an object,
+    2. the initializer list @a init contains only two elements, and
+    3. the first element of @a init is a string,
+
+    @a init is converted into an object element and added using
+    @ref push_back(const typename object_t::value_type&). Otherwise, @a init
+    is converted to a JSON value and added using @ref push_back(basic_json&&).
+
+    @param[in] init  an initializer list
+
+    @complexity Linear in the size of the initializer list @a init.
+
+    @note This function is required to resolve an ambiguous overload error,
+          because pairs like `{"key", "value"}` can be both interpreted as
+          `object_t::value_type` or `std::initializer_list<basic_json>`, see
+          https://github.com/nlohmann/json/issues/235 for more information.
+
+    @liveexample{The example shows how initializer lists are treated as
+    objects when possible.,push_back__initializer_list}
+    */
+    void push_back(initializer_list_t init)
+    {
+        if (is_object() && init.size() == 2 && (*init.begin())->is_string())
+        {
+            basic_json&& key = init.begin()->moved_or_copied();
+            push_back(typename object_t::value_type(
+                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
+        }
+        else
+        {
+            push_back(basic_json(init));
+        }
+    }
+
+    /*!
+    @brief add an object to an object
+    @copydoc push_back(initializer_list_t)
+    */
+    reference operator+=(initializer_list_t init)
+    {
+        push_back(init);
+        return *this;
+    }
+
+    /*!
+    @brief add an object to an array
+
+    Creates a JSON value from the passed parameters @a args to the end of the
+    JSON value. If the function is called on a JSON null value, an empty array
+    is created before appending the value created from @a args.
+
+    @param[in] args arguments to forward to a constructor of @ref basic_json
+    @tparam Args compatible types to create a @ref basic_json object
+
+    @return reference to the inserted element
+
+    @throw type_error.311 when called on a type other than JSON array or
+    null; example: `"cannot use emplace_back() with number"`
+
+    @complexity Amortized constant.
+
+    @liveexample{The example shows how `push_back()` can be used to add
+    elements to a JSON array. Note how the `null` value was silently converted
+    to a JSON array.,emplace_back}
+
+    @since version 2.0.8, returns reference since 3.7.0
+    */
+    template<class... Args>
+    reference emplace_back(Args&& ... args)
+    {
+        // emplace_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+        {
+            JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        const auto old_capacity = m_value.array->capacity();
+        m_value.array->emplace_back(std::forward<Args>(args)...);
+        return set_parent(m_value.array->back(), old_capacity);
+    }
+
+    /*!
+    @brief add an object to an object if key does not exist
+
+    Inserts a new element into a JSON object constructed in-place with the
+    given @a args if there is no element with the key in the container. If the
+    function is called on a JSON null value, an empty object is created before
+    appending the value created from @a args.
+
+    @param[in] args arguments to forward to a constructor of @ref basic_json
+    @tparam Args compatible types to create a @ref basic_json object
+
+    @return a pair consisting of an iterator to the inserted element, or the
+            already-existing element if no insertion happened, and a bool
+            denoting whether the insertion took place.
+
+    @throw type_error.311 when called on a type other than JSON object or
+    null; example: `"cannot use emplace() with number"`
+
+    @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+    @liveexample{The example shows how `emplace()` can be used to add elements
+    to a JSON object. Note how the `null` value was silently converted to a
+    JSON object. Further note how no value is added if there was already one
+    value stored with the same key.,emplace}
+
+    @since version 2.0.8
+    */
+    template<class... Args>
+    std::pair<iterator, bool> emplace(Args&& ... args)
+    {
+        // emplace only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
+        {
+            JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
+        }
+
+        // transform null object into an object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        auto res = m_value.object->emplace(std::forward<Args>(args)...);
+        set_parent(res.first->second);
+
+        // create result iterator and set iterator to the result of emplace
+        auto it = begin();
+        it.m_it.object_iterator = res.first;
+
+        // return pair of iterator and boolean
+        return {it, res.second};
+    }
+
+    /// Helper for insertion of an iterator
+    /// @note: This uses std::distance to support GCC 4.8,
+    ///        see https://github.com/nlohmann/json/pull/1257
+    template<typename... Args>
+    iterator insert_iterator(const_iterator pos, Args&& ... args)
+    {
+        iterator result(this);
+        JSON_ASSERT(m_value.array != nullptr);
+
+        auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
+        m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
+        result.m_it.array_iterator = m_value.array->begin() + insert_pos;
+
+        // This could have been written as:
+        // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
+        // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
+
+        set_parents();
+        return result;
+    }
+
+    /*!
+    @brief inserts element
+
+    Inserts element @a val before iterator @a pos.
+
+    @param[in] pos iterator before which the content will be inserted; may be
+    the end() iterator
+    @param[in] val element to insert
+    @return iterator pointing to the inserted @a val.
+
+    @throw type_error.309 if called on JSON values other than arrays;
+    example: `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+    example: `"iterator does not fit current value"`
+
+    @complexity Constant plus linear in the distance between @a pos and end of
+    the container.
+
+    @liveexample{The example shows how `insert()` is used.,insert}
+
+    @since version 1.0.0
+    */
+    iterator insert(const_iterator pos, const basic_json& val)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // check if iterator pos fits to this JSON value
+            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+            {
+                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+            }
+
+            // insert to array and return iterator
+            return insert_iterator(pos, val);
+        }
+
+        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief inserts element
+    @copydoc insert(const_iterator, const basic_json&)
+    */
+    iterator insert(const_iterator pos, basic_json&& val)
+    {
+        return insert(pos, val);
+    }
+
+    /*!
+    @brief inserts elements
+
+    Inserts @a cnt copies of @a val before iterator @a pos.
+
+    @param[in] pos iterator before which the content will be inserted; may be
+    the end() iterator
+    @param[in] cnt number of copies of @a val to insert
+    @param[in] val element to insert
+    @return iterator pointing to the first element inserted, or @a pos if
+    `cnt==0`
+
+    @throw type_error.309 if called on JSON values other than arrays; example:
+    `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+    example: `"iterator does not fit current value"`
+
+    @complexity Linear in @a cnt plus linear in the distance between @a pos
+    and end of the container.
+
+    @liveexample{The example shows how `insert()` is used.,insert__count}
+
+    @since version 1.0.0
+    */
+    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // check if iterator pos fits to this JSON value
+            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+            {
+                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+            }
+
+            // insert to array and return iterator
+            return insert_iterator(pos, cnt, val);
+        }
+
+        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+    }
+
+    /*!
+    @brief inserts elements
+
+    Inserts elements from range `[first, last)` before iterator @a pos.
+
+    @param[in] pos iterator before which the content will be inserted; may be
+    the end() iterator
+    @param[in] first begin of the range of elements to insert
+    @param[in] last end of the range of elements to insert
+
+    @throw type_error.309 if called on JSON values other than arrays; example:
+    `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+    example: `"iterator does not fit current value"`
+    @throw invalid_iterator.210 if @a first and @a last do not belong to the
+    same JSON value; example: `"iterators do not fit"`
+    @throw invalid_iterator.211 if @a first or @a last are iterators into
+    container for which insert is called; example: `"passed iterators may not
+    belong to container"`
+
+    @return iterator pointing to the first element inserted, or @a pos if
+    `first==last`
+
+    @complexity Linear in `std::distance(first, last)` plus linear in the
+    distance between @a pos and end of the container.
+
+    @liveexample{The example shows how `insert()` is used.,insert__range}
+
+    @since version 1.0.0
+    */
+    iterator insert(const_iterator pos, const_iterator first, const_iterator last)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_UNLIKELY(!is_array()))
+        {
+            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+        }
+
+        // check if iterator pos fits to this JSON value
+        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
+        {
+            JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
+        }
+
+        // insert to array and return iterator
+        return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
+    }
+
+    /*!
+    @brief inserts elements
+
+    Inserts elements from initializer list @a ilist before iterator @a pos.
+
+    @param[in] pos iterator before which the content will be inserted; may be
+    the end() iterator
+    @param[in] ilist initializer list to insert the values from
+
+    @throw type_error.309 if called on JSON values other than arrays; example:
+    `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+    example: `"iterator does not fit current value"`
+
+    @return iterator pointing to the first element inserted, or @a pos if
+    `ilist` is empty
+
+    @complexity Linear in `ilist.size()` plus linear in the distance between
+    @a pos and end of the container.
+
+    @liveexample{The example shows how `insert()` is used.,insert__ilist}
+
+    @since version 1.0.0
+    */
+    iterator insert(const_iterator pos, initializer_list_t ilist)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_UNLIKELY(!is_array()))
+        {
+            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+        }
+
+        // check if iterator pos fits to this JSON value
+        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+        }
+
+        // insert to array and return iterator
+        return insert_iterator(pos, ilist.begin(), ilist.end());
+    }
+
+    /*!
+    @brief inserts elements
+
+    Inserts elements from range `[first, last)`.
+
+    @param[in] first begin of the range of elements to insert
+    @param[in] last end of the range of elements to insert
+
+    @throw type_error.309 if called on JSON values other than objects; example:
+    `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if iterator @a first or @a last does does not
+    point to an object; example: `"iterators first and last must point to
+    objects"`
+    @throw invalid_iterator.210 if @a first and @a last do not belong to the
+    same JSON value; example: `"iterators do not fit"`
+
+    @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
+    of elements to insert.
+
+    @liveexample{The example shows how `insert()` is used.,insert__range_object}
+
+    @since version 3.0.0
+    */
+    void insert(const_iterator first, const_iterator last)
+    {
+        // insert only works for objects
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+        }
+
+        // passed iterators must belong to objects
+        if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
+        }
+
+        m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
+    }
+
+    /*!
+    @brief updates a JSON object from another object, overwriting existing keys
+
+    Inserts all values from JSON object @a j and overwrites existing keys.
+
+    @param[in] j  JSON object to read values from
+    @param[in] merge_objects  when true, existing keys are not overwritten, but
+                              contents of objects are merged recursively
+                              (default: false)
+
+    @throw type_error.312 if called on JSON values other than objects; example:
+    `"cannot use update() with string"`
+
+    @complexity O(N*log(size() + N)), where N is the number of elements to
+                insert.
+
+    @liveexample{The example shows how `update()` is used.,update}
+
+    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
+
+    @since version 3.0.0, `merge_objects` parameter added in 3.10.4.
+    */
+    void update(const_reference j, bool merge_objects = false)
+    {
+        update(j.begin(), j.end(), merge_objects);
+    }
+
+    /*!
+    @brief updates a JSON object from another object, overwriting existing keys
+
+    Inserts all values from from range `[first, last)` and overwrites existing
+    keys.
+
+    @param[in] first begin of the range of elements to insert
+    @param[in] last end of the range of elements to insert
+    @param[in] merge_objects  when true, existing keys are not overwritten, but
+                              contents of objects are merged recursively
+                              (default: false)
+
+    @throw type_error.312 if called on JSON values other than objects; example:
+    `"cannot use update() with string"`
+    @throw type_error.312 if iterator @a first or @a last does does not
+    point to an object; example: `"cannot use update() with string"`
+    @throw invalid_iterator.210 if @a first and @a last do not belong to the
+    same JSON value; example: `"iterators do not fit"`
+
+    @complexity O(N*log(size() + N)), where N is the number of elements to
+                insert.
+
+    @liveexample{The example shows how `update()` is used__range.,update}
+
+    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
+
+    @since version 3.0.0, `merge_objects` parameter added in 3.10.4.
+    */
+    void update(const_iterator first, const_iterator last, bool merge_objects = false)
+    {
+        // implicitly convert null value to an empty object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value.object = create<object_t>();
+            assert_invariant();
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(!is_object()))
+        {
+            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+        }
+
+        // passed iterators must belong to objects
+        if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
+        {
+            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object));
+        }
+
+        for (auto it = first; it != last; ++it)
+        {
+            if (merge_objects && it.value().is_object())
+            {
+                auto it2 = m_value.object->find(it.key());
+                if (it2 != m_value.object->end())
+                {
+                    it2->second.update(it.value(), true);
+                    continue;
+                }
+            }
+            m_value.object->operator[](it.key()) = it.value();
+#if JSON_DIAGNOSTICS
+            m_value.object->operator[](it.key()).m_parent = this;
+#endif
+        }
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of the JSON value with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other JSON value to exchange the contents with
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how JSON values can be swapped with
+    `swap()`.,swap__reference}
+
+    @since version 1.0.0
+    */
+    void swap(reference other) noexcept (
+        std::is_nothrow_move_constructible<value_t>::value&&
+        std::is_nothrow_move_assignable<value_t>::value&&
+        std::is_nothrow_move_constructible<json_value>::value&&
+        std::is_nothrow_move_assignable<json_value>::value
+    )
+    {
+        std::swap(m_type, other.m_type);
+        std::swap(m_value, other.m_value);
+
+        set_parents();
+        other.set_parents();
+        assert_invariant();
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of the JSON value from @a left with those of @a right. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated. implemented as a friend function callable via ADL.
+
+    @param[in,out] left JSON value to exchange the contents with
+    @param[in,out] right JSON value to exchange the contents with
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how JSON values can be swapped with
+    `swap()`.,swap__reference}
+
+    @since version 1.0.0
+    */
+    friend void swap(reference left, reference right) noexcept (
+        std::is_nothrow_move_constructible<value_t>::value&&
+        std::is_nothrow_move_assignable<value_t>::value&&
+        std::is_nothrow_move_constructible<json_value>::value&&
+        std::is_nothrow_move_assignable<json_value>::value
+    )
+    {
+        left.swap(right);
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of a JSON array with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other array to exchange the contents with
+
+    @throw type_error.310 when JSON value is not an array; example: `"cannot
+    use swap() with string"`
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how arrays can be swapped with
+    `swap()`.,swap__array_t}
+
+    @since version 1.0.0
+    */
+    void swap(array_t& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            std::swap(*(m_value.array), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of a JSON object with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other object to exchange the contents with
+
+    @throw type_error.310 when JSON value is not an object; example:
+    `"cannot use swap() with string"`
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how objects can be swapped with
+    `swap()`.,swap__object_t}
+
+    @since version 1.0.0
+    */
+    void swap(object_t& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            std::swap(*(m_value.object), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of a JSON string with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other string to exchange the contents with
+
+    @throw type_error.310 when JSON value is not a string; example: `"cannot
+    use swap() with boolean"`
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how strings can be swapped with
+    `swap()`.,swap__string_t}
+
+    @since version 1.0.0
+    */
+    void swap(string_t& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for strings
+        if (JSON_HEDLEY_LIKELY(is_string()))
+        {
+            std::swap(*(m_value.string), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of a JSON string with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other binary to exchange the contents with
+
+    @throw type_error.310 when JSON value is not a string; example: `"cannot
+    use swap() with boolean"`
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how strings can be swapped with
+    `swap()`.,swap__binary_t}
+
+    @since version 3.8.0
+    */
+    void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for strings
+        if (JSON_HEDLEY_LIKELY(is_binary()))
+        {
+            std::swap(*(m_value.binary), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /// @copydoc swap(binary_t&)
+    void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
+    {
+        // swap only works for strings
+        if (JSON_HEDLEY_LIKELY(is_binary()))
+        {
+            std::swap(*(m_value.binary), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+        }
+    }
+
+    /// @}
+
+  public:
+    //////////////////////////////////////////
+    // lexicographical comparison operators //
+    //////////////////////////////////////////
+
+    /// @name lexicographical comparison operators
+    /// @{
+
+    /*!
+    @brief comparison: equal
+
+    Compares two JSON values for equality according to the following rules:
+    - Two JSON values are equal if (1) they are from the same type and (2)
+      their stored values are the same according to their respective
+      `operator==`.
+    - Integer and floating-point numbers are automatically converted before
+      comparison. Note that two NaN values are always treated as unequal.
+    - Two JSON null values are equal.
+
+    @note Floating-point inside JSON values numbers are compared with
+    `json::number_float_t::operator==` which is `double::operator==` by
+    default. To compare floating-point while respecting an epsilon, an alternative
+    [comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39)
+    could be used, for instance
+    @code {.cpp}
+    template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
+    inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
+    {
+        return std::abs(a - b) <= epsilon;
+    }
+    @endcode
+    Or you can self-defined operator equal function like this:
+    @code {.cpp}
+    bool my_equal(const_reference lhs, const_reference rhs) {
+    const auto lhs_type lhs.type();
+    const auto rhs_type rhs.type();
+    if (lhs_type == rhs_type) {
+        switch(lhs_type)
+            // self_defined case
+            case value_t::number_float:
+                return std::abs(lhs - rhs) <= std::numeric_limits<float>::epsilon();
+            // other cases remain the same with the original
+            ...
+    }
+    ...
+    }
+    @endcode
+
+    @note NaN values never compare equal to themselves or to other NaN values.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether the values @a lhs and @a rhs are equal
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @complexity Linear.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__equal}
+
+    @since version 1.0.0
+    */
+    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
+    {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+        const auto lhs_type = lhs.type();
+        const auto rhs_type = rhs.type();
+
+        if (lhs_type == rhs_type)
+        {
+            switch (lhs_type)
+            {
+                case value_t::array:
+                    return *lhs.m_value.array == *rhs.m_value.array;
+
+                case value_t::object:
+                    return *lhs.m_value.object == *rhs.m_value.object;
+
+                case value_t::null:
+                    return true;
+
+                case value_t::string:
+                    return *lhs.m_value.string == *rhs.m_value.string;
+
+                case value_t::boolean:
+                    return lhs.m_value.boolean == rhs.m_value.boolean;
+
+                case value_t::number_integer:
+                    return lhs.m_value.number_integer == rhs.m_value.number_integer;
+
+                case value_t::number_unsigned:
+                    return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
+
+                case value_t::number_float:
+                    return lhs.m_value.number_float == rhs.m_value.number_float;
+
+                case value_t::binary:
+                    return *lhs.m_value.binary == *rhs.m_value.binary;
+
+                case value_t::discarded:
+                default:
+                    return false;
+            }
+        }
+        else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
+        {
+            return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
+        }
+        else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
+        {
+            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
+        }
+        else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+        }
+
+        return false;
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+    }
+
+    /*!
+    @brief comparison: equal
+    @copydoc operator==(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs == basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: equal
+    @copydoc operator==(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) == rhs;
+    }
+
+    /*!
+    @brief comparison: not equal
+
+    Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether the values @a lhs and @a rhs are not equal
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__notequal}
+
+    @since version 1.0.0
+    */
+    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
+    {
+        return !(lhs == rhs);
+    }
+
+    /*!
+    @brief comparison: not equal
+    @copydoc operator!=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs != basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: not equal
+    @copydoc operator!=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) != rhs;
+    }
+
+    /*!
+    @brief comparison: less than
+
+    Compares whether one JSON value @a lhs is less than another JSON value @a
+    rhs according to the following rules:
+    - If @a lhs and @a rhs have the same type, the values are compared using
+      the default `<` operator.
+    - Integer and floating-point numbers are automatically converted before
+      comparison
+    - In case @a lhs and @a rhs have different types, the values are ignored
+      and the order of the types is considered, see
+      @ref operator<(const value_t, const value_t).
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether @a lhs is less than @a rhs
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__less}
+
+    @since version 1.0.0
+    */
+    friend bool operator<(const_reference lhs, const_reference rhs) noexcept
+    {
+        const auto lhs_type = lhs.type();
+        const auto rhs_type = rhs.type();
+
+        if (lhs_type == rhs_type)
+        {
+            switch (lhs_type)
+            {
+                case value_t::array:
+                    // note parentheses are necessary, see
+                    // https://github.com/nlohmann/json/issues/1530
+                    return (*lhs.m_value.array) < (*rhs.m_value.array);
+
+                case value_t::object:
+                    return (*lhs.m_value.object) < (*rhs.m_value.object);
+
+                case value_t::null:
+                    return false;
+
+                case value_t::string:
+                    return (*lhs.m_value.string) < (*rhs.m_value.string);
+
+                case value_t::boolean:
+                    return (lhs.m_value.boolean) < (rhs.m_value.boolean);
+
+                case value_t::number_integer:
+                    return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
+
+                case value_t::number_unsigned:
+                    return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
+
+                case value_t::number_float:
+                    return (lhs.m_value.number_float) < (rhs.m_value.number_float);
+
+                case value_t::binary:
+                    return (*lhs.m_value.binary) < (*rhs.m_value.binary);
+
+                case value_t::discarded:
+                default:
+                    return false;
+            }
+        }
+        else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
+        {
+            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
+        }
+        else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
+        {
+            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
+        }
+
+        // We only reach this line if we cannot compare values. In that case,
+        // we compare types. Note we have to call the operator explicitly,
+        // because MSVC has problems otherwise.
+        return operator<(lhs_type, rhs_type);
+    }
+
+    /*!
+    @brief comparison: less than
+    @copydoc operator<(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs < basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: less than
+    @copydoc operator<(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) < rhs;
+    }
+
+    /*!
+    @brief comparison: less than or equal
+
+    Compares whether one JSON value @a lhs is less than or equal to another
+    JSON value by calculating `not (rhs < lhs)`.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether @a lhs is less than or equal to @a rhs
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__greater}
+
+    @since version 1.0.0
+    */
+    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
+    {
+        return !(rhs < lhs);
+    }
+
+    /*!
+    @brief comparison: less than or equal
+    @copydoc operator<=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs <= basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: less than or equal
+    @copydoc operator<=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) <= rhs;
+    }
+
+    /*!
+    @brief comparison: greater than
+
+    Compares whether one JSON value @a lhs is greater than another
+    JSON value by calculating `not (lhs <= rhs)`.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether @a lhs is greater than to @a rhs
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__lessequal}
+
+    @since version 1.0.0
+    */
+    friend bool operator>(const_reference lhs, const_reference rhs) noexcept
+    {
+        return !(lhs <= rhs);
+    }
+
+    /*!
+    @brief comparison: greater than
+    @copydoc operator>(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs > basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: greater than
+    @copydoc operator>(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) > rhs;
+    }
+
+    /*!
+    @brief comparison: greater than or equal
+
+    Compares whether one JSON value @a lhs is greater than or equal to another
+    JSON value by calculating `not (lhs < rhs)`.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether @a lhs is greater than or equal to @a rhs
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__greaterequal}
+
+    @since version 1.0.0
+    */
+    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
+    {
+        return !(lhs < rhs);
+    }
+
+    /*!
+    @brief comparison: greater than or equal
+    @copydoc operator>=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
+    {
+        return lhs >= basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: greater than or equal
+    @copydoc operator>=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) >= rhs;
+    }
+
+    /// @}
+
+    ///////////////////
+    // serialization //
+    ///////////////////
+
+    /// @name serialization
+    /// @{
+#ifndef JSON_NO_IO
+    /*!
+    @brief serialize to stream
+
+    Serialize the given JSON value @a j to the output stream @a o. The JSON
+    value will be serialized using the @ref dump member function.
+
+    - The indentation of the output can be controlled with the member variable
+      `width` of the output stream @a o. For instance, using the manipulator
+      `std::setw(4)` on @a o sets the indentation level to `4` and the
+      serialization result is the same as calling `dump(4)`.
+
+    - The indentation character can be controlled with the member variable
+      `fill` of the output stream @a o. For instance, the manipulator
+      `std::setfill('\\t')` sets indentation to use a tab character rather than
+      the default space character.
+
+    @param[in,out] o  stream to serialize to
+    @param[in] j  JSON value to serialize
+
+    @return the stream @a o
+
+    @throw type_error.316 if a string stored inside the JSON value is not
+                          UTF-8 encoded
+
+    @complexity Linear.
+
+    @liveexample{The example below shows the serialization with different
+    parameters to `width` to adjust the indentation level.,operator_serialize}
+
+    @since version 1.0.0; indentation character added in version 3.0.0
+    */
+    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
+    {
+        // read width member and use it as indentation parameter if nonzero
+        const bool pretty_print = o.width() > 0;
+        const auto indentation = pretty_print ? o.width() : 0;
+
+        // reset width to 0 for subsequent calls to this stream
+        o.width(0);
+
+        // do the actual serialization
+        serializer s(detail::output_adapter<char>(o), o.fill());
+        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
+        return o;
+    }
+
+    /*!
+    @brief serialize to stream
+    @deprecated This stream operator is deprecated and will be removed in
+                future 4.0.0 of the library. Please use
+                @ref operator<<(std::ostream&, const basic_json&)
+                instead; that is, replace calls like `j >> o;` with `o << j;`.
+    @since version 1.0.0; deprecated since version 3.0.0
+    */
+    JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
+    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
+    {
+        return o << j;
+    }
+#endif  // JSON_NO_IO
+    /// @}
+
+
+    /////////////////////
+    // deserialization //
+    /////////////////////
+
+    /// @name deserialization
+    /// @{
+
+    /*!
+    @brief deserialize from a compatible input
+
+    @tparam InputType A compatible input, for instance
+    - an std::istream object
+    - a FILE pointer
+    - a C-style array of characters
+    - a pointer to a null-terminated string of single byte characters
+    - an object obj for which begin(obj) and end(obj) produces a valid pair of
+      iterators.
+
+    @param[in] i  input to read from
+    @param[in] cb  a parser callback function of type @ref parser_callback_t
+    which is used to control the deserialization by filtering unwanted values
+    (optional)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+    @param[in] ignore_comments  whether comments should be ignored and treated
+    like whitespace (true) or yield a parse error (true); (optional, false by
+    default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+    of input; expected string literal""`
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+
+    @complexity Linear in the length of the input. The parser is a predictive
+    LL(1) parser. The complexity can be higher if the parser callback function
+    @a cb or reading from the input @a i has a super-linear complexity.
+
+    @note A UTF-8 byte order mark is silently ignored.
+
+    @liveexample{The example below demonstrates the `parse()` function reading
+    from an array.,parse__array__parser_callback_t}
+
+    @liveexample{The example below demonstrates the `parse()` function with
+    and without callback function.,parse__string__parser_callback_t}
+
+    @liveexample{The example below demonstrates the `parse()` function with
+    and without callback function.,parse__istream__parser_callback_t}
+
+    @liveexample{The example below demonstrates the `parse()` function reading
+    from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
+
+    @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to
+    ignore comments.
+    */
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json parse(InputType&& i,
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true,
+                            const bool ignore_comments = false)
+    {
+        basic_json result;
+        parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
+        return result;
+    }
+
+    /*!
+    @brief deserialize from a pair of character iterators
+
+    The value_type of the iterator must be a integral type with size of 1, 2 or
+    4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32.
+
+    @param[in] first iterator to start of character range
+    @param[in] last  iterator to end of character range
+    @param[in] cb  a parser callback function of type @ref parser_callback_t
+    which is used to control the deserialization by filtering unwanted values
+    (optional)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+    @param[in] ignore_comments  whether comments should be ignored and treated
+    like whitespace (true) or yield a parse error (true); (optional, false by
+    default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+    of input; expected string literal""`
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+    */
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json parse(IteratorType first,
+                            IteratorType last,
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true,
+                            const bool ignore_comments = false)
+    {
+        basic_json result;
+        parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
+        return result;
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
+    static basic_json parse(detail::span_input_adapter&& i,
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true,
+                            const bool ignore_comments = false)
+    {
+        basic_json result;
+        parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
+        return result;
+    }
+
+    /*!
+    @brief check if the input is valid JSON
+
+    Unlike the @ref parse(InputType&&, const parser_callback_t,const bool)
+    function, this function neither throws an exception in case of invalid JSON
+    input (i.e., a parse error) nor creates diagnostic information.
+
+    @tparam InputType A compatible input, for instance
+    - an std::istream object
+    - a FILE pointer
+    - a C-style array of characters
+    - a pointer to a null-terminated string of single byte characters
+    - an object obj for which begin(obj) and end(obj) produces a valid pair of
+      iterators.
+
+    @param[in] i input to read from
+    @param[in] ignore_comments  whether comments should be ignored and treated
+    like whitespace (true) or yield a parse error (true); (optional, false by
+    default)
+
+    @return Whether the input read from @a i is valid JSON.
+
+    @complexity Linear in the length of the input. The parser is a predictive
+    LL(1) parser.
+
+    @note A UTF-8 byte order mark is silently ignored.
+
+    @liveexample{The example below demonstrates the `accept()` function reading
+    from a string.,accept__string}
+    */
+    template<typename InputType>
+    static bool accept(InputType&& i,
+                       const bool ignore_comments = false)
+    {
+        return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
+    }
+
+    template<typename IteratorType>
+    static bool accept(IteratorType first, IteratorType last,
+                       const bool ignore_comments = false)
+    {
+        return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
+    static bool accept(detail::span_input_adapter&& i,
+                       const bool ignore_comments = false)
+    {
+        return parser(i.get(), nullptr, false, ignore_comments).accept(true);
+    }
+
+    /*!
+    @brief generate SAX events
+
+    The SAX event lister must follow the interface of @ref json_sax.
+
+    This function reads from a compatible input. Examples are:
+    - an std::istream object
+    - a FILE pointer
+    - a C-style array of characters
+    - a pointer to a null-terminated string of single byte characters
+    - an object obj for which begin(obj) and end(obj) produces a valid pair of
+      iterators.
+
+    @param[in] i  input to read from
+    @param[in,out] sax  SAX event listener
+    @param[in] format  the format to parse (JSON, CBOR, MessagePack, or UBJSON)
+    @param[in] strict  whether the input has to be consumed completely
+    @param[in] ignore_comments  whether comments should be ignored and treated
+    like whitespace (true) or yield a parse error (true); (optional, false by
+    default); only applies to the JSON file format.
+
+    @return return value of the last processed SAX event
+
+    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+    of input; expected string literal""`
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+
+    @complexity Linear in the length of the input. The parser is a predictive
+    LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
+    a super-linear complexity.
+
+    @note A UTF-8 byte order mark is silently ignored.
+
+    @liveexample{The example below demonstrates the `sax_parse()` function
+    reading from string and processing the events with a user-defined SAX
+    event consumer.,sax_parse}
+
+    @since version 3.2.0
+    */
+    template <typename InputType, typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    static bool sax_parse(InputType&& i, SAX* sax,
+                          input_format_t format = input_format_t::json,
+                          const bool strict = true,
+                          const bool ignore_comments = false)
+    {
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        return format == input_format_t::json
+               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+    }
+
+    template<class IteratorType, class SAX>
+    JSON_HEDLEY_NON_NULL(3)
+    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
+                          input_format_t format = input_format_t::json,
+                          const bool strict = true,
+                          const bool ignore_comments = false)
+    {
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        return format == input_format_t::json
+               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+    }
+
+    template <typename SAX>
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
+    JSON_HEDLEY_NON_NULL(2)
+    static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
+                          input_format_t format = input_format_t::json,
+                          const bool strict = true,
+                          const bool ignore_comments = false)
+    {
+        auto ia = i.get();
+        return format == input_format_t::json
+               // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+               // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+    }
+#ifndef JSON_NO_IO
+    /*!
+    @brief deserialize from stream
+    @deprecated This stream operator is deprecated and will be removed in
+                version 4.0.0 of the library. Please use
+                @ref operator>>(std::istream&, basic_json&)
+                instead; that is, replace calls like `j << i;` with `i >> j;`.
+    @since version 1.0.0; deprecated since version 3.0.0
+    */
+    JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
+    friend std::istream& operator<<(basic_json& j, std::istream& i)
+    {
+        return operator>>(i, j);
+    }
+
+    /*!
+    @brief deserialize from stream
+
+    Deserializes an input stream to a JSON value.
+
+    @param[in,out] i  input stream to read a serialized JSON value from
+    @param[in,out] j  JSON value to write the deserialized input to
+
+    @throw parse_error.101 in case of an unexpected token
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+
+    @complexity Linear in the length of the input. The parser is a predictive
+    LL(1) parser.
+
+    @note A UTF-8 byte order mark is silently ignored.
+
+    @liveexample{The example below shows how a JSON value is constructed by
+    reading a serialization from a stream.,operator_deserialize}
+
+    @sa parse(std::istream&, const parser_callback_t) for a variant with a
+    parser callback function to filter values while parsing
+
+    @since version 1.0.0
+    */
+    friend std::istream& operator>>(std::istream& i, basic_json& j)
+    {
+        parser(detail::input_adapter(i)).parse(false, j);
+        return i;
+    }
+#endif  // JSON_NO_IO
+    /// @}
+
+    ///////////////////////////
+    // convenience functions //
+    ///////////////////////////
+
+    /*!
+    @brief return the type as string
+
+    Returns the type name as string to be used in error messages - usually to
+    indicate that a function was called on a wrong JSON type.
+
+    @return a string representation of a the @a m_type member:
+            Value type  | return value
+            ----------- | -------------
+            null        | `"null"`
+            boolean     | `"boolean"`
+            string      | `"string"`
+            number      | `"number"` (for all number types)
+            object      | `"object"`
+            array       | `"array"`
+            binary      | `"binary"`
+            discarded   | `"discarded"`
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @complexity Constant.
+
+    @liveexample{The following code exemplifies `type_name()` for all JSON
+    types.,type_name}
+
+    @sa see @ref type() -- return the type of the JSON value
+    @sa see @ref operator value_t() -- return the type of the JSON value (implicit)
+
+    @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
+    since 3.0.0
+    */
+    JSON_HEDLEY_RETURNS_NON_NULL
+    const char* type_name() const noexcept
+    {
+        {
+            switch (m_type)
+            {
+                case value_t::null:
+                    return "null";
+                case value_t::object:
+                    return "object";
+                case value_t::array:
+                    return "array";
+                case value_t::string:
+                    return "string";
+                case value_t::boolean:
+                    return "boolean";
+                case value_t::binary:
+                    return "binary";
+                case value_t::discarded:
+                    return "discarded";
+                case value_t::number_integer:
+                case value_t::number_unsigned:
+                case value_t::number_float:
+                default:
+                    return "number";
+            }
+        }
+    }
+
+
+  JSON_PRIVATE_UNLESS_TESTED:
+    //////////////////////
+    // member variables //
+    //////////////////////
+
+    /// the type of the current element
+    value_t m_type = value_t::null;
+
+    /// the value of the current element
+    json_value m_value = {};
+
+#if JSON_DIAGNOSTICS
+    /// a pointer to a parent value (for debugging purposes)
+    basic_json* m_parent = nullptr;
+#endif
+
+    //////////////////////////////////////////
+    // binary serialization/deserialization //
+    //////////////////////////////////////////
+
+    /// @name binary serialization/deserialization support
+    /// @{
+
+  public:
+    /*!
+    @brief create a CBOR serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
+    Binary Object Representation) serialization format. CBOR is a binary
+    serialization format which aims to be more compact than JSON itself, yet
+    more efficient to parse.
+
+    The library uses the following mapping from JSON values types to
+    CBOR types according to the CBOR specification (RFC 7049):
+
+    JSON value type | value/range                                | CBOR type                          | first byte
+    --------------- | ------------------------------------------ | ---------------------------------- | ---------------
+    null            | `null`                                     | Null                               | 0xF6
+    boolean         | `true`                                     | True                               | 0xF5
+    boolean         | `false`                                    | False                              | 0xF4
+    number_integer  | -9223372036854775808..-2147483649          | Negative integer (8 bytes follow)  | 0x3B
+    number_integer  | -2147483648..-32769                        | Negative integer (4 bytes follow)  | 0x3A
+    number_integer  | -32768..-129                               | Negative integer (2 bytes follow)  | 0x39
+    number_integer  | -128..-25                                  | Negative integer (1 byte follow)   | 0x38
+    number_integer  | -24..-1                                    | Negative integer                   | 0x20..0x37
+    number_integer  | 0..23                                      | Integer                            | 0x00..0x17
+    number_integer  | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
+    number_integer  | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
+    number_integer  | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
+    number_integer  | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
+    number_unsigned | 0..23                                      | Integer                            | 0x00..0x17
+    number_unsigned | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
+    number_unsigned | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
+    number_unsigned | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
+    number_unsigned | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
+    number_float    | *any value representable by a float*       | Single-Precision Float             | 0xFA
+    number_float    | *any value NOT representable by a float*   | Double-Precision Float             | 0xFB
+    string          | *length*: 0..23                            | UTF-8 string                       | 0x60..0x77
+    string          | *length*: 23..255                          | UTF-8 string (1 byte follow)       | 0x78
+    string          | *length*: 256..65535                       | UTF-8 string (2 bytes follow)      | 0x79
+    string          | *length*: 65536..4294967295                | UTF-8 string (4 bytes follow)      | 0x7A
+    string          | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow)      | 0x7B
+    array           | *size*: 0..23                              | array                              | 0x80..0x97
+    array           | *size*: 23..255                            | array (1 byte follow)              | 0x98
+    array           | *size*: 256..65535                         | array (2 bytes follow)             | 0x99
+    array           | *size*: 65536..4294967295                  | array (4 bytes follow)             | 0x9A
+    array           | *size*: 4294967296..18446744073709551615   | array (8 bytes follow)             | 0x9B
+    object          | *size*: 0..23                              | map                                | 0xA0..0xB7
+    object          | *size*: 23..255                            | map (1 byte follow)                | 0xB8
+    object          | *size*: 256..65535                         | map (2 bytes follow)               | 0xB9
+    object          | *size*: 65536..4294967295                  | map (4 bytes follow)               | 0xBA
+    object          | *size*: 4294967296..18446744073709551615   | map (8 bytes follow)               | 0xBB
+    binary          | *size*: 0..23                              | byte string                        | 0x40..0x57
+    binary          | *size*: 23..255                            | byte string (1 byte follow)        | 0x58
+    binary          | *size*: 256..65535                         | byte string (2 bytes follow)       | 0x59
+    binary          | *size*: 65536..4294967295                  | byte string (4 bytes follow)       | 0x5A
+    binary          | *size*: 4294967296..18446744073709551615   | byte string (8 bytes follow)       | 0x5B
+
+    Binary values with subtype are mapped to tagged values (0xD8..0xDB)
+    depending on the subtype, followed by a byte string, see "binary" cells
+    in the table above.
+
+    @note The mapping is **complete** in the sense that any JSON value type
+          can be converted to a CBOR value.
+
+    @note If NaN or Infinity are stored inside a JSON number, they are
+          serialized properly. This behavior differs from the @ref dump()
+          function which serializes NaN or Infinity to `null`.
+
+    @note The following CBOR types are not used in the conversion:
+          - UTF-8 strings terminated by "break" (0x7F)
+          - arrays terminated by "break" (0x9F)
+          - maps terminated by "break" (0xBF)
+          - byte strings terminated by "break" (0x5F)
+          - date/time (0xC0..0xC1)
+          - bignum (0xC2..0xC3)
+          - decimal fraction (0xC4)
+          - bigfloat (0xC5)
+          - expected conversions (0xD5..0xD7)
+          - simple values (0xE0..0xF3, 0xF8)
+          - undefined (0xF7)
+          - half-precision floats (0xF9)
+          - break (0xFF)
+
+    @param[in] j  JSON value to serialize
+    @return CBOR serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in CBOR format.,to_cbor}
+
+    @sa http://cbor.io
+    @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the
+        analogous deserialization
+    @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
+    @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the
+             related UBJSON format
+
+    @since version 2.0.9; compact representation of floating-point numbers
+           since version 3.8.0
+    */
+    static std::vector<std::uint8_t> to_cbor(const basic_json& j)
+    {
+        std::vector<std::uint8_t> result;
+        to_cbor(j, result);
+        return result;
+    }
+
+    static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+    {
+        binary_writer<std::uint8_t>(o).write_cbor(j);
+    }
+
+    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_cbor(j);
+    }
+
+    /*!
+    @brief create a MessagePack serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the MessagePack
+    serialization format. MessagePack is a binary serialization format which
+    aims to be more compact than JSON itself, yet more efficient to parse.
+
+    The library uses the following mapping from JSON values types to
+    MessagePack types according to the MessagePack specification:
+
+    JSON value type | value/range                       | MessagePack type | first byte
+    --------------- | --------------------------------- | ---------------- | ----------
+    null            | `null`                            | nil              | 0xC0
+    boolean         | `true`                            | true             | 0xC3
+    boolean         | `false`                           | false            | 0xC2
+    number_integer  | -9223372036854775808..-2147483649 | int64            | 0xD3
+    number_integer  | -2147483648..-32769               | int32            | 0xD2
+    number_integer  | -32768..-129                      | int16            | 0xD1
+    number_integer  | -128..-33                         | int8             | 0xD0
+    number_integer  | -32..-1                           | negative fixint  | 0xE0..0xFF
+    number_integer  | 0..127                            | positive fixint  | 0x00..0x7F
+    number_integer  | 128..255                          | uint 8           | 0xCC
+    number_integer  | 256..65535                        | uint 16          | 0xCD
+    number_integer  | 65536..4294967295                 | uint 32          | 0xCE
+    number_integer  | 4294967296..18446744073709551615  | uint 64          | 0xCF
+    number_unsigned | 0..127                            | positive fixint  | 0x00..0x7F
+    number_unsigned | 128..255                          | uint 8           | 0xCC
+    number_unsigned | 256..65535                        | uint 16          | 0xCD
+    number_unsigned | 65536..4294967295                 | uint 32          | 0xCE
+    number_unsigned | 4294967296..18446744073709551615  | uint 64          | 0xCF
+    number_float    | *any value representable by a float*     | float 32 | 0xCA
+    number_float    | *any value NOT representable by a float* | float 64 | 0xCB
+    string          | *length*: 0..31                   | fixstr           | 0xA0..0xBF
+    string          | *length*: 32..255                 | str 8            | 0xD9
+    string          | *length*: 256..65535              | str 16           | 0xDA
+    string          | *length*: 65536..4294967295       | str 32           | 0xDB
+    array           | *size*: 0..15                     | fixarray         | 0x90..0x9F
+    array           | *size*: 16..65535                 | array 16         | 0xDC
+    array           | *size*: 65536..4294967295         | array 32         | 0xDD
+    object          | *size*: 0..15                     | fix map          | 0x80..0x8F
+    object          | *size*: 16..65535                 | map 16           | 0xDE
+    object          | *size*: 65536..4294967295         | map 32           | 0xDF
+    binary          | *size*: 0..255                    | bin 8            | 0xC4
+    binary          | *size*: 256..65535                | bin 16           | 0xC5
+    binary          | *size*: 65536..4294967295         | bin 32           | 0xC6
+
+    @note The mapping is **complete** in the sense that any JSON value type
+          can be converted to a MessagePack value.
+
+    @note The following values can **not** be converted to a MessagePack value:
+          - strings with more than 4294967295 bytes
+          - byte strings with more than 4294967295 bytes
+          - arrays with more than 4294967295 elements
+          - objects with more than 4294967295 elements
+
+    @note Any MessagePack output created @ref to_msgpack can be successfully
+          parsed by @ref from_msgpack.
+
+    @note If NaN or Infinity are stored inside a JSON number, they are
+          serialized properly. This behavior differs from the @ref dump()
+          function which serializes NaN or Infinity to `null`.
+
+    @param[in] j  JSON value to serialize
+    @return MessagePack serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in MessagePack format.,to_msgpack}
+
+    @sa http://msgpack.org
+    @sa see @ref from_msgpack for the analogous deserialization
+    @sa see @ref to_cbor(const basic_json& for the related CBOR format
+    @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the
+             related UBJSON format
+
+    @since version 2.0.9
+    */
+    static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
+    {
+        std::vector<std::uint8_t> result;
+        to_msgpack(j, result);
+        return result;
+    }
+
+    static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+    {
+        binary_writer<std::uint8_t>(o).write_msgpack(j);
+    }
+
+    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_msgpack(j);
+    }
+
+    /*!
+    @brief create a UBJSON serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the UBJSON
+    (Universal Binary JSON) serialization format. UBJSON aims to be more compact
+    than JSON itself, yet more efficient to parse.
+
+    The library uses the following mapping from JSON values types to
+    UBJSON types according to the UBJSON specification:
+
+    JSON value type | value/range                       | UBJSON type | marker
+    --------------- | --------------------------------- | ----------- | ------
+    null            | `null`                            | null        | `Z`
+    boolean         | `true`                            | true        | `T`
+    boolean         | `false`                           | false       | `F`
+    number_integer  | -9223372036854775808..-2147483649 | int64       | `L`
+    number_integer  | -2147483648..-32769               | int32       | `l`
+    number_integer  | -32768..-129                      | int16       | `I`
+    number_integer  | -128..127                         | int8        | `i`
+    number_integer  | 128..255                          | uint8       | `U`
+    number_integer  | 256..32767                        | int16       | `I`
+    number_integer  | 32768..2147483647                 | int32       | `l`
+    number_integer  | 2147483648..9223372036854775807   | int64       | `L`
+    number_unsigned | 0..127                            | int8        | `i`
+    number_unsigned | 128..255                          | uint8       | `U`
+    number_unsigned | 256..32767                        | int16       | `I`
+    number_unsigned | 32768..2147483647                 | int32       | `l`
+    number_unsigned | 2147483648..9223372036854775807   | int64       | `L`
+    number_unsigned | 2147483649..18446744073709551615  | high-precision | `H`
+    number_float    | *any value*                       | float64     | `D`
+    string          | *with shortest length indicator*  | string      | `S`
+    array           | *see notes on optimized format*   | array       | `[`
+    object          | *see notes on optimized format*   | map         | `{`
+
+    @note The mapping is **complete** in the sense that any JSON value type
+          can be converted to a UBJSON value.
+
+    @note The following values can **not** be converted to a UBJSON value:
+          - strings with more than 9223372036854775807 bytes (theoretical)
+
+    @note The following markers are not used in the conversion:
+          - `Z`: no-op values are not created.
+          - `C`: single-byte strings are serialized with `S` markers.
+
+    @note Any UBJSON output created @ref to_ubjson can be successfully parsed
+          by @ref from_ubjson.
+
+    @note If NaN or Infinity are stored inside a JSON number, they are
+          serialized properly. This behavior differs from the @ref dump()
+          function which serializes NaN or Infinity to `null`.
+
+    @note The optimized formats for containers are supported: Parameter
+          @a use_size adds size information to the beginning of a container and
+          removes the closing marker. Parameter @a use_type further checks
+          whether all elements of a container have the same type and adds the
+          type marker to the beginning of the container. The @a use_type
+          parameter must only be used together with @a use_size = true. Note
+          that @a use_size = true alone may result in larger representations -
+          the benefit of this parameter is that the receiving side is
+          immediately informed on the number of elements of the container.
+
+    @note If the JSON data contains the binary type, the value stored is a list
+          of integers, as suggested by the UBJSON documentation.  In particular,
+          this means that serialization and the deserialization of a JSON
+          containing binary values into UBJSON and back will result in a
+          different JSON object.
+
+    @param[in] j  JSON value to serialize
+    @param[in] use_size  whether to add size annotations to container types
+    @param[in] use_type  whether to add type annotations to container types
+                         (must be combined with @a use_size = true)
+    @return UBJSON serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in UBJSON format.,to_ubjson}
+
+    @sa http://ubjson.org
+    @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the
+        analogous deserialization
+    @sa see @ref to_cbor(const basic_json& for the related CBOR format
+    @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
+
+    @since version 3.1.0
+    */
+    static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
+            const bool use_size = false,
+            const bool use_type = false)
+    {
+        std::vector<std::uint8_t> result;
+        to_ubjson(j, result, use_size, use_type);
+        return result;
+    }
+
+    static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
+                          const bool use_size = false, const bool use_type = false)
+    {
+        binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
+    }
+
+    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
+                          const bool use_size = false, const bool use_type = false)
+    {
+        binary_writer<char>(o).write_ubjson(j, use_size, use_type);
+    }
+
+
+    /*!
+    @brief Serializes the given JSON object `j` to BSON and returns a vector
+           containing the corresponding BSON-representation.
+
+    BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are
+    stored as a single entity (a so-called document).
+
+    The library uses the following mapping from JSON values types to BSON types:
+
+    JSON value type | value/range                       | BSON type   | marker
+    --------------- | --------------------------------- | ----------- | ------
+    null            | `null`                            | null        | 0x0A
+    boolean         | `true`, `false`                   | boolean     | 0x08
+    number_integer  | -9223372036854775808..-2147483649 | int64       | 0x12
+    number_integer  | -2147483648..2147483647           | int32       | 0x10
+    number_integer  | 2147483648..9223372036854775807   | int64       | 0x12
+    number_unsigned | 0..2147483647                     | int32       | 0x10
+    number_unsigned | 2147483648..9223372036854775807   | int64       | 0x12
+    number_unsigned | 9223372036854775808..18446744073709551615| --   | --
+    number_float    | *any value*                       | double      | 0x01
+    string          | *any value*                       | string      | 0x02
+    array           | *any value*                       | document    | 0x04
+    object          | *any value*                       | document    | 0x03
+    binary          | *any value*                       | binary      | 0x05
+
+    @warning The mapping is **incomplete**, since only JSON-objects (and things
+    contained therein) can be serialized to BSON.
+    Also, integers larger than 9223372036854775807 cannot be serialized to BSON,
+    and the keys may not contain U+0000, since they are serialized a
+    zero-terminated c-strings.
+
+    @throw out_of_range.407  if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`
+    @throw out_of_range.409  if a key in `j` contains a NULL (U+0000)
+    @throw type_error.317    if `!j.is_object()`
+
+    @pre The input `j` is required to be an object: `j.is_object() == true`.
+
+    @note Any BSON output created via @ref to_bson can be successfully parsed
+          by @ref from_bson.
+
+    @param[in] j  JSON value to serialize
+    @return BSON serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in BSON format.,to_bson}
+
+    @sa http://bsonspec.org/spec.html
+    @sa see @ref from_bson(detail::input_adapter&&, const bool strict) for the
+        analogous deserialization
+    @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the
+             related UBJSON format
+    @sa see @ref to_cbor(const basic_json&) for the related CBOR format
+    @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
+    */
+    static std::vector<std::uint8_t> to_bson(const basic_json& j)
+    {
+        std::vector<std::uint8_t> result;
+        to_bson(j, result);
+        return result;
+    }
+
+    /*!
+    @brief Serializes the given JSON object `j` to BSON and forwards the
+           corresponding BSON-representation to the given output_adapter `o`.
+    @param j The JSON object to convert to BSON.
+    @param o The output adapter that receives the binary BSON representation.
+    @pre The input `j` shall be an object: `j.is_object() == true`
+    @sa see @ref to_bson(const basic_json&)
+    */
+    static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+    {
+        binary_writer<std::uint8_t>(o).write_bson(j);
+    }
+
+    /*!
+    @copydoc to_bson(const basic_json&, detail::output_adapter<std::uint8_t>)
+    */
+    static void to_bson(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_bson(j);
+    }
+
+
+    /*!
+    @brief create a JSON value from an input in CBOR format
+
+    Deserializes a given input @a i to a JSON value using the CBOR (Concise
+    Binary Object Representation) serialization format.
+
+    The library maps CBOR types to JSON value types as follows:
+
+    CBOR type              | JSON value type | first byte
+    ---------------------- | --------------- | ----------
+    Integer                | number_unsigned | 0x00..0x17
+    Unsigned integer       | number_unsigned | 0x18
+    Unsigned integer       | number_unsigned | 0x19
+    Unsigned integer       | number_unsigned | 0x1A
+    Unsigned integer       | number_unsigned | 0x1B
+    Negative integer       | number_integer  | 0x20..0x37
+    Negative integer       | number_integer  | 0x38
+    Negative integer       | number_integer  | 0x39
+    Negative integer       | number_integer  | 0x3A
+    Negative integer       | number_integer  | 0x3B
+    Byte string            | binary          | 0x40..0x57
+    Byte string            | binary          | 0x58
+    Byte string            | binary          | 0x59
+    Byte string            | binary          | 0x5A
+    Byte string            | binary          | 0x5B
+    UTF-8 string           | string          | 0x60..0x77
+    UTF-8 string           | string          | 0x78
+    UTF-8 string           | string          | 0x79
+    UTF-8 string           | string          | 0x7A
+    UTF-8 string           | string          | 0x7B
+    UTF-8 string           | string          | 0x7F
+    array                  | array           | 0x80..0x97
+    array                  | array           | 0x98
+    array                  | array           | 0x99
+    array                  | array           | 0x9A
+    array                  | array           | 0x9B
+    array                  | array           | 0x9F
+    map                    | object          | 0xA0..0xB7
+    map                    | object          | 0xB8
+    map                    | object          | 0xB9
+    map                    | object          | 0xBA
+    map                    | object          | 0xBB
+    map                    | object          | 0xBF
+    False                  | `false`         | 0xF4
+    True                   | `true`          | 0xF5
+    Null                   | `null`          | 0xF6
+    Half-Precision Float   | number_float    | 0xF9
+    Single-Precision Float | number_float    | 0xFA
+    Double-Precision Float | number_float    | 0xFB
+
+    @warning The mapping is **incomplete** in the sense that not all CBOR
+             types can be converted to a JSON value. The following CBOR types
+             are not supported and will yield parse errors (parse_error.112):
+             - date/time (0xC0..0xC1)
+             - bignum (0xC2..0xC3)
+             - decimal fraction (0xC4)
+             - bigfloat (0xC5)
+             - expected conversions (0xD5..0xD7)
+             - simple values (0xE0..0xF3, 0xF8)
+             - undefined (0xF7)
+
+    @warning CBOR allows map keys of any type, whereas JSON only allows
+             strings as keys in object values. Therefore, CBOR maps with keys
+             other than UTF-8 strings are rejected (parse_error.113).
+
+    @note Any CBOR output created @ref to_cbor can be successfully parsed by
+          @ref from_cbor.
+
+    @param[in] i  an input in CBOR format convertible to an input adapter
+    @param[in] strict  whether to expect the input to be consumed until EOF
+                       (true by default)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+    @param[in] tag_handler how to treat CBOR tags (optional, error by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.110 if the given input ends prematurely or the end of
+    file was not reached when @a strict was set to true
+    @throw parse_error.112 if unsupported features from CBOR were
+    used in the given input @a v or if the input is not valid CBOR
+    @throw parse_error.113 if a string was expected as map key, but not found
+
+    @complexity Linear in the size of the input @a i.
+
+    @liveexample{The example shows the deserialization of a byte vector in CBOR
+    format to a JSON value.,from_cbor}
+
+    @sa http://cbor.io
+    @sa see @ref to_cbor(const basic_json&) for the analogous serialization
+    @sa see @ref from_msgpack(InputType&&, const bool, const bool) for the
+        related MessagePack format
+    @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the
+        related UBJSON format
+
+    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
+           consume input adapters, removed start_index parameter, and added
+           @a strict parameter since 3.0.0; added @a allow_exceptions parameter
+           since 3.2.0; added @a tag_handler parameter since 3.9.0.
+    */
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_cbor(InputType&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true,
+                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @copydoc from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t)
+    */
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_cbor(IteratorType first, IteratorType last,
+                                const bool strict = true,
+                                const bool allow_exceptions = true,
+                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    template<typename T>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
+    static basic_json from_cbor(const T* ptr, std::size_t len,
+                                const bool strict = true,
+                                const bool allow_exceptions = true,
+                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
+    }
+
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
+    static basic_json from_cbor(detail::span_input_adapter&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true,
+                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = i.get();
+        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @brief create a JSON value from an input in MessagePack format
+
+    Deserializes a given input @a i to a JSON value using the MessagePack
+    serialization format.
+
+    The library maps MessagePack types to JSON value types as follows:
+
+    MessagePack type | JSON value type | first byte
+    ---------------- | --------------- | ----------
+    positive fixint  | number_unsigned | 0x00..0x7F
+    fixmap           | object          | 0x80..0x8F
+    fixarray         | array           | 0x90..0x9F
+    fixstr           | string          | 0xA0..0xBF
+    nil              | `null`          | 0xC0
+    false            | `false`         | 0xC2
+    true             | `true`          | 0xC3
+    float 32         | number_float    | 0xCA
+    float 64         | number_float    | 0xCB
+    uint 8           | number_unsigned | 0xCC
+    uint 16          | number_unsigned | 0xCD
+    uint 32          | number_unsigned | 0xCE
+    uint 64          | number_unsigned | 0xCF
+    int 8            | number_integer  | 0xD0
+    int 16           | number_integer  | 0xD1
+    int 32           | number_integer  | 0xD2
+    int 64           | number_integer  | 0xD3
+    str 8            | string          | 0xD9
+    str 16           | string          | 0xDA
+    str 32           | string          | 0xDB
+    array 16         | array           | 0xDC
+    array 32         | array           | 0xDD
+    map 16           | object          | 0xDE
+    map 32           | object          | 0xDF
+    bin 8            | binary          | 0xC4
+    bin 16           | binary          | 0xC5
+    bin 32           | binary          | 0xC6
+    ext 8            | binary          | 0xC7
+    ext 16           | binary          | 0xC8
+    ext 32           | binary          | 0xC9
+    fixext 1         | binary          | 0xD4
+    fixext 2         | binary          | 0xD5
+    fixext 4         | binary          | 0xD6
+    fixext 8         | binary          | 0xD7
+    fixext 16        | binary          | 0xD8
+    negative fixint  | number_integer  | 0xE0-0xFF
+
+    @note Any MessagePack output created @ref to_msgpack can be successfully
+          parsed by @ref from_msgpack.
+
+    @param[in] i  an input in MessagePack format convertible to an input
+                  adapter
+    @param[in] strict  whether to expect the input to be consumed until EOF
+                       (true by default)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.110 if the given input ends prematurely or the end of
+    file was not reached when @a strict was set to true
+    @throw parse_error.112 if unsupported features from MessagePack were
+    used in the given input @a i or if the input is not valid MessagePack
+    @throw parse_error.113 if a string was expected as map key, but not found
+
+    @complexity Linear in the size of the input @a i.
+
+    @liveexample{The example shows the deserialization of a byte vector in
+    MessagePack format to a JSON value.,from_msgpack}
+
+    @sa http://msgpack.org
+    @sa see @ref to_msgpack(const basic_json&) for the analogous serialization
+    @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the
+        related CBOR format
+    @sa see @ref from_ubjson(InputType&&, const bool, const bool) for
+        the related UBJSON format
+    @sa see @ref from_bson(InputType&&, const bool, const bool) for
+        the related BSON format
+
+    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
+           consume input adapters, removed start_index parameter, and added
+           @a strict parameter since 3.0.0; added @a allow_exceptions parameter
+           since 3.2.0
+    */
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_msgpack(InputType&& i,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @copydoc from_msgpack(InputType&&, const bool, const bool)
+    */
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_msgpack(IteratorType first, IteratorType last,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+
+    template<typename T>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
+    static basic_json from_msgpack(const T* ptr, std::size_t len,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
+    static basic_json from_msgpack(detail::span_input_adapter&& i,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = i.get();
+        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+
+    /*!
+    @brief create a JSON value from an input in UBJSON format
+
+    Deserializes a given input @a i to a JSON value using the UBJSON (Universal
+    Binary JSON) serialization format.
+
+    The library maps UBJSON types to JSON value types as follows:
+
+    UBJSON type | JSON value type                         | marker
+    ----------- | --------------------------------------- | ------
+    no-op       | *no value, next value is read*          | `N`
+    null        | `null`                                  | `Z`
+    false       | `false`                                 | `F`
+    true        | `true`                                  | `T`
+    float32     | number_float                            | `d`
+    float64     | number_float                            | `D`
+    uint8       | number_unsigned                         | `U`
+    int8        | number_integer                          | `i`
+    int16       | number_integer                          | `I`
+    int32       | number_integer                          | `l`
+    int64       | number_integer                          | `L`
+    high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H'
+    string      | string                                  | `S`
+    char        | string                                  | `C`
+    array       | array (optimized values are supported)  | `[`
+    object      | object (optimized values are supported) | `{`
+
+    @note The mapping is **complete** in the sense that any UBJSON value can
+          be converted to a JSON value.
+
+    @param[in] i  an input in UBJSON format convertible to an input adapter
+    @param[in] strict  whether to expect the input to be consumed until EOF
+                       (true by default)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.110 if the given input ends prematurely or the end of
+    file was not reached when @a strict was set to true
+    @throw parse_error.112 if a parse error occurs
+    @throw parse_error.113 if a string could not be parsed successfully
+
+    @complexity Linear in the size of the input @a i.
+
+    @liveexample{The example shows the deserialization of a byte vector in
+    UBJSON format to a JSON value.,from_ubjson}
+
+    @sa http://ubjson.org
+    @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the
+             analogous serialization
+    @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the
+        related CBOR format
+    @sa see @ref from_msgpack(InputType&&, const bool, const bool) for
+        the related MessagePack format
+    @sa see @ref from_bson(InputType&&, const bool, const bool) for
+        the related BSON format
+
+    @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
+    */
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_ubjson(InputType&& i,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @copydoc from_ubjson(InputType&&, const bool, const bool)
+    */
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_ubjson(IteratorType first, IteratorType last,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    template<typename T>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
+    static basic_json from_ubjson(const T* ptr, std::size_t len,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
+    static basic_json from_ubjson(detail::span_input_adapter&& i,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = i.get();
+        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+
+    /*!
+    @brief Create a JSON value from an input in BSON format
+
+    Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)
+    serialization format.
+
+    The library maps BSON record types to JSON value types as follows:
+
+    BSON type       | BSON marker byte | JSON value type
+    --------------- | ---------------- | ---------------------------
+    double          | 0x01             | number_float
+    string          | 0x02             | string
+    document        | 0x03             | object
+    array           | 0x04             | array
+    binary          | 0x05             | binary
+    undefined       | 0x06             | still unsupported
+    ObjectId        | 0x07             | still unsupported
+    boolean         | 0x08             | boolean
+    UTC Date-Time   | 0x09             | still unsupported
+    null            | 0x0A             | null
+    Regular Expr.   | 0x0B             | still unsupported
+    DB Pointer      | 0x0C             | still unsupported
+    JavaScript Code | 0x0D             | still unsupported
+    Symbol          | 0x0E             | still unsupported
+    JavaScript Code | 0x0F             | still unsupported
+    int32           | 0x10             | number_integer
+    Timestamp       | 0x11             | still unsupported
+    128-bit decimal float | 0x13       | still unsupported
+    Max Key         | 0x7F             | still unsupported
+    Min Key         | 0xFF             | still unsupported
+
+    @warning The mapping is **incomplete**. The unsupported mappings
+             are indicated in the table above.
+
+    @param[in] i  an input in BSON format convertible to an input adapter
+    @param[in] strict  whether to expect the input to be consumed until EOF
+                       (true by default)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.114 if an unsupported BSON record type is encountered
+
+    @complexity Linear in the size of the input @a i.
+
+    @liveexample{The example shows the deserialization of a byte vector in
+    BSON format to a JSON value.,from_bson}
+
+    @sa http://bsonspec.org/spec.html
+    @sa see @ref to_bson(const basic_json&) for the analogous serialization
+    @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the
+        related CBOR format
+    @sa see @ref from_msgpack(InputType&&, const bool, const bool) for
+        the related MessagePack format
+    @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the
+        related UBJSON format
+    */
+    template<typename InputType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_bson(InputType&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::forward<InputType>(i));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @copydoc from_bson(InputType&&, const bool, const bool)
+    */
+    template<typename IteratorType>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_bson(IteratorType first, IteratorType last,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = detail::input_adapter(std::move(first), std::move(last));
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    template<typename T>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
+    static basic_json from_bson(const T* ptr, std::size_t len,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        return from_bson(ptr, ptr + len, strict, allow_exceptions);
+    }
+
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
+    static basic_json from_bson(detail::span_input_adapter&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        auto ia = i.get();
+        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+        const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+    /// @}
+
+    //////////////////////////
+    // JSON Pointer support //
+    //////////////////////////
+
+    /// @name JSON Pointer functions
+    /// @{
+
+    /*!
+    @brief access specified element via JSON Pointer
+
+    Uses a JSON pointer to retrieve a reference to the respective JSON value.
+    No bound checking is performed. Similar to @ref operator[](const typename
+    object_t::key_type&), `null` values are created in arrays and objects if
+    necessary.
+
+    In particular:
+    - If the JSON pointer points to an object key that does not exist, it
+      is created an filled with a `null` value before a reference to it
+      is returned.
+    - If the JSON pointer points to an array index that does not exist, it
+      is created an filled with a `null` value before a reference to it
+      is returned. All indices between the current maximum and the given
+      index are also filled with `null`.
+    - The special value `-` is treated as a synonym for the index past the
+      end.
+
+    @param[in] ptr  a JSON pointer
+
+    @return reference to the element pointed to by @a ptr
+
+    @complexity Constant.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+
+    @liveexample{The behavior is shown in the example.,operatorjson_pointer}
+
+    @since version 2.0.0
+    */
+    reference operator[](const json_pointer& ptr)
+    {
+        return ptr.get_unchecked(this);
+    }
+
+    /*!
+    @brief access specified element via JSON Pointer
+
+    Uses a JSON pointer to retrieve a reference to the respective JSON value.
+    No bound checking is performed. The function does not change the JSON
+    value; no `null` values are created. In particular, the special value
+    `-` yields an exception.
+
+    @param[in] ptr  JSON pointer to the desired element
+
+    @return const reference to the element pointed to by @a ptr
+
+    @complexity Constant.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+
+    @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
+
+    @since version 2.0.0
+    */
+    const_reference operator[](const json_pointer& ptr) const
+    {
+        return ptr.get_unchecked(this);
+    }
+
+    /*!
+    @brief access specified element via JSON Pointer
+
+    Returns a reference to the element at with specified JSON pointer @a ptr,
+    with bounds checking.
+
+    @param[in] ptr  JSON pointer to the desired element
+
+    @return reference to the element pointed to by @a ptr
+
+    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
+    begins with '0'. See example below.
+
+    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
+    is not a number. See example below.
+
+    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
+    is out of range. See example below.
+
+    @throw out_of_range.402 if the array index '-' is used in the passed JSON
+    pointer @a ptr. As `at` provides checked access (and no elements are
+    implicitly inserted), the index '-' is always invalid. See example below.
+
+    @throw out_of_range.403 if the JSON pointer describes a key of an object
+    which cannot be found. See example below.
+
+    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
+    See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 2.0.0
+
+    @liveexample{The behavior is shown in the example.,at_json_pointer}
+    */
+    reference at(const json_pointer& ptr)
+    {
+        return ptr.get_checked(this);
+    }
+
+    /*!
+    @brief access specified element via JSON Pointer
+
+    Returns a const reference to the element at with specified JSON pointer @a
+    ptr, with bounds checking.
+
+    @param[in] ptr  JSON pointer to the desired element
+
+    @return reference to the element pointed to by @a ptr
+
+    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
+    begins with '0'. See example below.
+
+    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
+    is not a number. See example below.
+
+    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
+    is out of range. See example below.
+
+    @throw out_of_range.402 if the array index '-' is used in the passed JSON
+    pointer @a ptr. As `at` provides checked access (and no elements are
+    implicitly inserted), the index '-' is always invalid. See example below.
+
+    @throw out_of_range.403 if the JSON pointer describes a key of an object
+    which cannot be found. See example below.
+
+    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
+    See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 2.0.0
+
+    @liveexample{The behavior is shown in the example.,at_json_pointer_const}
+    */
+    const_reference at(const json_pointer& ptr) const
+    {
+        return ptr.get_checked(this);
+    }
+
+    /*!
+    @brief return flattened JSON value
+
+    The function creates a JSON object whose keys are JSON pointers (see [RFC
+    6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
+    primitive. The original JSON value can be restored using the @ref
+    unflatten() function.
+
+    @return an object that maps JSON pointers to primitive values
+
+    @note Empty objects and arrays are flattened to `null` and will not be
+          reconstructed correctly by the @ref unflatten() function.
+
+    @complexity Linear in the size the JSON value.
+
+    @liveexample{The following code shows how a JSON object is flattened to an
+    object whose keys consist of JSON pointers.,flatten}
+
+    @sa see @ref unflatten() for the reverse function
+
+    @since version 2.0.0
+    */
+    basic_json flatten() const
+    {
+        basic_json result(value_t::object);
+        json_pointer::flatten("", *this, result);
+        return result;
+    }
+
+    /*!
+    @brief unflatten a previously flattened JSON value
+
+    The function restores the arbitrary nesting of a JSON value that has been
+    flattened before using the @ref flatten() function. The JSON value must
+    meet certain constraints:
+    1. The value must be an object.
+    2. The keys must be JSON pointers (see
+       [RFC 6901](https://tools.ietf.org/html/rfc6901))
+    3. The mapped values must be primitive JSON types.
+
+    @return the original JSON from a flattened version
+
+    @note Empty objects and arrays are flattened by @ref flatten() to `null`
+          values and can not unflattened to their original type. Apart from
+          this example, for a JSON value `j`, the following is always true:
+          `j == j.flatten().unflatten()`.
+
+    @complexity Linear in the size the JSON value.
+
+    @throw type_error.314  if value is not an object
+    @throw type_error.315  if object values are not primitive
+
+    @liveexample{The following code shows how a flattened JSON object is
+    unflattened into the original nested JSON object.,unflatten}
+
+    @sa see @ref flatten() for the reverse function
+
+    @since version 2.0.0
+    */
+    basic_json unflatten() const
+    {
+        return json_pointer::unflatten(*this);
+    }
+
+    /// @}
+
+    //////////////////////////
+    // JSON Patch functions //
+    //////////////////////////
+
+    /// @name JSON Patch functions
+    /// @{
+
+    /*!
+    @brief applies a JSON patch
+
+    [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
+    expressing a sequence of operations to apply to a JSON) document. With
+    this function, a JSON Patch is applied to the current JSON value by
+    executing all operations from the patch.
+
+    @param[in] json_patch  JSON patch document
+    @return patched document
+
+    @note The application of a patch is atomic: Either all operations succeed
+          and the patched document is returned or an exception is thrown. In
+          any case, the original value is not changed: the patch is applied
+          to a copy of the value.
+
+    @throw parse_error.104 if the JSON patch does not consist of an array of
+    objects
+
+    @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
+    attributes are missing); example: `"operation add must have member path"`
+
+    @throw out_of_range.401 if an array index is out of range.
+
+    @throw out_of_range.403 if a JSON pointer inside the patch could not be
+    resolved successfully in the current JSON value; example: `"key baz not
+    found"`
+
+    @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
+    "move")
+
+    @throw other_error.501 if "test" operation was unsuccessful
+
+    @complexity Linear in the size of the JSON value and the length of the
+    JSON patch. As usually only a fraction of the JSON value is affected by
+    the patch, the complexity can usually be neglected.
+
+    @liveexample{The following code shows how a JSON patch is applied to a
+    value.,patch}
+
+    @sa see @ref diff -- create a JSON patch by comparing two JSON values
+
+    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
+    @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
+
+    @since version 2.0.0
+    */
+    basic_json patch(const basic_json& json_patch) const
+    {
+        // make a working copy to apply the patch to
+        basic_json result = *this;
+
+        // the valid JSON Patch operations
+        enum class patch_operations {add, remove, replace, move, copy, test, invalid};
+
+        const auto get_op = [](const std::string & op)
+        {
+            if (op == "add")
+            {
+                return patch_operations::add;
+            }
+            if (op == "remove")
+            {
+                return patch_operations::remove;
+            }
+            if (op == "replace")
+            {
+                return patch_operations::replace;
+            }
+            if (op == "move")
+            {
+                return patch_operations::move;
+            }
+            if (op == "copy")
+            {
+                return patch_operations::copy;
+            }
+            if (op == "test")
+            {
+                return patch_operations::test;
+            }
+
+            return patch_operations::invalid;
+        };
+
+        // wrapper for "add" operation; add value at ptr
+        const auto operation_add = [&result](json_pointer & ptr, basic_json val)
+        {
+            // adding to the root of the target document means replacing it
+            if (ptr.empty())
+            {
+                result = val;
+                return;
+            }
+
+            // make sure the top element of the pointer exists
+            json_pointer top_pointer = ptr.top();
+            if (top_pointer != ptr)
+            {
+                result.at(top_pointer);
+            }
+
+            // get reference to parent of JSON pointer ptr
+            const auto last_path = ptr.back();
+            ptr.pop_back();
+            basic_json& parent = result[ptr];
+
+            switch (parent.m_type)
+            {
+                case value_t::null:
+                case value_t::object:
+                {
+                    // use operator[] to add value
+                    parent[last_path] = val;
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    if (last_path == "-")
+                    {
+                        // special case: append to back
+                        parent.push_back(val);
+                    }
+                    else
+                    {
+                        const auto idx = json_pointer::array_index(last_path);
+                        if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
+                        {
+                            // avoid undefined behavior
+                            JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
+                        }
+
+                        // default case: insert add offset
+                        parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
+                    }
+                    break;
+                }
+
+                // if there exists a parent it cannot be primitive
+                case value_t::string: // LCOV_EXCL_LINE
+                case value_t::boolean: // LCOV_EXCL_LINE
+                case value_t::number_integer: // LCOV_EXCL_LINE
+                case value_t::number_unsigned: // LCOV_EXCL_LINE
+                case value_t::number_float: // LCOV_EXCL_LINE
+                case value_t::binary: // LCOV_EXCL_LINE
+                case value_t::discarded: // LCOV_EXCL_LINE
+                default:            // LCOV_EXCL_LINE
+                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+            }
+        };
+
+        // wrapper for "remove" operation; remove value at ptr
+        const auto operation_remove = [this, &result](json_pointer & ptr)
+        {
+            // get reference to parent of JSON pointer ptr
+            const auto last_path = ptr.back();
+            ptr.pop_back();
+            basic_json& parent = result.at(ptr);
+
+            // remove child
+            if (parent.is_object())
+            {
+                // perform range check
+                auto it = parent.find(last_path);
+                if (JSON_HEDLEY_LIKELY(it != parent.end()))
+                {
+                    parent.erase(it);
+                }
+                else
+                {
+                    JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
+                }
+            }
+            else if (parent.is_array())
+            {
+                // note erase performs range check
+                parent.erase(json_pointer::array_index(last_path));
+            }
+        };
+
+        // type check: top level value must be an array
+        if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
+        {
+            JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
+        }
+
+        // iterate and apply the operations
+        for (const auto& val : json_patch)
+        {
+            // wrapper to get a value for an operation
+            const auto get_value = [&val](const std::string & op,
+                                          const std::string & member,
+                                          bool string_type) -> basic_json &
+            {
+                // find value
+                auto it = val.m_value.object->find(member);
+
+                // context-sensitive error message
+                const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
+
+                // check if desired value is present
+                if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
+                {
+                    // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
+                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
+                }
+
+                // check if result is of type string
+                if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
+                {
+                    // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
+                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
+                }
+
+                // no error: return value
+                return it->second;
+            };
+
+            // type check: every element of the array must be an object
+            if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
+            {
+                JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
+            }
+
+            // collect mandatory members
+            const auto op = get_value("op", "op", true).template get<std::string>();
+            const auto path = get_value(op, "path", true).template get<std::string>();
+            json_pointer ptr(path);
+
+            switch (get_op(op))
+            {
+                case patch_operations::add:
+                {
+                    operation_add(ptr, get_value("add", "value", false));
+                    break;
+                }
+
+                case patch_operations::remove:
+                {
+                    operation_remove(ptr);
+                    break;
+                }
+
+                case patch_operations::replace:
+                {
+                    // the "path" location must exist - use at()
+                    result.at(ptr) = get_value("replace", "value", false);
+                    break;
+                }
+
+                case patch_operations::move:
+                {
+                    const auto from_path = get_value("move", "from", true).template get<std::string>();
+                    json_pointer from_ptr(from_path);
+
+                    // the "from" location must exist - use at()
+                    basic_json v = result.at(from_ptr);
+
+                    // The move operation is functionally identical to a
+                    // "remove" operation on the "from" location, followed
+                    // immediately by an "add" operation at the target
+                    // location with the value that was just removed.
+                    operation_remove(from_ptr);
+                    operation_add(ptr, v);
+                    break;
+                }
+
+                case patch_operations::copy:
+                {
+                    const auto from_path = get_value("copy", "from", true).template get<std::string>();
+                    const json_pointer from_ptr(from_path);
+
+                    // the "from" location must exist - use at()
+                    basic_json v = result.at(from_ptr);
+
+                    // The copy is functionally identical to an "add"
+                    // operation at the target location using the value
+                    // specified in the "from" member.
+                    operation_add(ptr, v);
+                    break;
+                }
+
+                case patch_operations::test:
+                {
+                    bool success = false;
+                    JSON_TRY
+                    {
+                        // check if "value" matches the one at "path"
+                        // the "path" location must exist - use at()
+                        success = (result.at(ptr) == get_value("test", "value", false));
+                    }
+                    JSON_INTERNAL_CATCH (out_of_range&)
+                    {
+                        // ignore out of range errors: success remains false
+                    }
+
+                    // throw an exception if test fails
+                    if (JSON_HEDLEY_UNLIKELY(!success))
+                    {
+                        JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
+                    }
+
+                    break;
+                }
+
+                case patch_operations::invalid:
+                default:
+                {
+                    // op must be "add", "remove", "replace", "move", "copy", or
+                    // "test"
+                    JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief creates a diff as a JSON patch
+
+    Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
+    be changed into the value @a target by calling @ref patch function.
+
+    @invariant For two JSON values @a source and @a target, the following code
+    yields always `true`:
+    @code {.cpp}
+    source.patch(diff(source, target)) == target;
+    @endcode
+
+    @note Currently, only `remove`, `add`, and `replace` operations are
+          generated.
+
+    @param[in] source  JSON value to compare from
+    @param[in] target  JSON value to compare against
+    @param[in] path    helper value to create JSON pointers
+
+    @return a JSON patch to convert the @a source to @a target
+
+    @complexity Linear in the lengths of @a source and @a target.
+
+    @liveexample{The following code shows how a JSON patch is created as a
+    diff for two JSON values.,diff}
+
+    @sa see @ref patch -- apply a JSON patch
+    @sa see @ref merge_patch -- apply a JSON Merge Patch
+
+    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
+
+    @since version 2.0.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json diff(const basic_json& source, const basic_json& target,
+                           const std::string& path = "")
+    {
+        // the patch
+        basic_json result(value_t::array);
+
+        // if the values are the same, return empty patch
+        if (source == target)
+        {
+            return result;
+        }
+
+        if (source.type() != target.type())
+        {
+            // different types: replace value
+            result.push_back(
+            {
+                {"op", "replace"}, {"path", path}, {"value", target}
+            });
+            return result;
+        }
+
+        switch (source.type())
+        {
+            case value_t::array:
+            {
+                // first pass: traverse common elements
+                std::size_t i = 0;
+                while (i < source.size() && i < target.size())
+                {
+                    // recursive call to compare array values at index i
+                    auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
+                    result.insert(result.end(), temp_diff.begin(), temp_diff.end());
+                    ++i;
+                }
+
+                // i now reached the end of at least one array
+                // in a second pass, traverse the remaining elements
+
+                // remove my remaining elements
+                const auto end_index = static_cast<difference_type>(result.size());
+                while (i < source.size())
+                {
+                    // add operations in reverse order to avoid invalid
+                    // indices
+                    result.insert(result.begin() + end_index, object(
+                    {
+                        {"op", "remove"},
+                        {"path", path + "/" + std::to_string(i)}
+                    }));
+                    ++i;
+                }
+
+                // add other remaining elements
+                while (i < target.size())
+                {
+                    result.push_back(
+                    {
+                        {"op", "add"},
+                        {"path", path + "/-"},
+                        {"value", target[i]}
+                    });
+                    ++i;
+                }
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                // first pass: traverse this object's elements
+                for (auto it = source.cbegin(); it != source.cend(); ++it)
+                {
+                    // escape the key name to be used in a JSON patch
+                    const auto path_key = path + "/" + detail::escape(it.key());
+
+                    if (target.find(it.key()) != target.end())
+                    {
+                        // recursive call to compare object values at key it
+                        auto temp_diff = diff(it.value(), target[it.key()], path_key);
+                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());
+                    }
+                    else
+                    {
+                        // found a key that is not in o -> remove it
+                        result.push_back(object(
+                        {
+                            {"op", "remove"}, {"path", path_key}
+                        }));
+                    }
+                }
+
+                // second pass: traverse other object's elements
+                for (auto it = target.cbegin(); it != target.cend(); ++it)
+                {
+                    if (source.find(it.key()) == source.end())
+                    {
+                        // found a key that is not in this -> add it
+                        const auto path_key = path + "/" + detail::escape(it.key());
+                        result.push_back(
+                        {
+                            {"op", "add"}, {"path", path_key},
+                            {"value", it.value()}
+                        });
+                    }
+                }
+
+                break;
+            }
+
+            case value_t::null:
+            case value_t::string:
+            case value_t::boolean:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::number_float:
+            case value_t::binary:
+            case value_t::discarded:
+            default:
+            {
+                // both primitive type: replace value
+                result.push_back(
+                {
+                    {"op", "replace"}, {"path", path}, {"value", target}
+                });
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    /// @}
+
+    ////////////////////////////////
+    // JSON Merge Patch functions //
+    ////////////////////////////////
+
+    /// @name JSON Merge Patch functions
+    /// @{
+
+    /*!
+    @brief applies a JSON Merge Patch
+
+    The merge patch format is primarily intended for use with the HTTP PATCH
+    method as a means of describing a set of modifications to a target
+    resource's content. This function applies a merge patch to the current
+    JSON value.
+
+    The function implements the following algorithm from Section 2 of
+    [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
+
+    ```
+    define MergePatch(Target, Patch):
+      if Patch is an Object:
+        if Target is not an Object:
+          Target = {} // Ignore the contents and set it to an empty Object
+        for each Name/Value pair in Patch:
+          if Value is null:
+            if Name exists in Target:
+              remove the Name/Value pair from Target
+          else:
+            Target[Name] = MergePatch(Target[Name], Value)
+        return Target
+      else:
+        return Patch
+    ```
+
+    Thereby, `Target` is the current object; that is, the patch is applied to
+    the current value.
+
+    @param[in] apply_patch  the patch to apply
+
+    @complexity Linear in the lengths of @a patch.
+
+    @liveexample{The following code shows how a JSON Merge Patch is applied to
+    a JSON document.,merge_patch}
+
+    @sa see @ref patch -- apply a JSON patch
+    @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
+
+    @since version 3.0.0
+    */
+    void merge_patch(const basic_json& apply_patch)
+    {
+        if (apply_patch.is_object())
+        {
+            if (!is_object())
+            {
+                *this = object();
+            }
+            for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
+            {
+                if (it.value().is_null())
+                {
+                    erase(it.key());
+                }
+                else
+                {
+                    operator[](it.key()).merge_patch(it.value());
+                }
+            }
+        }
+        else
+        {
+            *this = apply_patch;
+        }
+    }
+
+    /// @}
+};
+
+/*!
+@brief user-defined to_string function for JSON values
+
+This function implements a user-defined to_string  for JSON objects.
+
+@param[in] j  a JSON object
+@return a std::string object
+*/
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
+{
+    return j.dump();
+}
+} // namespace nlohmann
+
+///////////////////////
+// nonmember support //
+///////////////////////
+
+namespace std // NOLINT(cert-dcl58-cpp)
+{
+
+/// hash value for JSON objects
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
+{
+    /*!
+    @brief return a hash value for a JSON object
+
+    @since version 1.0.0, extended for arbitrary basic_json types in 3.10.5.
+    */
+    std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
+    {
+        return nlohmann::detail::hash(j);
+    }
+};
+
+/// specialization for std::less<value_t>
+/// @note: do not remove the space after '<',
+///        see https://github.com/nlohmann/json/pull/679
+template<>
+struct less< ::nlohmann::detail::value_t>
+{
+    /*!
+    @brief compare two value_t enum values
+    @since version 3.0.0
+    */
+    bool operator()(nlohmann::detail::value_t lhs,
+                    nlohmann::detail::value_t rhs) const noexcept
+    {
+        return nlohmann::detail::operator<(lhs, rhs);
+    }
+};
+
+// C++20 prohibit function specialization in the std namespace.
+#ifndef JSON_HAS_CPP_20
+
+/*!
+@brief exchanges the values of two JSON objects
+
+@since version 1.0.0, extended for arbitrary basic_json types in 3.10.5.
+*/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept(  // NOLINT(readability-inconsistent-declaration-parameter-name)
+    is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression)
+    is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
+{
+    j1.swap(j2);
+}
+
+#endif
+
+} // namespace std
+
+/*!
+@brief user-defined string literal for JSON values
+
+This operator implements a user-defined string literal for JSON objects. It
+can be used by adding `"_json"` to a string literal and returns a JSON object
+if no parse error occurred.
+
+@param[in] s  a string representation of a JSON object
+@param[in] n  the length of string @a s
+@return a JSON object
+
+@since version 1.0.0
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json operator "" _json(const char* s, std::size_t n)
+{
+    return nlohmann::json::parse(s, s + n);
+}
+
+/*!
+@brief user-defined string literal for JSON pointer
+
+This operator implements a user-defined string literal for JSON Pointers. It
+can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
+object if no parse error occurred.
+
+@param[in] s  a string representation of a JSON Pointer
+@param[in] n  the length of string @a s
+@return a JSON pointer object
+
+@since version 2.0.0
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
+{
+    return nlohmann::json::json_pointer(std::string(s, n));
+}
+
+// #include <nlohmann/detail/macro_unscope.hpp>
+
+
+// restore clang diagnostic settings
+#if defined(__clang__)
+    #pragma clang diagnostic pop
+#endif
+
+// clean up
+#undef JSON_ASSERT
+#undef JSON_INTERNAL_CATCH
+#undef JSON_CATCH
+#undef JSON_THROW
+#undef JSON_TRY
+#undef JSON_PRIVATE_UNLESS_TESTED
+#undef JSON_HAS_CPP_11
+#undef JSON_HAS_CPP_14
+#undef JSON_HAS_CPP_17
+#undef JSON_HAS_CPP_20
+#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
+#undef NLOHMANN_BASIC_JSON_TPL
+#undef JSON_EXPLICIT
+#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
+
+// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
+
+
+#undef JSON_HEDLEY_ALWAYS_INLINE
+#undef JSON_HEDLEY_ARM_VERSION
+#undef JSON_HEDLEY_ARM_VERSION_CHECK
+#undef JSON_HEDLEY_ARRAY_PARAM
+#undef JSON_HEDLEY_ASSUME
+#undef JSON_HEDLEY_BEGIN_C_DECLS
+#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
+#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
+#undef JSON_HEDLEY_CLANG_HAS_FEATURE
+#undef JSON_HEDLEY_CLANG_HAS_WARNING
+#undef JSON_HEDLEY_COMPCERT_VERSION
+#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
+#undef JSON_HEDLEY_CONCAT
+#undef JSON_HEDLEY_CONCAT3
+#undef JSON_HEDLEY_CONCAT3_EX
+#undef JSON_HEDLEY_CONCAT_EX
+#undef JSON_HEDLEY_CONST
+#undef JSON_HEDLEY_CONSTEXPR
+#undef JSON_HEDLEY_CONST_CAST
+#undef JSON_HEDLEY_CPP_CAST
+#undef JSON_HEDLEY_CRAY_VERSION
+#undef JSON_HEDLEY_CRAY_VERSION_CHECK
+#undef JSON_HEDLEY_C_DECL
+#undef JSON_HEDLEY_DEPRECATED
+#undef JSON_HEDLEY_DEPRECATED_FOR
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#undef JSON_HEDLEY_DIAGNOSTIC_POP
+#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
+#undef JSON_HEDLEY_DMC_VERSION
+#undef JSON_HEDLEY_DMC_VERSION_CHECK
+#undef JSON_HEDLEY_EMPTY_BASES
+#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
+#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
+#undef JSON_HEDLEY_END_C_DECLS
+#undef JSON_HEDLEY_FLAGS
+#undef JSON_HEDLEY_FLAGS_CAST
+#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_BUILTIN
+#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_EXTENSION
+#undef JSON_HEDLEY_GCC_HAS_FEATURE
+#undef JSON_HEDLEY_GCC_HAS_WARNING
+#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
+#undef JSON_HEDLEY_GCC_VERSION
+#undef JSON_HEDLEY_GCC_VERSION_CHECK
+#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
+#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
+#undef JSON_HEDLEY_GNUC_HAS_FEATURE
+#undef JSON_HEDLEY_GNUC_HAS_WARNING
+#undef JSON_HEDLEY_GNUC_VERSION
+#undef JSON_HEDLEY_GNUC_VERSION_CHECK
+#undef JSON_HEDLEY_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_BUILTIN
+#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
+#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_EXTENSION
+#undef JSON_HEDLEY_HAS_FEATURE
+#undef JSON_HEDLEY_HAS_WARNING
+#undef JSON_HEDLEY_IAR_VERSION
+#undef JSON_HEDLEY_IAR_VERSION_CHECK
+#undef JSON_HEDLEY_IBM_VERSION
+#undef JSON_HEDLEY_IBM_VERSION_CHECK
+#undef JSON_HEDLEY_IMPORT
+#undef JSON_HEDLEY_INLINE
+#undef JSON_HEDLEY_INTEL_CL_VERSION
+#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
+#undef JSON_HEDLEY_INTEL_VERSION
+#undef JSON_HEDLEY_INTEL_VERSION_CHECK
+#undef JSON_HEDLEY_IS_CONSTANT
+#undef JSON_HEDLEY_IS_CONSTEXPR_
+#undef JSON_HEDLEY_LIKELY
+#undef JSON_HEDLEY_MALLOC
+#undef JSON_HEDLEY_MCST_LCC_VERSION
+#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
+#undef JSON_HEDLEY_MESSAGE
+#undef JSON_HEDLEY_MSVC_VERSION
+#undef JSON_HEDLEY_MSVC_VERSION_CHECK
+#undef JSON_HEDLEY_NEVER_INLINE
+#undef JSON_HEDLEY_NON_NULL
+#undef JSON_HEDLEY_NO_ESCAPE
+#undef JSON_HEDLEY_NO_RETURN
+#undef JSON_HEDLEY_NO_THROW
+#undef JSON_HEDLEY_NULL
+#undef JSON_HEDLEY_PELLES_VERSION
+#undef JSON_HEDLEY_PELLES_VERSION_CHECK
+#undef JSON_HEDLEY_PGI_VERSION
+#undef JSON_HEDLEY_PGI_VERSION_CHECK
+#undef JSON_HEDLEY_PREDICT
+#undef JSON_HEDLEY_PRINTF_FORMAT
+#undef JSON_HEDLEY_PRIVATE
+#undef JSON_HEDLEY_PUBLIC
+#undef JSON_HEDLEY_PURE
+#undef JSON_HEDLEY_REINTERPRET_CAST
+#undef JSON_HEDLEY_REQUIRE
+#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
+#undef JSON_HEDLEY_REQUIRE_MSG
+#undef JSON_HEDLEY_RESTRICT
+#undef JSON_HEDLEY_RETURNS_NON_NULL
+#undef JSON_HEDLEY_SENTINEL
+#undef JSON_HEDLEY_STATIC_ASSERT
+#undef JSON_HEDLEY_STATIC_CAST
+#undef JSON_HEDLEY_STRINGIFY
+#undef JSON_HEDLEY_STRINGIFY_EX
+#undef JSON_HEDLEY_SUNPRO_VERSION
+#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
+#undef JSON_HEDLEY_TINYC_VERSION
+#undef JSON_HEDLEY_TINYC_VERSION_CHECK
+#undef JSON_HEDLEY_TI_ARMCL_VERSION
+#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL2000_VERSION
+#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL430_VERSION
+#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL6X_VERSION
+#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL7X_VERSION
+#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CLPRU_VERSION
+#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
+#undef JSON_HEDLEY_TI_VERSION
+#undef JSON_HEDLEY_TI_VERSION_CHECK
+#undef JSON_HEDLEY_UNAVAILABLE
+#undef JSON_HEDLEY_UNLIKELY
+#undef JSON_HEDLEY_UNPREDICTABLE
+#undef JSON_HEDLEY_UNREACHABLE
+#undef JSON_HEDLEY_UNREACHABLE_RETURN
+#undef JSON_HEDLEY_VERSION
+#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
+#undef JSON_HEDLEY_VERSION_DECODE_MINOR
+#undef JSON_HEDLEY_VERSION_DECODE_REVISION
+#undef JSON_HEDLEY_VERSION_ENCODE
+#undef JSON_HEDLEY_WARNING
+#undef JSON_HEDLEY_WARN_UNUSED_RESULT
+#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
+#undef JSON_HEDLEY_FALL_THROUGH
+
+
+
+#endif  // INCLUDE_NLOHMANN_JSON_HPP_
index d0d7e4aeafae124566b73157c2565a4aef4a1bcb..9138be788bf64d384be1ba1ed15b41f8cf71ba1a 100644 (file)
@@ -24,7 +24,7 @@
 #include <limits.h>
 #include <pthread.h>
 #include <sys/mman.h>
-#include <common/compat/time.h>
+#include <common/compat/time.hpp>
 
 #define BUF_SIZE 256
 #define NB_FD 1
index c67cde86d3ca3546da73dc685482e3327779a321..494b982df1989ec0d4698b39f443f7b41c8176cd 100644 (file)
@@ -3,13 +3,6 @@
 AM_CPPFLAGS += -I$(top_srcdir)/tests/utils/ -I$(srcdir)
 
 LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la
-
-LIBCOMMON=$(top_builddir)/src/common/libcommon.la
-LIBSESSIOND_COMM=$(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la
-LIBHASHTABLE=$(top_builddir)/src/common/hashtable/libhashtable.la
-LIBRELAYD=$(top_builddir)/src/common/relayd/librelayd.la
-LIBHEALTH=$(top_builddir)/src/common/health/libhealth.la
-LIBCOMPAT=$(top_builddir)/src/common/compat/libcompat.la
 LIBLTTNG_SESSIOND_COMMON=$(top_builddir)/src/bin/lttng-sessiond/liblttng-sessiond-common.la
 
 noinst_PROGRAMS = live_test
index afaf23b658442e2b407d509ab29cec878aba87e8..391bf03db31770b4e735bf4ed67edf29328c77b8 100644 (file)
@@ -9,7 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <common/compat/time.h>
+#include <common/compat/time.hpp>
 #include <sys/types.h>
 #include <inttypes.h>
 #include <stdlib.h>
 #include <lttng/lttng.h>
 
 #include <urcu/list.h>
-#include <common/common.h>
+#include <common/common.hpp>
 
-#include <bin/lttng-relayd/lttng-viewer-abi.h>
-#include <common/index/ctf-index.h>
+#include <bin/lttng-relayd/lttng-viewer-abi.hpp>
+#include <common/index/ctf-index.hpp>
 
-#include <common/compat/errno.h>
-#include <common/compat/endian.h>
+#include <common/compat/errno.hpp>
+#include <common/compat/endian.hpp>
 
 #define SESSION1 "test1"
 #define RELAYD_URL "net://localhost"
index 4029a21263d640dd572d130113c08aaea63192fd..94eacdf2b7a19d8e146c778777898a08bd274902 100644 (file)
@@ -37,7 +37,7 @@ FORCE_SHARED_LIB_OPTIONS = -module -shared -avoid-version \
 
 libpause_consumer_la_SOURCES = consumer_testpoints.cpp
 libpause_consumer_la_LIBADD = \
-       $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \
+       $(top_builddir)/src/common/libsessiond-comm.la \
        $(top_builddir)/src/common/libcommon.la \
        $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la \
        $(DL_LIBS)
index 05db3421a132fd878c58aa8f0c323d6fa35e6d1e..9f2314acb8d3f82807ecbd95db581827a601261a 100644 (file)
@@ -5,10 +5,10 @@
  *
  */
 
-#include <common/compat/getenv.h>
-#include <common/consumer/consumer.h>
-#include <common/pipe.h>
-#include <common/error.h>
+#include <common/compat/getenv.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/pipe.hpp>
+#include <common/error.hpp>
 #include <unistd.h>
 #include <stdbool.h>
 #include <lttng/constant.h>
index cc24cec1ea01ea45bd34ecba5b8697d3d5d5409c..4f1796bc1265d2146840a28f9b6ef1ece5d3aa76 100644 (file)
@@ -14,8 +14,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <common/pipe.h>
-#include <common/error.h>
+#include <common/pipe.hpp>
+#include <common/error.hpp>
 
 int lttng_opt_verbose;
 int lttng_opt_mi;
index 6d3e46ea32bb319ea9f0cb153daf17f88bba403f..776e1335637774c8b09dbe7170c981fb31862574 100644 (file)
@@ -22,8 +22,8 @@
 #include <signal.h>
 #include <poll.h>
 
-#include <common/compat/errno.h>
-#include <common/macros.h>
+#include <common/compat/errno.hpp>
+#include <common/macros.hpp>
 #include <lttng/lttng.h>
 
 #include <tap/tap.h>
index fa3fe7f418141e41b3cd57626cdda89a906f19c2..f0517ed14b911f9e62fc2bbf2ccd2d2e0036f76e 100644 (file)
@@ -6,10 +6,10 @@
  *
  */
 
-#include <common/compat/getenv.h>
-#include <common/consumer/consumer.h>
-#include <common/pipe.h>
-#include <common/error.h>
+#include <common/compat/getenv.hpp>
+#include <common/consumer/consumer.hpp>
+#include <common/pipe.hpp>
+#include <common/error.hpp>
 #include <unistd.h>
 #include <stdbool.h>
 #include <lttng/constant.h>
index b1134266aa1ae238004e00f4e87041cc6ec87135..ddf54db594e65cb6ef1aa952473025d8b640a623 100755 (executable)
@@ -9,7 +9,7 @@ TEST_DESC="Auto load session(s)"
 CURDIR=$(dirname $0)/
 CONFIG_DIR="${CURDIR}/configuration"
 TESTDIR=$CURDIR/../../../
-export LTTNG_SESSION_CONFIG_XSD_PATH=$(readlink -m ${TESTDIR}../src/common/config/)
+export LTTNG_SESSION_CONFIG_XSD_PATH=$(readlink -m ${TESTDIR}../src/common/)
 
 DIR=$(readlink -f $TESTDIR)
 
index 7899cc09ba71c9955f8912a87c7b7e3986f4edcc..cbdf96f6ebeded149cdb0ad9e7816d0aeb80f0e2 100755 (executable)
@@ -9,7 +9,7 @@ TEST_DESC="Load session(s)"
 CURDIR=$(dirname $0)/
 CONFIG_DIR="${CURDIR}/configuration"
 TESTDIR=$CURDIR/../../../
-export LTTNG_SESSION_CONFIG_XSD_PATH=$(readlink -m ${TESTDIR}../src/common/config/)
+export LTTNG_SESSION_CONFIG_XSD_PATH=$(readlink -m ${TESTDIR}../src/common/)
 
 SESSION_NAME="load-42"
 EVENT_NAME="tp:tptest"
index 668a60fb3fd97be3f304c9bd72c09569ab5af449..4be8e790de8dcf2c87854f03a7ee901cec37cd3e 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <tap/tap.h>
 
-#include <common/macros.h>
+#include <common/macros.hpp>
 #include <lttng/lttng.h>
 
 #define TEST_COUNT 1
index 1c9aae32c23afbba93b3f5b674380f08dea30caa..74b0c14b08b717bad8447871199494f62a157125 100644 (file)
@@ -15,7 +15,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <lttng/lttng.h>
-#include <common/macros.h>
+#include <common/macros.hpp>
 
 #define TEST_COUNT 70
 
index dd3b0278fb507bd75560249742cd9339ede5fe1b..86c863bd9fce3604de46cf58e5f3ad5322fae5b2 100644 (file)
@@ -13,5 +13,4 @@ notification_client_LDADD = $(LIBLTTNG_CTL) \
 
 register_some_triggers_SOURCES = register-some-triggers.cpp
 register_some_triggers_LDADD = $(LIBLTTNG_CTL) \
-       $(top_builddir)/src/common/filter/libfilter.la \
-       $(top_builddir)/src/common/bytecode/libbytecode.la
+       $(top_builddir)/src/common/libcommon.la
index 54eb78303348cbe3b8675a3a45193904e2e8b376..cbcfbfb82baadc4b12bccad2bf157bba8286a4dc 100644 (file)
@@ -7,8 +7,8 @@
 
 /* Utility to register some triggers, for test purposes. */
 
-#include <common/filter/filter-ast.h>
-#include <common/macros.h>
+#include <common/filter/filter-ast.hpp>
+#include <common/macros.hpp>
 #include <lttng/lttng.h>
 
 #include <stdlib.h>
index a12a5b76bc5bc836c4519360baaba4d8f6d320fb..a38cd515e217cfaee7cc55845f285790dd8067f2 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #include <stdlib.h>
-#include <common/compat/time.h>
+#include <common/compat/time.hpp>
 #include <string.h>
 #include <stdio.h>
 #include <lttng/lttng-export.h>
index dbe6c1d86283adf7c3cc1ef4f6780eb81696e54e..80240f1f5da47eb5d676b77cb99da9596717a0e1 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include <stdlib.h>
-#include <common/compat/time.h>
+#include <common/compat/time.hpp>
 #include <string.h>
 #include <stdio.h>
 #include <unistd.h>
index 473de57a90db560493ffd2a8d8651c4d406a2827..cd5e1068d24a5599686720106b16eae7f289e000 100644 (file)
@@ -11,7 +11,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 
-#include <common/compat/errno.h>
+#include <common/compat/errno.hpp>
 
 /*
  * libfoo has a direct dependency on libbar.
index e555b0149479d30b69cf0d2232e14cb734770fb0..c3fbdd927bbabeb86ad9a4b367df60f7d65fc1a6 100644 (file)
@@ -37,11 +37,11 @@ TESTS = \
 LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la
 
 LIBCOMMON=$(top_builddir)/src/common/libcommon.la
-LIBSTRINGUTILS=$(top_builddir)/src/common/string-utils/libstring-utils.la
-LIBFDTRACKER=$(top_builddir)/src/common/fd-tracker/libfd-tracker.la
-LIBSESSIOND_COMM=$(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la
-LIBHASHTABLE=$(top_builddir)/src/common/hashtable/libhashtable.la
-LIBRELAYD=$(top_builddir)/src/common/relayd/librelayd.la
+LIBSTRINGUTILS=$(top_builddir)/src/common/libstring-utils.la
+LIBFDTRACKER=$(top_builddir)/src/common/libfd-tracker.la
+LIBSESSIOND_COMM=$(top_builddir)/src/common/libsessiond-comm.la
+LIBHASHTABLE=$(top_builddir)/src/common/libhashtable.la
+LIBRELAYD=$(top_builddir)/src/common/librelayd.la
 LIBLTTNG_CTL=$(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la
 LIBLTTNG_SESSIOND_COMMON=$(top_builddir)/src/bin/lttng-sessiond/liblttng-sessiond-common.la
 
@@ -113,12 +113,12 @@ test_utils_parse_time_suffix_LDADD = $(LIBTAP) $(LIBHASHTABLE) $(LIBCOMMON)
 # compat_poll unit test
 test_utils_compat_poll_SOURCES = test_utils_compat_poll.cpp
 test_utils_compat_poll_LDADD  = $(LIBTAP) $(LIBHASHTABLE) $(DL_LIBS) \
-                     $(top_builddir)/src/common/compat/libcompat.la $(LIBCOMMON)
+                     $(top_builddir)/src/common/libcompat.la $(LIBCOMMON)
 
 # compat_pthread unit test
 test_utils_compat_pthread_SOURCES = test_utils_compat_pthread.cpp
 test_utils_compat_pthread_LDADD  = $(LIBTAP) \
-                     $(top_builddir)/src/common/compat/libcompat.la $(LIBCOMMON)
+                     $(top_builddir)/src/common/libcompat.la $(LIBCOMMON)
 
 # expand_path unit test
 test_utils_expand_path_SOURCES = test_utils_expand_path.cpp
index f7bf287708f822a918ab8b67bbc3684d1bb2cffb..b053221e3f984b3347424cc3c1f5135d9a5ad36f 100644 (file)
@@ -4,7 +4,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/tests/utils/
 
 LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la
 LIBCOMMON=$(top_builddir)/src/common/libcommon.la
-LIBHASHTABLE=$(top_builddir)/src/common/hashtable/libhashtable.la
+LIBHASHTABLE=$(top_builddir)/src/common/libhashtable.la
 
 noinst_PROGRAMS = ini_config
 EXTRA_DIST = test_ini_config sample.ini
index c2a753edece66593a336529a21a2bde8c0eca677..7099be9d718fc74b506bb34aba19014e4f50d1eb 100644 (file)
@@ -6,8 +6,8 @@
  */
 
 #include <tap/tap.h>
-#include <common/ini-config/ini-config.h>
-#include <common/utils.h>
+#include <common/ini-config/ini-config.hpp>
+#include <common/utils.hpp>
 #include <string.h>
 #include <lttng/constant.h>
 
index ad323e9acc169592c68de995f4344fe6d6e0e997..72bded447695a7b67d9275e3f7698b42d8f94cc3 100644 (file)
 
 #include <tap/tap.h>
 
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/action/action-internal.h>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/action/action-internal.hpp>
 #include <lttng/action/action.h>
 #include <lttng/action/notify.h>
-#include <lttng/action/rate-policy-internal.h>
+#include <lttng/action/rate-policy-internal.hpp>
 #include <lttng/action/rate-policy.h>
 #include <lttng/action/rotate-session.h>
 #include <lttng/action/snapshot-session.h>
index a129d4a9a0ec6fbf38ef6d80c40e307f8e9afcf4..764549b83da41c7e289090286d4d22326c819dd1 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 
-#include <common/buffer-view.h>
+#include <common/buffer-view.hpp>
 #include <tap/tap.h>
 
 static const int TEST_COUNT = 5;
index 1ed14fa6c3f502a02ba5e960cdbdbbc187ef0d8f..1505e477539b221ea0f3206d59aed17676a9a1e1 100644 (file)
 
 #include <lttng/event.h>
 #include <lttng/event-rule/user-tracepoint.h>
-#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/condition-internal.hpp>
 #include <lttng/condition/event-rule-matches.h>
-#include <lttng/condition/event-rule-matches-internal.h>
+#include <lttng/condition/event-rule-matches-internal.hpp>
 #include <lttng/domain.h>
 #include <lttng/log-level-rule.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
+#include <common/dynamic-buffer.hpp>
+#include <common/buffer-view.hpp>
 
 /* For error.h */
 int lttng_opt_quiet = 1;
index ca116716595165b5ad8bfae4707341714c449fcf..ecc8d1feb71b055413315d9c737bd4d449d549cd 100644 (file)
@@ -14,9 +14,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/compat/directory-handle.h>
-#include <common/compat/errno.h>
-#include <common/error.h>
+#include <common/compat/directory-handle.hpp>
+#include <common/compat/errno.hpp>
+#include <common/error.hpp>
 #include <tap/tap.h>
 
 #define TEST_COUNT 9
index fae7eb26ebe214f567a37bdf12bcd0abbf49e73a..577dea93229ce1ffc12c785508383b20e217b83e 100644 (file)
@@ -5,8 +5,8 @@
  *
  */
 
-#include <common/bytecode/bytecode.h>
-#include <lttng/event-expr-internal.h>
+#include <common/bytecode/bytecode.hpp>
+#include <lttng/event-expr-internal.hpp>
 #include <lttng/event-expr.h>
 #include <tap/tap.h>
 
index 0fc9ec7702a44724339e5a530d19af5f71de52ae..c6724115ba63201bf4dad38364e4c23024cad6e6 100644 (file)
 
 #include <tap/tap.h>
 
-#include <common/payload-view.h>
-#include <common/payload.h>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
 #include <lttng/domain.h>
-#include <lttng/event-rule/jul-logging-internal.h>
+#include <lttng/event-rule/jul-logging-internal.hpp>
 #include <lttng/event-rule/jul-logging.h>
-#include <lttng/event-rule/kernel-kprobe-internal.h>
+#include <lttng/event-rule/kernel-kprobe-internal.hpp>
 #include <lttng/event-rule/kernel-kprobe.h>
-#include <lttng/event-rule/kernel-syscall-internal.h>
+#include <lttng/event-rule/kernel-syscall-internal.hpp>
 #include <lttng/event-rule/kernel-syscall.h>
-#include <lttng/event-rule/python-logging-internal.h>
+#include <lttng/event-rule/python-logging-internal.hpp>
 #include <lttng/event-rule/python-logging.h>
-#include <lttng/event-rule/kernel-tracepoint-internal.h>
+#include <lttng/event-rule/kernel-tracepoint-internal.hpp>
 #include <lttng/event-rule/kernel-tracepoint.h>
-#include <lttng/event-rule/kernel-uprobe-internal.h>
+#include <lttng/event-rule/kernel-uprobe-internal.hpp>
 #include <lttng/event-rule/kernel-uprobe.h>
-#include <lttng/event-rule/user-tracepoint-internal.h>
+#include <lttng/event-rule/user-tracepoint-internal.hpp>
 #include <lttng/event-rule/user-tracepoint.h>
 #include <lttng/event.h>
-#include <lttng/kernel-probe-internal.h>
+#include <lttng/kernel-probe-internal.hpp>
 #include <lttng/kernel-probe.h>
-#include <lttng/userspace-probe-internal.h>
+#include <lttng/userspace-probe-internal.hpp>
 #include <lttng/userspace-probe.h>
-#include "bin/lttng/loglevel.h"
+#include "bin/lttng/loglevel.hpp"
 
 /* For error.h. */
 int lttng_opt_quiet = 1;
index 6df179f9d7516bfe8ffb2ef042164e867362781a..3c48939bfae8671c7d9798f532338c0ad1ad8cc1 100644 (file)
 
 #include <urcu.h>
 
-#include <common/compat/directory-handle.h>
-#include <common/compat/errno.h>
-#include <common/error.h>
-#include <common/fs-handle.h>
-#include <common/fd-tracker/fd-tracker.h>
+#include <common/compat/directory-handle.hpp>
+#include <common/compat/errno.hpp>
+#include <common/error.hpp>
+#include <common/fs-handle.hpp>
+#include <common/fd-tracker/fd-tracker.hpp>
 
 /* For error.h */
 int lttng_opt_quiet = 1;
index 6f0ce872b737170ae308b96d70a8eb41a21f7425..c197069335de05515db0a220cb1252bbc634bee1 100644 (file)
@@ -11,9 +11,9 @@
 #include <unistd.h>
 #include <time.h>
 
-#include <common/compat/errno.h>
-#include <bin/lttng-sessiond/trace-kernel.h>
-#include <common/defaults.h>
+#include <common/compat/errno.hpp>
+#include <bin/lttng-sessiond/trace-kernel.hpp>
+#include <common/defaults.hpp>
 
 #include <tap/tap.h>
 
index 0f6f89ec950cb7a0c94c3fac91e670b2b51c3d76..710577d18b63c8515e05dc8c5a5d23eedb238c86 100644 (file)
@@ -14,9 +14,9 @@
 
 #include <tap/tap.h>
 
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/kernel-probe-internal.h>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/kernel-probe-internal.hpp>
 #include <lttng/kernel-probe.h>
 
 /* For error.h */
index d2895c811bc5331e23d00bcea68805fe7d82827c..9b420dde5d2fc0a914ed438e261ae3e9ace5674e 100644 (file)
@@ -14,9 +14,9 @@
 
 #include <tap/tap.h>
 
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/log-level-rule-internal.h>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/log-level-rule-internal.hpp>
 #include <lttng/log-level-rule.h>
 
 /* For error.h. */
index 5a2bac14d2159d678d01b717fe658d6a357ce450..1e763820b27b5e8f66091675b4a138bb95eed0c4 100644 (file)
@@ -24,7 +24,7 @@
 #include <lttng/notification/notification.h>
 #include <lttng/trigger/trigger.h>
 
-#include <common/macros.h>
+#include <common/macros.hpp>
 
 /* For error.h */
 int lttng_opt_quiet = 1;
index 53565f5eb58db06345c7de63edd8d558ecc61083..de50ed383b5a6ec8cfc4e1160124a30385f703c2 100644 (file)
@@ -7,9 +7,9 @@
 
 #include <unistd.h>
 
-#include <common/compat/fcntl.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
+#include <common/compat/fcntl.hpp>
+#include <common/payload.hpp>
+#include <common/payload-view.hpp>
 #include <tap/tap.h>
 
 static const int TEST_COUNT = 5;
index acfe159039fdf79e748be3e53873b979fb27b071..27ef0c6ce800f9a273b99e89b7f18f3cb6e5ac9f 100644 (file)
@@ -14,9 +14,9 @@
 
 #include <tap/tap.h>
 
-#include <common/payload-view.h>
-#include <common/payload.h>
-#include <lttng/action/rate-policy-internal.h>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/action/rate-policy-internal.hpp>
 #include <lttng/action/rate-policy.h>
 
 /* For error.h. */
index dee0fabd41df9028435da3750e7f705f4ceb60ae..70e8c928f7612b5b75b089e3c8ced67d08a6f28a 100644 (file)
@@ -11,9 +11,9 @@
 #include <string.h>
 #include <tap/tap.h>
 
-#include <common/time.h>
+#include <common/time.hpp>
 
-#include "backward-compatibility-group-by.h"
+#include "backward-compatibility-group-by.hpp"
 
 /* Number of TAP tests in this file */
 #define NUM_TESTS_PER_TEST 1
index 4fc23791e0737f46b45878aa17e8471f2b0d80df..40af1e3abc14aaa415e3462ef36875886d4dbeff 100644 (file)
 
 #include <tap/tap.h>
 
-#include <common/compat/errno.h>
-#include <bin/lttng-sessiond/session.h>
-#include <bin/lttng-sessiond/ust-app.h>
-#include <bin/lttng-sessiond/ht-cleanup.h>
-#include <bin/lttng-sessiond/health-sessiond.h>
-#include <bin/lttng-sessiond/thread.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/common.h>
+#include <common/compat/errno.hpp>
+#include <bin/lttng-sessiond/session.hpp>
+#include <bin/lttng-sessiond/ust-app.hpp>
+#include <bin/lttng-sessiond/ht-cleanup.hpp>
+#include <bin/lttng-sessiond/health-sessiond.hpp>
+#include <bin/lttng-sessiond/thread.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/common.hpp>
 
 #define SESSION1 "test1"
 
index e20f88f7a8552432302194bd1e9646893b650ce9..4efe4d3317cca2404737d10b78778febb51bb416 100644 (file)
@@ -9,7 +9,7 @@
 #include <stdbool.h>
 #include <string.h>
 #include <stdarg.h>
-#include <common/string-utils/string-utils.h>
+#include <common/string-utils/string-utils.hpp>
 #include <tap/tap.h>
 
 /* Number of TAP tests in this file */
index 2d59ba8eeac6457ba4d2399fa4cbf2fbddd9157a..2ff65a679749838586fb47846306a740cc0b3f0f 100644 (file)
@@ -6,16 +6,16 @@
  */
 
 #include <algorithm>
-#include <common/compat/fcntl.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
-#include <common/unix.h>
-#include <common/utils.h>
-#include <common/defaults.h>
+#include <common/compat/fcntl.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/payload.hpp>
+#include <common/payload-view.hpp>
+#include <common/unix.hpp>
+#include <common/utils.hpp>
+#include <common/defaults.hpp>
 #include <tap/tap.h>
 #include <stdbool.h>
-#include <common/error.h>
+#include <common/error.hpp>
 #include <lttng/constant.h>
 #include <stdio.h>
 #include <pthread.h>
index d2ad04b0ce7a98a4b734ac3d83380f70ca7ed60e..6561cf24a8ea12ebac692381b10256155c83990b 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <tap/tap.h>
 
-#include <common/uri.h>
+#include <common/uri.hpp>
 
 /* For error.h */
 int lttng_opt_quiet = 1;
index f1b197ea94b12a002cdb82c359a06570c260e5dd..d681f9b0ef4f0bd5b7864fd0f9ca9d4fcb5fd219 100644 (file)
 #include <urcu.h>
 
 #include <lttng/lttng.h>
-#include <bin/lttng-sessiond/lttng-ust-abi.h>
-#include <common/defaults.h>
-#include <common/compat/errno.h>
-#include <bin/lttng-sessiond/trace-ust.h>
-#include <bin/lttng-sessiond/ust-app.h>
-#include <bin/lttng-sessiond/notification-thread.h>
+#include <bin/lttng-sessiond/lttng-ust-abi.hpp>
+#include <common/defaults.hpp>
+#include <common/compat/errno.hpp>
+#include <bin/lttng-sessiond/trace-ust.hpp>
+#include <bin/lttng-sessiond/ust-app.hpp>
+#include <bin/lttng-sessiond/notification-thread.hpp>
 
 #include <lttng/ust-sigbus.h>
 
index eb6d94a5eedb876bb39d25deb1645c7c2cc68733..f34ef5d0ea27f7da28484eafcfef21416c6e66b8 100644 (file)
 
 #include <tap/tap.h>
 
-#include <common/compat/poll.h>
-#include <common/readwrite.h>
-#include <common/pipe.h>
-#include <common/dynamic-array.h>
+#include <common/compat/poll.hpp>
+#include <common/readwrite.hpp>
+#include <common/pipe.hpp>
+#include <common/dynamic-array.hpp>
 
 /* Verification without trashing test order in the child process */
 #define childok(e, test, ...) do { \
index eb2b7b6ec2cf524947427bba6697d88d844812ed..88c2dbde55b4f04f51212efb1a8a4a25b5d44a63 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <stdio.h>
 #include <string.h>
-#include "common/compat/pthread.h"
+#include "common/compat/pthread.hpp"
 
 #include <tap/tap.h>
 
index 85c8a54282fc947aa7591c4476368fef62032d3b..0aa656ab8ff086d1f9d49d63e35c882255c35b27 100644 (file)
@@ -15,8 +15,8 @@
 
 #include <tap/tap.h>
 
-#include <common/utils.h>
-#include <common/common.h>
+#include <common/utils.hpp>
+#include <common/common.hpp>
 
 /* For error.h */
 int lttng_opt_quiet = 1;
index ac6efa251f3041e371a5c338c9af8d55986c37f6..e103f96442d8021b37ea03ddfc418a499e852a12 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <tap/tap.h>
 
-#include <common/utils.h>
+#include <common/utils.hpp>
 
 /* For error.h */
 int lttng_opt_quiet = 1;
index 89fab12eb1ed72e3d7235543fa83acb6fbfe8bf6..94505b6dd2c1686eb6d7f0e9799909c76189014d 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <tap/tap.h>
 
-#include <common/utils.h>
+#include <common/utils.hpp>
 
 /* For error.h */
 int lttng_opt_quiet = 1;
index e13a0975175308c684e586451d7609a8cb7e7344..b21ade14e9677ee53b22cc325847923efabe99c1 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <tap/tap.h>
 
-#include "common/uuid.h"
+#include "common/uuid.hpp"
 
 #define NR_TESTS 21
 
index 5b3805c6b026b4d9d168a7f4a8923fdc31307a2b..55a7ba7ebddb055b0f61346a9ee8e69abb433091 100644 (file)
@@ -24,4 +24,4 @@ SUBDIRS += \
          gen-ust-events-ns
 endif # IS_LINUX
 
-noinst_HEADERS = signal-helper.h
+noinst_HEADERS = signal-helper.hpp
index 78b962d19bb71a0e214fcd6a0f4ec41511eb73f1..a8df4405b95f8fb2eaf920c29081aa85684b5784 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/compat/tid.h>
-#include <common/macros.h>
+#include <common/compat/tid.hpp>
+#include <common/macros.hpp>
 
-#include "signal-helper.h"
+#include "signal-helper.hpp"
 #include "utils.h"
 
 #define LTTNG_PROC_NS_PATH_MAX 40
index 6a246867d39c824422e0db778ecdf85ef46528fc..9b19d2d2d6d5424866a388ede519700ea0de2793 100644 (file)
@@ -9,8 +9,8 @@
 #include <stdio.h>
 #include <sys/syscall.h>
 #include <unistd.h>
-#include <common/error.h>
-#include <common/align.h>
+#include <common/error.hpp>
+#include <common/align.hpp>
 
 #include "utils.h"
 
index c916a961611c3d1f7aeae903c7f46190432f552c..242b658e5a4e2598d7246a876e0b93b11cbfdc22 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/compat/tid.h>
-#include <common/macros.h>
+#include <common/compat/tid.hpp>
+#include <common/macros.hpp>
 
-#include "signal-helper.h"
+#include "signal-helper.hpp"
 #include "utils.h"
 
 #define TRACEPOINT_DEFINE
index cf8819977dc79d83596b1da1d31a746d6b271cb9..b66f1ce8c6efc099c1aa5eb0aa71ed602e97426f 100644 (file)
@@ -22,7 +22,7 @@
 #include <poll.h>
 #include <errno.h>
 #include "utils.h"
-#include "signal-helper.h"
+#include "signal-helper.hpp"
 
 #define TRACEPOINT_DEFINE
 #include "tp.h"
index d68501bee553406e00b2cb8f78a673a231493067..d59dfa3d81c919cf1993bb7487ac5a302e8f1bb6 100644 (file)
@@ -7,7 +7,7 @@
 
 #define _LGPL_SOURCE
 #include <stdio.h>
-#include "signal-helper.h"
+#include "signal-helper.hpp"
 
 #define TRACEPOINT_DEFINE
 #include "tp.h"
index ec71023de4d872632d59aef98d1f14037bc854bc..a2aae040f9b01cefb419332afdc0175f10c1546d 100644 (file)
@@ -17,7 +17,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include "utils.h"
-#include "signal-helper.h"
+#include "signal-helper.hpp"
 
 #define TRACEPOINT_DEFINE
 #include "tp.h"
index f0f6cc63c372465363bda2b453c466d810580f3f..31aa3798f99432c198696d55100d9d347c5210c2 100644 (file)
@@ -17,9 +17,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/macros.h>
+#include <common/macros.hpp>
 #include <lttng/tracef.h>
-#include "signal-helper.h"
+#include "signal-helper.hpp"
 
 const char *str = "test string";
 
diff --git a/tests/utils/testapp/signal-helper.h b/tests/utils/testapp/signal-helper.h
deleted file mode 100644 (file)
index ceadcb3..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#ifndef LTTNG_TESTAPP_SIGNAL_HELPER_H
-#define LTTNG_TESTAPP_SIGNAL_HELPER_H
-
-#include <signal.h>
-
-static volatile int should_quit;
-
-static
-void sighandler(int sig)
-{
-       if (sig == SIGTERM) {
-               should_quit = 1;
-       }
-}
-
-static
-int set_signal_handler(void)
-{
-       int ret;
-       struct sigaction sa {};
-       sa.sa_flags = 0;
-       sa.sa_handler = sighandler;
-
-       ret = sigemptyset(&sa.sa_mask);
-       if (ret) {
-               perror("sigemptyset");
-               goto end;
-       }
-
-       ret = sigaction(SIGTERM, &sa, NULL);
-       if (ret) {
-               perror("sigaction");
-               goto end;
-       }
-end:
-       return ret;
-}
-
-#endif /* LTTNG_TESTAPP_SIGNAL_HELPER_H */
diff --git a/tests/utils/testapp/signal-helper.hpp b/tests/utils/testapp/signal-helper.hpp
new file mode 100644 (file)
index 0000000..ceadcb3
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_TESTAPP_SIGNAL_HELPER_H
+#define LTTNG_TESTAPP_SIGNAL_HELPER_H
+
+#include <signal.h>
+
+static volatile int should_quit;
+
+static
+void sighandler(int sig)
+{
+       if (sig == SIGTERM) {
+               should_quit = 1;
+       }
+}
+
+static
+int set_signal_handler(void)
+{
+       int ret;
+       struct sigaction sa {};
+       sa.sa_flags = 0;
+       sa.sa_handler = sighandler;
+
+       ret = sigemptyset(&sa.sa_mask);
+       if (ret) {
+               perror("sigemptyset");
+               goto end;
+       }
+
+       ret = sigaction(SIGTERM, &sa, NULL);
+       if (ret) {
+               perror("sigaction");
+               goto end;
+       }
+end:
+       return ret;
+}
+
+#endif /* LTTNG_TESTAPP_SIGNAL_HELPER_H */
index 6483ae8996e00103613ad3c9fd1e351dab1cf822..7d095c131fe1e60b05c6ea3133ded09ff578ba9f 100644 (file)
@@ -3,4 +3,4 @@
 # no optimization
 AM_CPPFLAGS = -O0
 noinst_PROGRAMS = userspace-probe-elf-cxx-binary
-userspace_probe_elf_cxx_binary_SOURCES = userspace-probe-elf-cxx-binary.cpp test_class.cpp test_class.h
+userspace_probe_elf_cxx_binary_SOURCES = userspace-probe-elf-cxx-binary.cpp test_class.cpp test_class.hpp
index 83bde0b205bd1e8eb8ffc69ab63f09db1155b42f..05a20c7a188466471b8a39370178b295eaa122da 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include "test_class.h"
+#include "test_class.hpp"
 test_class::test_class() {
        test_member = 1;
 }
diff --git a/tests/utils/testapp/userspace-probe-elf-cxx-binary/test_class.h b/tests/utils/testapp/userspace-probe-elf-cxx-binary/test_class.h
deleted file mode 100644 (file)
index aa518e4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2018 Francis Deslauriers <francis.deslauriers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-or-later
- *
- */
-
-class test_class
-{
-public:
-       test_class();
-       void test_method();
-       volatile int test_member;
-};
-
-
diff --git a/tests/utils/testapp/userspace-probe-elf-cxx-binary/test_class.hpp b/tests/utils/testapp/userspace-probe-elf-cxx-binary/test_class.hpp
new file mode 100644 (file)
index 0000000..aa518e4
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2018 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ */
+
+class test_class
+{
+public:
+       test_class();
+       void test_method();
+       volatile int test_member;
+};
+
+
index ab0f241447b1cda1b7db0b0fe8194a39bb596462..e87fe6cf6614f2dc0e338ddc0172405b95aaec64 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include "test_class.h"
+#include "test_class.hpp"
 
 volatile int not_a_function = 0;
 
index fee74e961245d02e0322f70c86c9e7d21e33cd43..0f1bd28c7e7a3da58d09abc63c5c3270347b7071 100644 (file)
@@ -5,8 +5,8 @@
  *
  */
 
-#include <common/compat/time.h>
-#include <common/time.h>
+#include <common/compat/time.hpp>
+#include <common/time.hpp>
 #include <fcntl.h>
 #include <poll.h>
 #include <stdbool.h>
@@ -17,8 +17,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <common/compat/errno.h>
-#include <common/macros.h>
+#include <common/compat/errno.hpp>
+#include <common/macros.hpp>
 
 #include "utils.h"
 
index 2680daae923e15b937f8263d203210efd44549c1..8a710fe303b10c7aa69950a9e2da6cae85823079 100644 (file)
@@ -682,8 +682,8 @@ function start_lttng_sessiond_opt()
            LTTNG_BAIL_OUT "*** Kernel too old for session daemon tests ***"
        fi
 
-       diag "export LTTNG_SESSION_CONFIG_XSD_PATH=${DIR}/../src/common/config/"
-       : "${LTTNG_SESSION_CONFIG_XSD_PATH="${DIR}/../src/common/config/"}"
+       diag "export LTTNG_SESSION_CONFIG_XSD_PATH=${DIR}/../src/common/"
+       : "${LTTNG_SESSION_CONFIG_XSD_PATH="${DIR}/../src/common/"}"
        export LTTNG_SESSION_CONFIG_XSD_PATH
 
        if [ -z "$(lttng_pgrep "${SESSIOND_MATCH}")" ]; then
index 011f38f4a65c17d36464ffc4697864c66410fc05..c58cf1362351f17664a6ed60bfaf614ede9b49db 100644 (file)
@@ -34,7 +34,7 @@
 #include <libxml/parser.h>
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
-#include <common/defaults.h>
+#include <common/defaults.hpp>
 
 #if defined(LIBXML_XPATH_ENABLED)
 
index 56002ed7cd4769e7b1a3c83ed2fa106e2723352b..93b9d093c2da39afdb3e264669dafec60262c8ea 100644 (file)
@@ -25,9 +25,7 @@
 #include <libxml/parser.h>
 
 #include <lttng/lttng-error.h>
-#include <common/macros.h>
-
-#include <common/macros.h>
+#include <common/macros.hpp>
 
 struct validation_ctx {
        xmlSchemaParserCtxtPtr parser_ctx;
This page took 1.165516 seconds and 5 git commands to generate.