blob: 729a0daa5e2653faf56cba845aaa5b3f0ddfc8c2 [file] [edit]
/*****************************************************************************\
* relay_io.h - IO relay interface
*****************************************************************************
* Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* This file is part of Slurm, a resource management program.
* For details, see <https://slurm.schedmd.com/>.
* Please also read the included file: DISCLAIMER.
*
* Slurm is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* In addition, as a special exception, the copyright holders give permission
* to link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two. You must obey the GNU
* General Public License in all respects for all of the code used other than
* OpenSSL. If you modify file(s) with this exception, you may extend this
* exception to your version of the file(s), but you are not obligated to do
* so. If you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files in
* the program, then also delete it here.
*
* Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with Slurm; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\*****************************************************************************/
#ifndef _INTERFACES_RELAY_IO_H
#define _INTERFACES_RELAY_IO_H
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include "slurm/slurm.h"
#include "src/common/data.h"
#include "src/common/slurm_time.h"
/*
* Version of the record schema documented in relay_io.shtml. Bump this
* whenever the meaning of an existing field changes, so that a consumer can
* tell one layout from another.
*/
#define RELAY_IO_SCHEMA_VERSION 1
typedef enum {
RELAY_IO_STREAM_STDOUT = 0,
RELAY_IO_STREAM_STDERR,
} relay_io_stream_t;
typedef enum {
RELAY_IO_EVENT_LOG = 0,
RELAY_IO_EVENT_JOB_START,
RELAY_IO_EVENT_JOB_END,
RELAY_IO_EVENT_STEP_START,
RELAY_IO_EVENT_STEP_END,
} relay_io_event_t;
/*
* Identity carried on every record, so a consumer can tie an event back to
* where it was produced. All pointers are borrowed and must outlive the call.
*/
typedef struct {
const char *account; /* job events only, may be NULL */
const char *cluster; /* ClusterName */
uint32_t job_id;
const char *node; /* node the event was produced on */
const char *partition; /* job events only, may be NULL */
uint16_t restart_count; /* times the job has been requeued */
sluid_t sluid;
const char *user_name; /* submitting user, may be NULL */
} relay_io_ident_t;
/*
* A single event. For RELAY_IO_EVENT_LOG the step, task, stream and body
* fields describe one line, or one chunk of unbuffered output. For the
* lifecycle events only ident, type and time are meaningful, except that the
* step events also carry step_id.
*/
typedef struct {
const char *body; /* borrowed, need not be NULL terminated */
size_t body_len;
relay_io_ident_t ident;
bool partial; /* flushed without a trailing newline */
uint32_t step_id; /* SLURM_BATCH_SCRIPT, or the step number */
relay_io_stream_t stream;
uint32_t task_id_global;
uint32_t task_id_local;
timespec_t time; /* when the event was produced */
relay_io_event_t type;
bool unbuffered; /* produced by a step using --unbuffered */
} relay_io_record_t;
/*
* Load and initialize the configured relay_io plugin, if RelayIOPlugin is set.
* IN spooldir - SlurmdSpoolDir, already %n expanded, used to locate sockets
* RET SLURM_SUCCESS or error
*/
extern int relay_io_g_init(const char *spooldir);
/*
* Unload the relay_io plugin.
* RET SLURM_SUCCESS or error
*/
extern int relay_io_g_fini(void);
/*
* Queue an event for relaying. Never blocks, and may drop the record.
* IN record - event to relay, borrowed for the duration of the call
* OUT consumed_ptr - bytes of record->body this record carries, never 0 for a
* non-empty body. The caller passes the rest in a further record. NULL if
* the caller has no body to place.
* RET SLURM_SUCCESS or error, which does not indicate delivery
*/
extern int relay_io_g_record(const relay_io_record_t *record,
size_t *consumed_ptr);
/*
* Check whether RelayIOPlugin names a plugin to load, without loading it.
* RET true if RelayIOPlugin is set and is not "none"
*/
extern bool relay_io_configured(void);
/*
* Resolve a job's --relay-io request against this daemon's configuration.
* IN requested - value the job asked for, NO_VAL16 if it did not ask
* RET true if this job's output should be relayed
*/
extern bool relay_io_requested(uint16_t requested);
/*
* Narrow a job's resolved relay_io setting to one step on this node.
* IN step_id - id of the step in question
* IN relay_io - what slurmctld resolved for the job
* RET true if this step's output should be relayed, which is never true for
* the extern step or on a node with no plugin configured
*/
extern bool relay_io_step_requested(uint32_t step_id, bool relay_io);
/*
* Emit a job start record. The caller emits it once per node, and only for a
* job that relays.
* IN ident - identity of the job, copied
*/
extern void relay_io_g_job_start(const relay_io_ident_t *ident);
/*
* Emit a job end record. The caller pairs it with relay_io_g_job_start().
* IN ident - identity of the job, copied
*/
extern void relay_io_g_job_end(const relay_io_ident_t *ident);
/* One task's stdout or stderr, turned into records on the relay thread */
typedef struct relay_io_src_s relay_io_src_t;
/*
* Register a source of task output.
* IN ident - identity every record from this source carries, copied
* IN step_id - step the task belongs to
* IN task_id_global / task_id_local - task the output came from
* IN stream - stdout or stderr
* IN unbuffered - true for --unbuffered, to cut output into fixed size chunks
* rather than lines
* RET source, or NULL when nothing is being relayed
*/
extern relay_io_src_t *relay_io_g_src_create(const relay_io_ident_t *ident,
uint32_t step_id,
uint32_t task_id_global,
uint32_t task_id_local,
relay_io_stream_t stream,
bool unbuffered);
/*
* Hand task output to the relay. Blocks while the source is full.
* IN src - source the bytes came from, NULL is a no-op
* IN data - bytes as the task wrote them, neither sanitized nor NULL terminated
* IN len - number of bytes in data
*/
extern void relay_io_g_src_append(relay_io_src_t *src, const char *data,
size_t len);
/*
* Mark a source as finished, so that a trailing line with no newline is
* emitted.
* IN src - source that reached eof, NULL is a no-op
*/
extern void relay_io_g_src_eof(relay_io_src_t *src);
/*
* Free a source. Without relay_io_g_src_eof() first, its trailing partial line
* is lost.
* IN/OUT src_ptr - source to free, set to NULL
*/
extern void relay_io_g_src_destroy(relay_io_src_t **src_ptr);
/*
* Turn what every source still holds into records, and stop the relay thread.
* Call it before the step end record is emitted.
*/
extern void relay_io_g_srcs_drain(void);
/*
* Write out what the plugin still has buffered, giving up after a bounded
* time.
* RET SLURM_SUCCESS or error
*/
extern int relay_io_g_flush(void);
#endif