. $CTDB_BASE/functions
loadconfig
+# If CTDB_RECOVERY_LOCK specifies a helper then exit because this
+# script can't do anything useful.
+case "$CTDB_RECOVERY_LOCK" in
+!*) exit 0 ;;
+esac
+
case "$1" in
init)
ctdb_counter_init
</para>
<para>
- The recovery lock is implemented using a file residing in shared
- storage (usually) on a cluster filesystem. To support a
- recovery lock the cluster filesystem must support lock
- coherence. See
+ By default, the recovery lock is implemented using a file
+ (specified by <parameter>CTDB_RECOVERY_LOCK</parameter>)
+ residing in shared storage (usually) on a cluster filesystem.
+ To support a recovery lock the cluster filesystem must support
+ lock coherence. See
<citerefentry><refentrytitle>ping_pong</refentrytitle>
<manvolnum>1</manvolnum></citerefentry> for more details.
</para>
+ <para>
+ The recovery lock can also be implemented using an arbitrary
+ cluster mutex call-out by using an exclamation point ('!') as
+ the first character of
+ <parameter>CTDB_RECOVERY_LOCK</parameter>. For example, a value
+ of <command>!/usr/local/bin/myhelper recovery</command> would
+ run the given helper with the specified arguments. See the
+ source code relating to cluster mutexes for clues about writing
+ call-outs.
+ </para>
+
<para>
If a cluster becomes partitioned (for example, due to a
communication failure) and a different recovery master is
</varlistentry>
<varlistentry>
- <term>--reclock=<parameter>FILE</parameter></term>
+ <term>--reclock=<parameter>LOCK</parameter></term>
<listitem>
<para>
- FILE is the name of the recovery lock file, stored in
- <emphasis>shared storage</emphasis>, that CTDB uses to
- prevent split brains.
+ LOCK specifies the cluster-wide mutex used to detect and
+ prevent a partitioned cluster (or "split brain").
</para>
<para>
For information about the recovery lock please see the
</varlistentry>
<varlistentry>
- <term>CTDB_RECOVERY_LOCK=<parameter>FILENAME</parameter></term>
+ <term>CTDB_RECOVERY_LOCK=<parameter>LOCK</parameter></term>
<listitem>
<para>
- Defaults to
+ LOCK specifies the cluster-wide mutex used to detect and
+ prevent a partitioned cluster (or "split brain").
+ </para>
+ <para>
+ No default, but the default configuration file specifies
<filename>/some/place/on/shared/storage</filename>, which
should be change to a useful value. Corresponds to
<option>--reclock</option>.
const char *argstring, char ***argv)
{
int nargs, i, ret, n;
+ bool is_command = false;
char **args = NULL;
char *strv = NULL;
char *t = NULL;
- ret = strv_split(mem_ctx, &strv, argstring, " \t");
+ if (argstring != NULL && argstring[0] == '!') {
+ /* This is actually a full command */
+ is_command = true;
+ t = discard_const(&argstring[1]);
+ } else {
+ is_command = false;
+ t = discard_const(argstring);
+ }
+
+ ret = strv_split(mem_ctx, &strv, t, " \t");
if (ret != 0) {
DEBUG(DEBUG_ERR,
("Unable to parse mutex helper string \"%s\" (%s)\n",
}
n = strv_count(strv);
- args = talloc_array(mem_ctx, char *, n + 2);
+ args = talloc_array(mem_ctx, char *, n + (is_command ? 1 : 2));
+
if (args == NULL) {
DEBUG(DEBUG_ERR,(__location__ " out of memory\n"));
return false;
nargs = 0;
- if (!ctdb_set_helper("cluster mutex helper",
- cluster_mutex_helper,
- sizeof(cluster_mutex_helper),
- "CTDB_CLUSTER_MUTEX_HELPER",
- CTDB_HELPER_BINDIR, "ctdb_mutex_fcntl_helper")) {
- DEBUG(DEBUG_ERR,("ctdb exiting with error: %s\n",
- __location__
- " Unable to set cluster mutex helper\n"));
- exit(1);
+ if (! is_command) {
+ if (!ctdb_set_helper("cluster mutex helper",
+ cluster_mutex_helper,
+ sizeof(cluster_mutex_helper),
+ "CTDB_CLUSTER_MUTEX_HELPER",
+ CTDB_HELPER_BINDIR,
+ "ctdb_mutex_fcntl_helper")) {
+ DEBUG(DEBUG_ERR,("ctdb exiting with error: %s\n",
+ __location__
+ " Unable to set cluster mutex helper\n"));
+ exit(1);
+ }
+
+ args[nargs++] = cluster_mutex_helper;
}
- args[nargs++] = cluster_mutex_helper;
t = NULL;
for (i = 0; i < n; i++) {