Configuring plugins

Before we can build a simulation, we need to configure the individual plugins that make up the simulation. This is usually done using a plugin process configuration (pcfg).

Constructing a plugin process configuration

There are two ways to construct the configuration. dqcs_pcfg_new() is the easy one: it will look for the plugin executable in the same way that the command-line interface does it. It works using a single string, which can be:

  • a valid path to the plugin executable;
  • the basename of the plugin executable with implicit dqcsfe/dqcsop/dqcsbe prefix, searched for in A) the current working directory, B) the directory that the binary for the current process resides in, and C) the system $PATH (in that order);
  • a valid path to a script file with a file extension. In this case, the above rule is run for a plugin named by the file extension of the script file. For instance, if test.py is specified for a frontend plugin, DQCsim will look for an executable named dqcsfepy. The script filename is passed to the plugin through the first command-line argument, moving the simulator endpoint string to the second slot.

Alternatively, you can bypass this algorithm by specifying the full path to the plugin and (optionally) the script file directly using dqcs_pcfg_new_raw().

dqcs_pcfg_new()

Creates a new plugin process configuration object using sugared syntax.

dqcs_handle_t dqcs_pcfg_new(
    dqcs_plugin_type_t typ,
    const char *name,
    const char *spec
)

typ specifies the type of plugin. name specifies the name used to refer to the plugin later, which much be unique within a simulation; if it is empty or NULL, auto-naming will be performed: "front" for the frontend, "oper<i>" for the operators (indices starting at 1 from frontend to backend), and "back" for the backend. spec specifies which plugin to use, using the same syntax that the dqcsim command line interface uses.

dqcs_pcfg_new_raw()

Creates a new plugin process configuration object using raw paths.

dqcs_handle_t dqcs_pcfg_new_raw(
    dqcs_plugin_type_t typ,
    const char *name,
    const char *executable,
    const char *script
)

This works the same as dqcs_pcfg_new(), but instead of the sugared, command-line style specification you have to specify the path to the plugin executable and (if applicable) the script it must execute directly. This is useful when you have a specific executable in mind and you don't want the somewhat heuristic desugaring algorithm from doing something unexpected.

Pass NULL or an empty string to script to specify a native plugin executable that does not take a script argument.

After construction, the plugin type, name, executable path, and optional script path become immutable. However, their values can be queried using the following functions.

dqcs_pcfg_type()

Returns the type of the given plugin process configuration.

dqcs_plugin_type_t dqcs_pcfg_type(dqcs_handle_t pcfg)
dqcs_pcfg_name()

Returns the configured name for the given plugin process.

char *dqcs_pcfg_name(dqcs_handle_t pcfg)

On success, this returns a newly allocated string containing the name. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_pcfg_executable()

Returns the configured executable path for the given plugin process.

char *dqcs_pcfg_executable(dqcs_handle_t pcfg)

On success, this returns a newly allocated string containing the executable path. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_pcfg_script()

Returns the configured script path for the given plugin process.

char *dqcs_pcfg_script(dqcs_handle_t pcfg)

On success, this returns a newly allocated string containing the script path. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL. An empty string will be returned if no script is configured to distinguish it from failure.

Functional configuration

A plugin's behavior can be augmented using a list of ArbCmds passed to its initialization callback and through environment variables. These can be set using the following functions.

dqcs_pcfg_init_cmd()

Appends an ArbCmd to the list of initialization commands of a plugin process.

dqcs_return_t dqcs_pcfg_init_cmd(
    dqcs_handle_t pcfg,
    dqcs_handle_t cmd
)

The ArbCmd handle is consumed by this function, and is thus invalidated, if and only if it is successful.

dqcs_pcfg_env_set()

Overrides an environment variable for the plugin process.

dqcs_return_t dqcs_pcfg_env_set(
    dqcs_handle_t pcfg,
    const char *key,
    const char *value
)

The environment variable key is set to value regardless of whether it exists in the parent environment variable scope.

If value is NULL, the environment variable key is unset instead.

dqcs_pcfg_env_unset()

Removes/unsets an environment variable for the plugin process.

dqcs_return_t dqcs_pcfg_env_unset(
    dqcs_handle_t pcfg,
    const char *key
)

The environment variable key is unset regardless of whether it exists in the parent environment variable scope.

It's also possible to assign a different working directory to a plugin process using the following functions.

dqcs_pcfg_work_set()

