Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

xretractor

The xretractor program is RetractorDB’s core process. It compiles files containing RQL queries and executes the data-processing plan. It’s built to run autonomously as a systemd daemon process.

Modes of operation

xretractor starts in one of two modes:

ModeDescription
ProcessingDefault - compiles queries and starts the query-execution loop
Compile only -cCompiles queries without starting the loop; allows visualizing the plan

Calling -h shows a different option list depending on the mode - option shorthands overlap, so pay attention to which mode a given option applies in.


Processing mode (default)

$ xretractor -h
xretractor - compiler & data processing tool.

Usage: xretractor queryfile [option]

Available options:
  -h [ --help ]               Show program options
  -b [ --build-info ]         show optimizer build configuration
  -c [ --onlycompile ]        compile only mode
  -q [ --queryfile ] arg      query set file
  -r [ --quiet ]              no output on screen, skip presenter
  -s [ --status ]             check service status
  -o [ --cleanup ]            remove leftovers of dead instances and exit
  -v [ --verbose ]            verbose mode (show stream params)
  -x [ --xqrywait ]           wait with processing for first query
  -n [ --name ] arg           instance name; own IPC area and lock
  -a [ --autoname ]           generate a docker-style instance name
  -k [ --noanykey ]           do not wait for any key to terminate
  -j [ --service ]            service mode: log to stderr (journald)
  -t [ --realtime ]           enable real-time scheduling
  -f [ --no-clock ]           offline mode: compute slots without waiting
  -u [ --until-eof ]          forces one-shot all sources
  -g [ --config ] arg         config file (TOML); overrides search
  -m [ --llimitqry ] arg (=0) loop iteration limit, 0 - no limit

Processing-mode options

OptionMeaning
helpDisplays the help text. The list differs depending on the mode (with or without -c).
build-infoPrints the optimizer configuration the binary was built with (the RDB_OPT_* flags and RDB_BENCH_PROBE) and exits without starting the engine. It is handled before the configuration file is loaded and validated, so it also works on a host with an invalid storage.dir. The output is stable and meant for automated processing - both scripts/buildrdb.sh and the it_optimizer_ablation-build-info test rely on it. See the appendix on production builds and diagnostic variants for details.
onlycompileSwitches the tool into “compile only” mode. The query-execution loop is not started.
queryfileThe name of the query file to compile and run.
quietSkips displaying results on screen. Processing runs normally, but the result presenter isn’t started.
statusChecks the instance lock selected by --name, RDB_NAMESPACE, or the historical empty name. Running means another process holds the same identity.
cleanupRemoves recognized leftovers of dead instances and exits without starting a plan. Also available as -o. Live owners remain protected; scope and limitations are described below.
verboseShows stream parameters and adds on stderr a message about streams growing without bound on disk and warnings about declarations in the deprecated DECLARE ... FILE form (one per declaration, with the plan line and the chosen keyword BINFILE, TEXTFILE or DEVICE). Without this option there are no warnings about the deprecated form. A separate log entry depends on the logging level.
xqrywaitCompiles the queries and holds off the processing loop until the first client command has been handled. When receiving data through xqry from a run limited by -m N, it prevents the entire budget from being processed before the client connects. xqry --select registers its subscription first, so its queue exists before the loop is unblocked. However, any handled command releases the gate, including --hello or --dir from another client; this does not mean all receivers are ready. A stop signal interrupts the wait without executing the zero step. When inspecting files after the run has finished, -x is not needed.
name argGives the instance a stable name. The name selects a separate lock file and IPC area and lets commands be routed through xqry --server. It may contain at most 32 lowercase letters, digits, _, and -, and its first character must be a letter.
autonameGenerates a container-style instance name and prints it at startup. Mutually exclusive with --name.
noanykeyDisables stopping the processing loop on any keypress. A positive --llimitqry N limit also disables this behavior, even without --noanykey. A keypress stops an unlimited run if this option was not supplied. Ctrl+C still stops the process.
serviceService mode: the log goes to stderr (captured by journald), with no log file in the temporary directory, no timestamp of its own, and no ANSI codes. The mode can also be enabled through the XRETRACTOR_SERVICE environment variable set to any value other than empty or 0 - convenient in a systemd unit via Environment=.
realtimeEnables real-time scheduling of the processing thread: SCHED_FIFO, mlockall, and moving the communication thread off the cores assigned to the processing thread. It does not change the slot schedule: sleeping until a deadline counted from a fixed anchor applies in every clocked mode (see Slot schedule). Requires CAP_SYS_NICE and CAP_IPC_LOCK capabilities (or root); without them it prints the compliance report and runs without these settings. Recommended in production environments requiring deterministic response time.
no-clockOffline mode: retains the rational timeline, logical indices, origins, and plan tails, but skips wall-clock waiting. The TIMEOUT deadline of every DEVICE source is then 0. It cannot be combined with --realtime.
until-eofSwitches declared sources to ONESHOT mode and stops when the first one runs out of data. For a DEVICE source exhaustion is the first end of data after data was received, that is, the writer leaving.
configPath to a configuration file in TOML format. It overrides the standard search order (/etc/retractor/retractor.toml, then $XDG_CONFIG_HOME/retractor/retractor.toml or ~/.config/retractor/retractor.toml). Missing files at those locations allow built-in defaults to be used; a missing file explicitly selected with --config is an error.
llimitqryLimits the number of iterations in the query-execution loop. A value of 0 means no limit.

