-
Notifications
You must be signed in to change notification settings - Fork 50
Module guide
DRAFT
Flux services are implemented as comms modules. Each module runs in
its own thread, currently within the flux-broker
process, although
it is planned to allow modules to run in standalone processes.
RFC 5/Flux Module Extension Protocol describes Flux extension modules, the static symbols they must define, how they are loaded and unloaded, and how they synchronize with the broker when they start and stop.
RFC 3/CMB1 - Flux Comms Message Broker Protocol describes how request messages are routed to services, and response messages are routed back to the requestor.
This document will serve as a brief practical guide to the module writer.
The module declares its own name with the MOD_NAME()
macro. Normally
the module name is also the service name (e.g. the topic string prefix
for the service provided by the module), however an additional name may
be registered with the MOD_SERVICE()
macro, which can be used when modules
of different names provide the same interface.
The module provides one entry point with the following prototype:
int mod_main (flux_t *h, int argc, char **argv)
The Flux handle h
represents a shared memory connection to the broker.
It is created before mod_main()
is run, and destroyed After mod_main()
exits.
Several request message handlers are registered on the handle to provide service for methods common to all modules. The methods are:
shutdown
stat.get
stats.clear
debug
ping
rusage
Normally mod_main()
registers some message handlers of its own
and enters the reactor loop with flux_reactor_run(3)
.
The module should not call exit(3)
, or any functions that call it,
as this terminates the broker. Instead, if a fatal error occurs in the
module, it should call flux_reactor_stop_error(3)
, which causes
flux_reactor_run()
to return an error.
If flux_reactor_run()
returns an error, mod_main()
should return with
a negative return code and errno set.
A typical mod_main()
looks similar to this one:
static struct flux_msg_handler_spec htab[] = {
{ FLUX_MSGTYPE_REQUEST, "userdb.lookup", lookup, 0, NULL },
{ FLUX_MSGTYPE_REQUEST, "userdb.addrole", addrole, 0, NULL },
{ FLUX_MSGTYPE_REQUEST, "userdb.delrole", delrole, 0, NULL },
{ FLUX_MSGTYPE_REQUEST, "userdb.getnext", getnext, 0, NULL },
{ FLUX_MSGTYPE_REQUEST, "userdb.disconnect", disconnect, 0, NULL },
FLUX_MSGHANDLER_TABLE_END,
};
int mod_main (flux_t *h, int argc, char **argv)
{
int rc = -1;
userdb_ctx_t *ctx;
struct user *up;
if (!(ctx = getctx (h, argc, argv))) {
goto done;
}
if (!(up = user_add (ctx, geteuid (), FLUX_ROLE_OWNER))) {
flux_log_error (h, "failed to add owner to userdb");
goto done;
}
if (flux_msg_handler_addvec (h, htab, ctx) < 0) {
flux_log_error (h, "flux_msghandler_add");
goto done;
}
if (flux_reactor_run (flux_get_reactor (h), 0) < 0) {
flux_log_error (h, "flux_reactor_run");
goto done_unreg;
}
rc = 0;
done_unreg:
flux_msg_handler_delvec (htab);
done:
return rc;
}
MOD_NAME ("userdb");
Modules may be loaded and unloaded dynamically with flux-module(1)
.
The instance's rc1 script (running on rank 0) takes care of loading modules at instance startup. The rc3 script unloads them.
- listing module status (
flux module list
) - module debug flags (
flux module debug
) - the disconnect message
- reactive programming constraints
- modules as processes
- overriding the
stats
method - security (handling request by guest users)