Overrides the working directory for the plugin process.

dqcs_return_t dqcs_pcfg_work_set(
    dqcs_handle_t pcfg,
    const char *work
)
dqcs_pcfg_work_get()

Returns the configured working directory for the given plugin process.

char *dqcs_pcfg_work_get(dqcs_handle_t pcfg)

On success, this returns a newly allocated string containing the working directory. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

These configuration parameters are recorded in reproduction files, since they may modify the behavior of the plugin.

Logging configuration

DQCsim allows log message filtering to be performed independently for each plugin. The following functions can be used to configure this per-plugin filter. The verbosity defaults to trace to pass all messages through; the messages will also be filtered by DQCsim itself.

dqcs_pcfg_verbosity_set()

Configures the logging verbosity for the given plugin process.

dqcs_return_t dqcs_pcfg_verbosity_set(
    dqcs_handle_t pcfg,
    dqcs_loglevel_t level
)
dqcs_pcfg_verbosity_get()

Returns the configured verbosity for the given plugin process.

dqcs_loglevel_t dqcs_pcfg_verbosity_get(dqcs_handle_t pcfg)

You can also let DQCsim pipe only the messages of a specific plugin to a file. This behavior can be configured using dqcs_pcfg_tee().

dqcs_pcfg_tee()

Configures a plugin process to also output its log messages to a file.

dqcs_return_t dqcs_pcfg_tee(
    dqcs_handle_t pcfg,
    dqcs_loglevel_t verbosity,
    const char *filename
)

verbosity configures the verbosity level for the file only.

Finally, DQCsim will by default capture the stdout and stderr streams of the plugin process and convert each received line into a log message. The following functions can be used to configure the loglevels used for these messages, to disable capturing, or to void the streams altogether.

dqcs_pcfg_stdout_mode_set()

Configures the capture mode for the stdout stream of the specified plugin process.

dqcs_return_t dqcs_pcfg_stdout_mode_set(
    dqcs_handle_t pcfg,
    dqcs_loglevel_t level
)
dqcs_pcfg_stdout_mode_get()

Returns the configured stdout capture mode for the specified plugin process.

dqcs_loglevel_t dqcs_pcfg_stdout_mode_get(dqcs_handle_t pcfg)
dqcs_pcfg_stderr_mode_set()

Configures the capture mode for the stderr stream of the specified plugin process.

dqcs_return_t dqcs_pcfg_stderr_mode_set(
    dqcs_handle_t pcfg,
    dqcs_loglevel_t level
)
dqcs_pcfg_stderr_mode_get()

Returns the configured stderr capture mode for the specified plugin process.

dqcs_loglevel_t dqcs_pcfg_stderr_mode_get(dqcs_handle_t pcfg)

Timeouts

DQCsim uses a timeout mechanism when spawning a plugin and shutting it down to detect deadlocks due to misconfiguration. This timeout defaults to 5 seconds. If your plugin needs more time to start up or shut down gracefully for some reason, you can modify the timeouts using the following functions.

dqcs_pcfg_accept_timeout_set()

Configures the timeout for the plugin process to connect to DQCsim.

dqcs_return_t dqcs_pcfg_accept_timeout_set(
    dqcs_handle_t pcfg,
    double timeout
)

The default is 5 seconds, so you should normally be able to leave this alone.

The time unit is seconds. Use IEEE positive infinity to specify an infinite timeout.

dqcs_pcfg_accept_timeout_get()

Returns the configured timeout for the plugin process to connect to DQCsim.

double dqcs_pcfg_accept_timeout_get(dqcs_handle_t pcfg)

The time unit is in seconds. Returns positive inifinity for an infinite timeout. Returns -1 when the function fails.

dqcs_pcfg_shutdown_timeout_set()

Configures the timeout for the plugin process to shut down gracefully.

dqcs_return_t dqcs_pcfg_shutdown_timeout_set(
    dqcs_handle_t pcfg,
    double timeout
)

The default is 5 seconds, so you should normally be able to leave this alone.

The time unit is seconds. Use IEEE positive infinity to specify an infinite timeout.

dqcs_pcfg_shutdown_timeout_get()

Returns the configured timeout for the plugin process to shut down gracefully.

double dqcs_pcfg_shutdown_timeout_get(dqcs_handle_t pcfg)

The time unit is in seconds. Returns positive inifinity for an infinite timeout. Returns -1 when the function fails.