Multiple instances

Several named instances can run concurrently:

xretractor measurements.rql --name measurements --noanykey &
xretractor diagnostics.rql --name diagnostics --noanykey &
xqry --bus

Each receives its own lock and IPC objects. The shared bus nevertheless rejects a plan that collides with a live instance by stream name, written storage file, or :ROTATION counter file. The check happens before artifacts are removed. Omitting --name preserves the historical unnamed instance. After the service-mode exclusivity check, an instance with the same name as a live bus entry, including a second unnamed one, is refused with exit code ENOLCK (37 on Linux) even when its lock file was deleted from the temporary directory.

Service mode provides a separate guarantee: exactly one service instance may run in each RDB_NAMESPACE; in the default namespace it is named service. See Multiple Instances and the Bus.

The instance lock file must be a regular file with a single name, owned by the account that starts the instance. A symbolic link (dangling ones included), a second hard link, a directory or a FIFO at that path, as well as a file owned by another account - also for an instance started as root - stop startup without changing the contents of the target file. The stderr message, shown in Release builds as well, names the path and the cause, and exit code 5 (EIO) distinguishes this refusal from an identity that is already taken (ENOLCK, 37 on Linux, message is already running). A leftover of another account after a crash is neither taken over by the instance nor removed by --cleanup; an operator with rights to the lock directory removes it by hand. Reading presence and IPC identity locks of other accounts remains allowed.

Cleaning up leftovers

xretractor --cleanup

The command does not start a plan. It attempts to acquire locks on recognized resources and removes only those without a live owner holding the lock. The same mechanism runs when an instance exits.

ScopeAction
Instance lock filesScans paths.lock_dir selected by configuration, defaulting to the process’s temporary directory.
IPC identitiesScans the shared /tmp; removes an abandoned lock and its command queue, response segment, and map mutex. Objects of an instance with a live slot on the bus of the current namespace are kept.
BusRemoves segments of the current xrdbbus_v7 layout that nobody holds through a presence lock and in which no slot belongs to a live instance.

The scope is not restricted to an instance selected with --name or a single RDB_NAMESPACE. Filesystem permissions still control access to resources. The command does not enumerate or remove client response queues; it also leaves v5 and older segments untouched because they do not participate in the presence-lock protocol.

The output counts removed instance locks, IPC identity sets, and segments, for example:

Removed leftovers of dead instances: 1 instance lock(s), 1 IPC identity set(s), 1 bus segment(s).

