Action functions

/* action operations             */
ham_action_t *ham_action_restart(ham_condition_t *chdl, const char *aname, 
              const char *path, unsigned flags);
ham_action_t *ham_action_execute(ham_condition_t *chdl, const char *aname, 
              const char *path, unsigned flags);
ham_action_t *ham_action_waitfor(ham_condition_t *chdl, const char *aname, 
              const char *path, int delay, unsigned flags);
ham_action_t *ham_action_notify_pulse(ham_condition_t *chdl, const char *aname, 
              int nd, int topid, int chid, int pulsecode, int value, 
              unsigned flags);
ham_action_t *ham_action_notify_signal(ham_condition_t *chdl, const char *aname, 
              int nd, pid_t topid, int signum, int code, int value, 
              unsigned flags);
ham_action_t *ham_action_notify_pulse_node(ham_condition_t *chdl, 
              const char *aname, const char *nodename, int topid, int chid, 
              int pulsecode, int value, unsigned flags);
ham_action_t *ham_action_notify_signal_node(ham_condition_t *chdl, 
              const char *aname, const char *nodename, pid_t topid, 
              int signum, int code, int value, unsigned flags);
ham_action_t *ham_action_heartbeat_healthy(ham_condition_t *chdl, 
              const char *aname, unsigned flags);
ham_action_t *ham_action_log(ham_condition_t *chdl, const char *aname, 
              const char *msg, unsigned attachprefix, int verbosity, 
              unsigned flags);

/* remove an action              */
int ham_action_remove(ham_action_t *ahdl, unsigned flags);

As mentioned earlier, a HAM currently supports several different types of action functions, but note that you can add your own action functions to suit your particular HA application.

ham_action_restart()
Provides a restart mechanism for the entity in the event that a death condition has occurred. This implies that the entity in question has terminated; the restart action will restart the entity and also keep track of the new pid that the entity will now be associated with.
Note: Restart actions can be associated only with death conditions. And across all conditions of type death, there can be only a single restart action at any time. This ensures that the entity is restarted only if it terminates, and only once. (Conditions of type death include conditions of the types CONDDEATH and CONDABNORMALDEATH.
ham_action_execute()
Executes an arbitrary command in the event that the condition is true. This could be any executable command line. When the condition in question is true, the list of actions is traversed and executed in sequence.

This executes a command line as specified in the parameters. The command line must contain the FULL path to the executable along with all parameters to be passed to it. The command line is in turn passed onto a spawn command by a HAM to create a new process that will execute the command.

You'll find execute actions useful when you need to set up a multistage recovery. For example, if fs-nfs2 dies and is restarted, the ham_action_execute() function lets you remount any directories that are required after fs-nfs2 is restarted.

You can have an execute action take place immediately by setting the HACTIONDONOW flag. Again, this is useful in startup situations when an entity is created in many stages.

Note that HACTIONDONOW is ignored for waitfor actions. So in order to insert delays into a sequence of actions flagged HACTIONDONOW, you'll need to insert the delays in the client program (between calls to ham_action*()).

ham_action_waitfor()
Given a sequence of actions in a condition that will execute in FIFO order, you can insert delays into the execution sequence by using ham_action_waitfor() (as long as the condition permits it — see the section Condition functions in this chapter). The delay specified is in multiples of 100 msecs.

The ham_action_waitfor() call takes as an argument a path component, which can be used to wait for a specific name to appear in the name space. If path is NULL, the waitfor is for exactly delay msecs. But if path is specified, the waitfor is for either delay msecs or until path appears in the namespace, whichever occurs earlier. Note that the delay when a pathname is specified is in integral multiples of 100 msecs.

If a pathname is specified, the delays will be the closest integral multiple of 100 msecs, rounding up. A delay of 0 effectively disables the waitfor, making the pathname specification redundant.

ham_action_notify_pulse(), ham_action_notify_signal()
The ham_action_notify_pulse() function sends the appropriate pulse to the given nd/pid/chid.

The action_notify_signal() sends an appropriate realtime signal with a value to the pid that requests it.

Actions can persist across a restart if the entity is restarted. Similarly, conditions can also be set to persist (i.e., you can rearm them) after a restart of the entity. You can do this by ORing HREARMAFTERRESTART into the flags argument to either the ham_condition() call or to the appropriate action statement.

If a condition persists when an entity is restarted, each individual action is checked to see if it also persists. Actions that needn't be rearmed are performed once and removed. Any actions that fail are also removed, even if they're set to be rearmed.

If a condition isn't marked as rearmed, then all actions under it are automatically removed, since the actions are associated only with the condition and can't be retained if the condition no longer exists.

The persistence of conditions and actions across a restart depends on the restart of the entity itself. So if the entity isn't restarted (i.e., there's no ACTIONRESTART or the ACTIONRESTART fails for some reason), then the entity is removed, along with all conditions and actions associated with the entity as well.

ham_action_notify_pulse_node()
This is the same as the ham_action_notify_pulse() above, except that the node name specified for the recipient of the pulse can be given using the fully qualified node name instead of the node identifier (nd).
ham_action_notify_signal_node()
This is the same as the ham_action_notify_signal() above, except that the node name specified for the recipient of the signal can be given using the fully qualified node name instead of the node identifier (nd).