The IPC-set count is not a count of individual queues. Completion does not establish that resources outside the command’s scope were removed. For a custom lock directory, select the appropriate TOML using --config.

Clock-free batch processing

The simplest run over a complete input file without manually selecting an iteration count is:

xretractor query.rql --no-clock --until-eof --noanykey --quiet

--no-clock removes sleeps only. It does not change slot order or artifact content, making it suitable for fast verification after completion. It can outrun an xqry client, however, so it is not intended for live observation.

--until-eof prevents a sequential source from returning to the start of its file. EOF is checked after a slot has been processed, exactly before the first record that would otherwise have to use synthetic NULL beyond the input. A DEVICE source is read at the start of the slot, so its exhaustion is checked before the slot - with the same effect. With several sources, the first exhausted one stops the run so the plan does not continue with a missing input. It may be combined with -m N; whichever condition occurs first wins.

A missing declared source, denied read access or a failed open ends execution with an environment error, K4, and code EIO (5 on Linux). This applies to TEXTFILE, BINFILE and DEVICE, including without -u. The message identifies the stream, path and cause. The startup check leaves previous results unchanged; compile-only mode (-c) does not require an available input. See source checks.

⚠️ Warning Short options depend on the mode. During execution, -f means --no-clock and -u means --until-eof. With -c, the same letters mean --fields and --rules, respectively, and do not start processing.

NOTE: noclock_offline verifies equivalence between paced and offline execution; untileof_stop verifies first-EOF termination and the non-wrapping control.


Compile-only mode (-c)

$ xretractor -h -c
xretractor - compiler & data processing tool.

Usage: xretractor -c queryfile [option]

Available options:
  -h [ --help ]          show help options
  -b [ --build-info ]    show optimizer build configuration
  -c [ --onlycompile ]   compile only mode
  -q [ --queryfile ] arg query set file
  -r [ --quiet ]         no output on screen, skip presenter
  -v [ --verbose ]       verbose mode (show stream params)
  -d [ --dot ]           create dot output
  -m [ --csv ]           create csv output
  -f [ --fields ]        show fields in dot file
  -t [ --tags ]          show tags in dot file
  -s [ --streamprogs ]   show stream programs in dot file
  -u [ --rules ]         show rules in dot file
  -i [ --hideruleprog ]  hide rule program in rules (-u) output
  -p [ --transparent ]   make dot background transparent
  -w [ --diagram ] arg   create diagram output
  -z [ --shmbudget ]     show shared memory budget of the compiled plan
  -g [ --config ] arg    config file (TOML); overrides search

In this mode, options for creating diagrams and diagnostic dumps, described in more detail elsewhere in this work, are available. -v is also available when compiling without running the plan.

Visualization and diagnostic options

OptionMeaning
helpDisplays the help text (identical to processing mode; the list differs depending on the mode).
build-infoIdentical in meaning to processing mode - prints the optimizer configuration and exits. The -c flag does not affect the output; the option is available in both modes so that the configuration dump can be obtained regardless of how the program is invoked.
onlycompileOn - this table describes the options that apply while the -c flag is active.
queryfileThe name of the query file to compile.
quietTests only the compilation process itself, without presenting results. The other presentation options are not started. Included for development purposes.
dotCreates a text file in DOT format describing the hierarchical structures produced by the compiler. The file can be passed to the Graphviz tool to generate a graphical description of the dependencies.
csvExports the hierarchical data structures to a CSV file (comma-separated values).
fieldsAdds, to the DOT graph, the fields and their types for each data stream.
tagsAdds, to the DOT graph, the internal-language programs that build the fields of each query. Must be called together with fields - it visually links the fields to their programs.
streamprogsAdds, to the DOT graph, the stream-algebra programs that build each query’s streams.
rulesAdds alerting rules to the graph.
hideruleprogHides the programs describing the alerting conditions (used together with rules).
transparentGenerates the graph with a transparent background.
diagramGenerates marble diagrams. Argument type[:cycle_count]: 0 disables the time grid and 1 enables it; the positive integer cycle count defaults to 1. The entire argument must be a valid integer or pair of integers; an invalid type, an empty part after the colon, or a nonpositive cycle count is an argument error. An empty plan and a cycle count that would overflow the grid are also rejected.
shmbudgetReports the fixed IPC reservation, capacity, and free space of the shm_open filesystem (usually /dev/shm), plus the cost of one client queue for each plan interval. This lets an operator estimate the number of concurrent subscriptions before starting a server.
configSelects an explicit TOML file in -c mode as well; retention and history budget settings apply during compilation.

Configuration file (TOML)

The --config option (short form -g) points at a configuration file, including in -c mode; without it the program searches two locations in layered fashion, in the order given, each later layer overriding keys from the previous one:

  1. /etc/retractor/retractor.toml - system layer,
  2. $XDG_CONFIG_HOME/retractor/retractor.toml (or ~/.config/retractor/retractor.toml) - user layer.

The absence of discovered files is a valid state - the program starts with default values. An existing file with invalid TOML stops startup: the program returns a nonzero exit code and reports an ERROR diagnostic naming the file and cause, including in Release builds. Every loaded layer must be valid, even if a later layer would override its keys. With an explicit path (--config), a missing file remains an error as well. The same configuration loader is used by xqry (--config, short option -e) and xtrdb; these programs also refuse to run with a malformed file. The --help option works in all three programs regardless of the configuration; xretractor then reports the error in the Config: line of its help. The [ipc] and [timing] sections apply to the engine and the xqry client.

KeyDefaultMeaning
storage.dir(none)Default artifact directory. Applied only when the RQL set contains no :STORAGE directive - RQL wins. The directory must exist and be writable, otherwise the program exits with Configuration error: storage.dir ….
storage.default_retention(none)Pair [capacity, segments], both positive. Sets bounded retention on DEFAULT and DIRECT file streams without their own RETENTION, including substrates. It does not change MEMORY, stores without retention, or explicit retention. An invalid value logs a warning and leaves default retention unset.
storage.ref_dirs(none)Read by xtrdb. A list of absolute paths to existing directories where the REF field of a retained .desc may relocate a writable data file. Without this key, a REF taken from .desc permits writing and deletion only within the storage directory; reading BINFILE, TEXTFILE, and DEVICE sources and using a REF from the plan are unrestricted. In xretractor, the REF of a retained .desc must equal the plan’s REF, so this key does not change engine behavior. An invalid entry stops xtrdb at startup with Configuration error: storage.ref_dirs ....
sources.timeout_s(none, i.e. 0)Read deadline in seconds for DEVICE sources without a TIMEOUT clause (→ Reading a DEVICE source and TIMEOUT). An explicit clause in RQL wins, including TIMEOUT 0. In --no-clock mode the deadline is 0. It does not change BINFILE, TEXTFILE or timing.query_no_data_timeout_ms. A negative, non-numeric value or one above 86400 stops the start with Configuration error: sources.timeout_s ….
ipc.queue_buffer_seconds10IPC queue depth expressed in seconds of stream; the element count is seconds / interval.
ipc.min_queue_elements100Lower bound on queue capacity, independent of the stream interval.
ipc.client_response_max_fails300Multiplier for the xqry response time budget. A monotonic-clock deadline is set to this value times the polling interval (10 ms) and covers both waiting for space in the command queue and waiting for the response.
timing.server_startup_wait_s30Maximum time xqry --wait-server waits for server readiness.
timing.server_startup_poll_ms100Polling interval while waiting for the server to start.
timing.query_no_data_timeout_ms10000No-data timeout after which the xqry client considers the server dead.
scheduling.rt_priority50SCHED_FIFO priority in --realtime mode; allowed range 1–99.
paths.lock_dir(system temp directory)Directory for instance lock files. For systemd services, /var/run/retractor or $XDG_RUNTIME_DIR is recommended. A nonempty path must be absolute in every loaded layer; a relative path stops startup with an ERROR diagnostic naming the file and cause, including in Release. An empty value keeps the default temporary directory. It does not change the fixed /tmp directory for IPC identity locks.
server.autonamefalseGenerates a name when neither --name nor --autoname was given. An explicit --name wins. false preserves the historical unnamed instance.
service.query_file(value from the build configuration)The query file overwritten when a set is handed to a running service. Used only as a fallback, when the service did not report its own QUERYFILE in the lock file. It must match the ExecStart argument of the systemd unit - configuration does not change ExecStart.
service.unrestrictedfalseAllows a DO SYSTEM rule in a plan accepted over the xqry --reset channel. The default value refuses such a plan as a whole (→ xqry). With true the instance leaves a warning in the log at every start, and anyone able to open its IPC objects runs shell commands under its account. The key is read at process start-up, so it is set by the same authority that writes the service’s plan file; it never opens the ad-hoc channel.
limits.history_memory_mib1024Combined history budget for DECLARE sources and MEMORY stores in MiB. Exceeding it rejects the plan at startup, in -c, ad hoc, and during --reset. It must be positive; an invalid value logs a warning and restores the default. See Plan Size Limits.

IPC objects created by the server - the response segment, command queue, subscription queues, and bus segment - receive an explicit 0600 mode. Queue and response-segment creation uses create_only; opening an existing object requires its owner to match the process’s effective UID and its mode to be 0600. xqry must therefore run with the same effective UID as the server, including when invoked by an administrator, for example through sudo -u retractor xqry --server service --dir. Foreign objects are rejected and are not removed during cleanup. See the IPC access boundary for collision, restart, and bus behavior.

Out-of-range values do not stop the service: the program logs a warning and uses the default. The exceptions are storage.dir, whose invalidity would mean results landing somewhere unintended, or nowhere, and sources.timeout_s, whose silent replacement with the default would change how sources are waited for - both are hard errors of xretractor. xqry does not check sources.timeout_s. An invalid storage.ref_dirs is also a hard error, but for xtrdb: the list of permitted write locations must not be guessed.

Example file:

[storage]
dir = "/var/lib/retractor"
default_retention = [1000, 4]

[sources]
timeout_s = 0.01

[limits]
history_memory_mib = 1024

[ipc]
queue_buffer_seconds = 30

[scheduling]
rt_priority = 60

[paths]
lock_dir = "/var/run/retractor"

[server]
autoname = false

NOTE: Layer loading and validation are covered by the ut_appConfig unit test; hard rejection of an invalid storage.dir, a malformed TOML file and a relative paths.lock_dir by the config_storage_validation integration test, and the precedence and rejection of sources.timeout_s by the device_timeout integration test.


Service and plan replacement

Starting without an .rql file, or with an empty one, creates an idle instance with working IPC. The first or a later complete plan can be loaded without restarting:

xqry --server service --reset plan.rql

The server parses and compiles the complete contents, checks retained .desc files, storage compatibility under :ROTATION, and resource collisions, reserves the new set, and then switches plans at a slot boundary. A malformed, empty, or incompatible descriptor causes a refusal with a reason; the old plan and the service startup file remain unchanged. An empty reset file returns the server to idle. On a service instance, the server also attempts to write accepted contents to the service’s startup file. A failed write is logged and does not stop the new plan, but a restart may restore the previous contents. The reset’s OK response does not guarantee plan durability.

The alternative xretractor new-plan.rql path detects a running systemd unit and validates the set, stores, descriptors, and rotation counter before atomically overwriting its startup file and requesting a restart. A plan refusal returns EPROTO (71 on Linux), while an environment refusal returns EIO (5); the message includes nothing was changed. The running service keeps its plan and is not restarted. Explicitly selecting another identity with --name or --autoname starts a separate instance instead.

Startup, plan delivery, reset, and ad hoc import share storage checks before changing the plan. They check the STORAGE directory (which must exist even for a plan using only MEMORY), retained profiles and descriptors, source existence, kinds and read permissions, and whether output data files and applicable .shadow files can be opened. The open check creates no new files. A bad .desc produces a diagnostic naming its path; a syntax error also identifies the line and column. DECLARE source descriptors are always checked; on startup and reset, output and substrate descriptors are checked when :ROTATION preserves their files. Ad hoc import checks new streams’ descriptors even without rotation and for MEMORY, because it does not delete them first.

Plan refusal and environment failure

Causexretractor responsePlan file in a systemd unit
Plan error: syntax, compilation, missing STORAGE directory, incompatible retained .desc, or invalid counter contentsrefusal, EPROTO (71 on Linux)cleared when startup is refused; the next start is idle
Environment error K4: missing DECLARE source, denied access, I/O failure, unreadable counter, or a symbolic link at an output path (ELOOP)EIO (5); during execution, FATAL (environment):preserved for another start after repair
Engine invariant violation, rdb::fatal() or the FatalError boundaryEXIT_FAILURE (1), FATAL:cleared by exit cleanup

The core propagates execution errors through Result. The xretractor boundary distinguishes Errc::IO from an internal error and runs the corresponding termination procedure; rdb::fatal() uses the handler installed by the launcher. The systemd unit since #475 also uses ExecStopPost: after SIGABRT or OOM kill it clears the plan file, because these terminations do not run atexit. An ordinary I/O failure preserves the plan. This policy requires the current unit and xretractor-stop-post helper, rather than only replacing the binary. it_service_abort-run guards it.

EIO identifies the process error category; causes such as EACCES or ENOSPC appear in diagnostics. Outside a unit, the operator’s .rql file remains unchanged. Compile-only mode (-c) neither checks declared sources, storage files or the counter nor clears the query file, even inside a unit. A reset or ad hoc request refused before acceptance returns the reason to the client, while the running server keeps its plan.

A successful check does not guarantee a later open: files can change on disk in between. A model-construction refusal retains its cause class: a plan error yields EPROTO, an environment error yields EIO, and no partial model is published. On reset, a change after the OK response but before model construction can terminate the process with the same code; the previous model has already been dismantled. Reset does not roll back this late failure. The checks are covered by it_storage_refusal-*, it_plan_error_e4-run, it_env_error_exit-run, it_untileof_stop-missing-sources, and ut_fatalError.

The supplied systemd unit template sets Restart=on-failure, RestartSec=5, RestartSteps=5, and RestartMaxDelaySec=5min. On versions supporting these keys, retry delays grow from 5 seconds to 5 minutes in five steps. The template sets no StartLimit* options, so administrator limits still apply; unlimited retries are not guaranteed. Check older systemd versions on the target host. Keeping the plan after an environment failure is not a checkpoint: a restart does not guarantee state restoration or freedom from lost or repeated data.


Version Information

At the end of every help message, a line with build information is displayed:

Branch: issue_31-doc:2707ce0,
Code compiler: GNU Ver. 13.3.0,
Build time: 2512211449,
Type: Debug
FieldMeaning
BranchThe repository branch name and the commit hash the program was built from
Code compilerThe GCC compiler version used for the build
Build timeThe compilation date and time, in YYMMDDHHMM format (here: December 21, 2025, 14:49)
TypeThe build type: Debug or Release

The next line indicates the log file location:

Log: /tmp/xretractor.log

The file /tmp/xretractor.log records the history of invocations and the system’s internal events. In a production environment, this file should be cleaned up or rotated regularly.

The Config: Defaults line means that no TOML files were loaded. If configuration was loaded, Config: lists the file paths in load order. For a syntax error in a plan loaded from a file, the parser’s log entry also includes that file’s path.

The last line contains MIT license information, which allows safe use of the code in corporate applications.