diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:40:13 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:40:13 +0000 |
commit | e9be59e1502a41bab9891d96d753102a7dafef0b (patch) | |
tree | c3b2da87c414881f4b53d0964f407c83492d813e /include | |
parent | Initial commit. (diff) | |
download | cluster-glue-e9be59e1502a41bab9891d96d753102a7dafef0b.tar.xz cluster-glue-e9be59e1502a41bab9891d96d753102a7dafef0b.zip |
Adding upstream version 1.0.12.upstream/1.0.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include')
54 files changed, 6137 insertions, 0 deletions
diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..2e07275 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright (C) 2008 Andrew Beekhof +# +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +MAINTAINERCLEANFILES = Makefile.in +SUBDIRS = clplumbing pils stonith lrm + +idir=$(includedir)/heartbeat +i_HEADERS = compress.h glue_config.h ha_msg.h + +noinst_HEADERS = config.h lha_internal.h replace_uuid.h diff --git a/include/clplumbing/GSource.h b/include/clplumbing/GSource.h new file mode 100644 index 0000000..2acc9eb --- /dev/null +++ b/include/clplumbing/GSource.h @@ -0,0 +1,236 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CLPLUMBING_GSOURCE_H +# define _CLPLUMBING_GSOURCE_H +# include <clplumbing/ipc.h> + +typedef struct GFDSource_s GFDSource; +typedef struct GCHSource_s GCHSource; +typedef struct GWCSource_s GWCSource; +typedef struct GSIGSource_s GSIGSource; +typedef struct GTRIGSource_s GTRIGSource; + + +void G_main_setmaxdispatchdelay(GSource* s, unsigned long delayms); +void G_main_setmaxdispatchtime(GSource* s, unsigned long dispatchms); +void G_main_setdescription(GSource* s, const char * description); + +void G_main_setmaxdispatchdelay_id(guint id, unsigned long delayms); +void G_main_setmaxdispatchtime_id(guint id, unsigned long dispatchms); +void G_main_setdescription_id(guint id, const char * description); +void G_main_setall_id(guint id, const char * description, unsigned long delayms, unsigned long dispatchms); + + +/*********************************************************************** + * Functions for interfacing input to the mainloop + ***********************************************************************/ + +GSource* +G_main_add_input(int priority, + gboolean can_recurse, + GSourceFuncs* funcs); + +/*********************************************************************** + * Functions for interfacing "raw" file descriptors to the mainloop + ***********************************************************************/ +/* +* Add a file descriptor to the gmainloop world... + */ +GFDSource* G_main_add_fd(int priority, int fd, gboolean can_recurse +, gboolean (*dispatch)(int fd, gpointer user_data) +, gpointer userdata +, GDestroyNotify notify); + +/* + * Delete a file descriptor from the gmainloop world... + * Note: destroys the GFDSource object. + */ +gboolean G_main_del_fd(GFDSource* fdp); + +/* + * Notify us that a file descriptor is blocked on output. + * (i.e., we should poll for output events) + */ +void g_main_output_is_blocked(GFDSource* fdp); + + +/************************************************************** + * Functions for interfacing IPC_Channels to the mainloop + **************************************************************/ +/* + * Add an IPC_channel to the gmainloop world... + */ +GCHSource* G_main_add_IPC_Channel(int priority, IPC_Channel* ch +, gboolean can_recurse +, gboolean (*dispatch)(IPC_Channel* source_data +, gpointer user_data) +, gpointer userdata +, GDestroyNotify notify); + +/* + * the events in this source is paused/resumed + */ + +void G_main_IPC_Channel_pause(GCHSource* chp); +void G_main_IPC_Channel_resume(GCHSource* chp); + + +/* + * Delete an IPC_channel from the gmainloop world... + * Note: destroys the GCHSource object, and the IPC_Channel + * object automatically. + */ +gboolean G_main_del_IPC_Channel(GCHSource* chp); + + +/* + * Set the destroy notify function + * + */ +void set_IPC_Channel_dnotify(GCHSource* chp, + GDestroyNotify notify); + + +/********************************************************************* + * Functions for interfacing IPC_WaitConnections to the mainloop + ********************************************************************/ +/* + * Add an IPC_WaitConnection to the gmainloop world... + * Note that the dispatch function is called *after* the + * connection is accepted. + */ +GWCSource* G_main_add_IPC_WaitConnection(int priority, IPC_WaitConnection* ch +, IPC_Auth* auth_info +, gboolean can_recurse +, gboolean (*dispatch)(IPC_Channel* source_data +, gpointer user_data) +, gpointer userdata +, GDestroyNotify notify); + +/* + * Delete an IPC_WaitConnection from the gmainloop world... + * Note: destroys the GWCSource object, and the IPC_WaitConnection + * object automatically. + */ +gboolean G_main_del_IPC_WaitConnection(GWCSource* wcp); + + +/************************************************************** + * Functions for interfacing Signals to the mainloop + **************************************************************/ +/* + * Add an Signal to the gmainloop world... + */ +GSIGSource* G_main_add_SignalHandler( + int priority, int signal, + gboolean (*dispatch)(int nsig, gpointer user_data), + gpointer userdata, GDestroyNotify notify); + +/* + * Delete an signal from the gmainloop world... + * Note: destroys the GSIGSource object, and the removes the + * Signal Handler automatically. + */ +gboolean G_main_del_SignalHandler(GSIGSource* chp); + + +/* + * Set the destroy notify function + * + */ +void set_SignalHandler_dnotify(GSIGSource* chp, GDestroyNotify notify); + + +/* manage child process death using sig source*/ +#define DEFAULT_MAXDISPATCHTIME 30 /* in ms */ +void set_sigchld_proctrack(int priority, unsigned long maxdisptime); + + + +/************************************************************** + * Functions for interfacing Manual triggers to the mainloop + **************************************************************/ +/* + * Add an Trigger to the gmainloop world... + */ +GTRIGSource* G_main_add_TriggerHandler( + int priority, gboolean (*dispatch)(gpointer user_data), + gpointer userdata, GDestroyNotify notify); + +/* + * Delete an signal from the gmainloop world... + * Note: destroys the GTRIGSource object, and the removes the + * Trigger Handler automatically. + */ +gboolean G_main_del_TriggerHandler(GTRIGSource* chp); + + +/* + * Set the destroy notify function + * + */ +void set_TriggerHandler_dnotify(GTRIGSource* chp, GDestroyNotify notify); + + +void G_main_set_trigger(GTRIGSource* man_src); + +/* + * Create a trigger for triggering an action in a short-lived (temporary) + * child process. + * + * The name isn't wonderful, but we couldn't think of a better one. + */ +GTRIGSource* G_main_add_tempproc_trigger(int priority +, int (*fun)(gpointer p) /* What to do? */ + /* Called in child process */ +, const char * procname /* What do we call this process? */ +, gpointer userdata /* Passed to 'triggerfun' */ +, void (*prefork)(gpointer p) /* Called before fork */ +, void (*postfork)(gpointer p) /* Called by parent process + * after fork(2) call. + * Each has 'userdata' + * passed to it. + */ +, void (*complete)(gpointer p, int status, int signo, int exitcode)); /* called after the child process completes */ + +/* + * Special notes: + * - No more than one child process will be active at a time per trigger + * object. + * + * - If you trigger the action while this object has a child active, + * then it will be re-triggered after the currently running child + * completes. There is no necessary correlation between the + * number of times a the action is triggered and how many + * times it is executed. What is guaranteed is that after you + * trigger the action, it will happen (at least) once - as soon + * as the scheduler gets around to it at the priority you've + * assigned it. But if several are triggered while a child + * process is running, only one process will be instantiated to + * take the action requested by all the trigger calls. + * + * - Child processes are forked off at the priority of the trigger, + * not the priority of the SIGCHLD handler. + * + * - This is useful for writing out updates to a file for example. + * While we're writing one copy out, subsequent updates are + * held off until this one completes. When it completes, then + * the file is written again - but not "n" times - just the + * latest version available at the time the trigger is + * activated (run). + */ +#endif diff --git a/include/clplumbing/GSource_internal.h b/include/clplumbing/GSource_internal.h new file mode 100644 index 0000000..c20a9c9 --- /dev/null +++ b/include/clplumbing/GSource_internal.h @@ -0,0 +1,111 @@ +/* + * Author: Alan Robertson <alanr@unix.sh> + * Copyright (C) 2005 International Business Machines Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <clplumbing/longclock.h> +#include <clplumbing/GSource.h> + +#define MAG_GFDSOURCE 0xfeed0001U +#define MAG_GCHSOURCE 0xfeed0002U +#define MAG_GWCSOURCE 0xfeed0003U +#define MAG_GSIGSOURCE 0xfeed0004U +#define MAG_GTRIGSOURCE 0xfeed0005U +#define MAG_GTIMEOUTSRC 0xfeed0006U + +#define IS_FDSOURCE(p) (p && (p)->magno == MAG_GFDSOURCE) +#define IS_CHSOURCE(p) (p && (p)->magno == MAG_GCHSOURCE) +#define IS_WCSOURCE(p) (p && (p)->magno == MAG_GWCSOURCE) +#define IS_SIGSOURCE(p) (p && (p)->magno == MAG_GSIGSOURCE) +#define IS_TRIGSOURCE(p) (p && (p)->magno == MAG_GTRIGSOURCE) +#define IS_TIMEOUTSRC(p) (p && (p)->magno == MAG_GTIMEOUTSRC) + +#define IS_ONEOFOURS(p) (IS_CHSOURCE(p)|IS_FDSOURCE(p)|IS_WCSOURCE(p)|| \ + IS_SIGSOURCE(p)|IS_TRIGSOURCE(p)||IS_TIMEOUTSRC(p)) + + +#define DEFAULT_MAXDISPATCH 0 +#define DEFAULT_MAXDELAY 0 +#define OTHER_MAXDELAY 100 + +#define COMMON_STRUCTSTART \ +GSource source; /* Common glib struct - must be 1st */ \ +unsigned magno; /* Magic number */ \ +long maxdispatchms; /* Time limit for dispatch function */ \ +long maxdispatchdelayms; /* Max delay before processing */ \ +char detecttime[sizeof(longclock_t)]; \ + /* Time last input detected */ \ +void* udata; /* User-defined data */ \ +guint gsourceid; /* Source id of this source */ \ +const char * description; /* Description of this source */ \ +GDestroyNotify dnotify + +struct GFDSource_s { + COMMON_STRUCTSTART; + gboolean (*dispatch)(int fd, gpointer user_data); + GPollFD gpfd; +}; + + +typedef gboolean (*GCHdispatch)(IPC_Channel* ch, gpointer user_data); + +struct GCHSource_s { + COMMON_STRUCTSTART; + IPC_Channel* ch; + gboolean fd_fdx; + GPollFD infd; + GPollFD outfd; + gboolean dontread; /* TRUE when we don't want to read + * more input for a while - we're + * flow controlling the writer off + */ + gboolean (*dispatch)(IPC_Channel* ch, gpointer user_data); +}; + +struct GWCSource_s { + COMMON_STRUCTSTART; + GPollFD gpfd; + IPC_WaitConnection* wch; + IPC_Auth* auth_info; + gboolean (*dispatch)(IPC_Channel* accept_ch, gpointer udata); +}; + +struct GSIGSource_s { + COMMON_STRUCTSTART; + clock_t sh_detecttime; + int signal; + gboolean signal_triggered; + gboolean (*dispatch)(int signal, gpointer user_data); +}; + +struct GTRIGSource_s { + COMMON_STRUCTSTART; + gboolean manual_trigger; + gboolean (*dispatch)(gpointer user_data); +}; + +/************************************************************ + * Functions for IPC_Channels + ***********************************************************/ +gboolean G_CH_prepare_int(GSource* source, gint* timeout); +gboolean G_CH_check_int(GSource* source); +gboolean G_CH_dispatch_int(GSource* source, GSourceFunc callback, + gpointer user_data); +void G_CH_destroy_int(GSource* source); +GCHSource* +G_main_IPC_Channel_constructor(GSource* source, IPC_Channel* ch +, gpointer userdata, GDestroyNotify notify); diff --git a/include/clplumbing/Gmain_timeout.h b/include/clplumbing/Gmain_timeout.h new file mode 100644 index 0000000..c696a9d --- /dev/null +++ b/include/clplumbing/Gmain_timeout.h @@ -0,0 +1,44 @@ +#ifndef _CLPLUMBING_GMAIN_TIMEOUT_H +#define _CLPLUMBING_GMAIN_TIMEOUT_H +#include <glib.h> +/* + * Copyright (C) 2002 Alan Robertson <alanr@unix.sh> + * This software licensed under the GNU LGPL. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * These functions must work correctly even if someone resets the + * time-of-day clock. The g_main_timeout_add() function does not have + * this property, since it relies on gettimeofday(). + * + * Our functions have the same semantics - except they always work ;-) + * + * This is because we use longclock_t for our time values. + */ +guint Gmain_timeout_add(guint interval +, GSourceFunc function +, gpointer data); + +guint Gmain_timeout_add_full(gint priority +, guint interval +, GSourceFunc function +, gpointer data +, GDestroyNotify notify); + +void Gmain_timeout_remove(guint tag); +#endif diff --git a/include/clplumbing/Makefile.am b/include/clplumbing/Makefile.am new file mode 100644 index 0000000..599b24c --- /dev/null +++ b/include/clplumbing/Makefile.am @@ -0,0 +1,59 @@ +# +# linux-ha: Linux-HA heartbeat code +# +# Copyright (C) 2002 International Business Machines. +# Author: Alan Robertson <alanr@unix.sh> +# +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# +MAINTAINERCLEANFILES = Makefile.in + +idir=$(includedir)/clplumbing + +i_HEADERS = \ + Gmain_timeout.h \ + GSource.h \ + GSource_internal.h \ + apphb_cs.h \ + base64.h \ + cl_log.h \ + cl_poll.h \ + cl_signal.h \ + cl_pidfile.h \ + cl_random.h \ + cl_reboot.h \ + cl_syslog.h \ + cl_uuid.h \ + coredumps.h \ + cpulimits.h \ + ipc.h \ + lsb_exitcodes.h \ + loggingdaemon.h \ + longclock.h \ + mkstemp_mode.h \ + netstring.h \ + proctrack.h \ + realtime.h \ + replytrack.h \ + setproctitle.h \ + timers.h \ + uids.h \ + cl_misc.h \ + md5.h \ + cl_plugin.h \ + cl_tiebreaker.h \ + cl_quorum.h \ + cl_quorumd.h diff --git a/include/clplumbing/apphb_cs.h b/include/clplumbing/apphb_cs.h new file mode 100644 index 0000000..9506db6 --- /dev/null +++ b/include/clplumbing/apphb_cs.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2002 Alan Robertson <alanr@unix.sh> + * This software licensed under the GNU LGPL. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _CLPLUMBING_APPHB_CS_H +#define _CLPLUMBING_APPHB_CS_H + +/* Internal client-server messages for APP heartbeat service */ + +#ifndef HA_VARRUNDIR +#define HA_VARRUNDIR "/var/run" +#endif +#define APPHBSOCKPATH HA_VARRUNDIR "/heartbeat/apphb.comm" + +#define APPHB_TLEN 8 +#define APPHB_OLEN 256 + +#define REGISTER "reg" +#define UNREGISTER "unreg" +#define HEARTBEAT "hb" +#define SETINTERVAL "setint" +#define SETWARNTIME "setwarn" +#define SETREBOOT "setboot" + +/* + * These messages are really primitive. + * They don't have any form of version control, they're in host byte order, + * and they're all in binary... + * + * Fortunately, this is a very simple local service ;-) + */ + +/* Generic (no parameter) App heartbeat message */ +struct apphb_msg { + char msgtype [APPHB_TLEN]; +}; + +/* App heartbeat Registration message */ +struct apphb_signupmsg { + char msgtype [APPHB_TLEN]; + char appname [APPHB_OLEN]; + char appinstance [APPHB_OLEN]; + char curdir [APPHB_OLEN]; + pid_t pid; + uid_t uid; + gid_t gid; +}; + +/* App heartbeat setinterval / setwarn message */ +struct apphb_msmsg { + char msgtype [APPHB_TLEN]; + unsigned long ms; +}; + +/* App heartbeat server return code (errno) */ +struct apphb_rc { + int rc; +}; +#endif diff --git a/include/clplumbing/base64.h b/include/clplumbing/base64.h new file mode 100644 index 0000000..4ea6810 --- /dev/null +++ b/include/clplumbing/base64.h @@ -0,0 +1,50 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CLPLUMBING_BASE64_H +# define _CLPLUMBING_BASE64_H +/* + * + * Base64 conversion functions. + * They convert from a binary array into a single string + * in base 64. This is almost (but not quite) like section 5.2 of RFC 1341 + * The only difference is that we don't care about line lengths. + * We do use their encoding algorithm. + * + */ + +#define B64inunit 3 +#define B64outunit 4 + +/* How long will the base64 string be for a particular binary object size? */ +/* This is like strlen() and doesn't include the '\0' byte at the end */ +#define B64_stringlen(bytes) \ + ((((bytes)+(B64inunit-1))/B64inunit)*B64outunit) + +/* How many bytes to you need to malloc to store a base64 string? */ +/* (includes space for the '\0' terminator byte) */ +#define B64_stringspace(bytes) (B64_stringlen(bytes)+1) + +/* How many bytes will a base64 string take up back in binary? */ +/* Note: This may be as much as two 2 bytes more than strictly needed */ +#define B64_maxbytelen(slen) (((slen) / B64outunit)*B64inunit) + +/* Returns strlen() of base64 string returned in "output" */ +int binary_to_base64(const void * data, int nbytes, char * output, int outlen); + +/* Returns the size of the binary object we returned in "output" */ +int base64_to_binary(const char * input, int inlen, void * output, int outlen); +#endif diff --git a/include/clplumbing/cl_log.h b/include/clplumbing/cl_log.h new file mode 100644 index 0000000..aa30fcd --- /dev/null +++ b/include/clplumbing/cl_log.h @@ -0,0 +1,99 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CLPLUMBING_CL_LOG_H +# define _CLPLUMBING_CL_LOG_H +# include <glib.h> +# include <syslog.h> + +#define TIME_T unsigned long +#define HA_FAIL 0 +#define HA_OK 1 +#define MAXLINE (512*10) + +/* this is defined by the caller */ +struct logspam { + const char *id; /* identifier */ + int max; /* maximum number of messages ... */ + time_t window; /* ... within this timeframe */ + time_t reset_time; /* log new messages after this time */ + const char *advice; /* what to log in case messages get suppressed */ +}; + +/* this is internal (oblique to the caller) */ +struct msg_ctrl { + struct logspam *lspam; /* */ + time_t *msg_slots; /* msg slot root (space for lspam->max) */ + int last; /* last used msg slot [0..lspam->max-1]; -1 on init */ + int cnt; /* current msg count [0..lspam->max] */ + time_t suppress_t; /* messages blocked since this time */ +}; + +struct IPC_CHANNEL; + +extern int debug_level; +#define ANYDEBUG (debug_level) +#define DEBUGDETAILS (debug_level >= 2) +#define DEBUGAUTH (debug_level >=3) +#define DEBUGMODULE (debug_level >=3) +#define DEBUGPKT (debug_level >= 4) +#define DEBUGPKTCONT (debug_level >= 5) + +void cl_direct_log(int priority, const char* buf, gboolean, const char*, int, TIME_T); +void cl_log(int priority, const char * fmt, ...) G_GNUC_PRINTF(2,3); +void cl_limit_log(struct msg_ctrl *ml, int priority, const char * fmt, ...) G_GNUC_PRINTF(3,4); +struct msg_ctrl *cl_limit_log_new(struct logspam *lspam); +void cl_limit_log_destroy(struct msg_ctrl *ml); +void cl_limit_log_reset(struct msg_ctrl *ml); +void cl_perror(const char * fmt, ...) G_GNUC_PRINTF(1,2); +void cl_log_enable_stderr(int truefalse); +void cl_log_enable_stdout(int truefalse); +gboolean cl_log_test_logd(void); +void cl_log_set_uselogd(int truefalse); +void cl_log_enable_syslog_filefmt(int truefalse); +void cl_log_use_buffered_io(int truefalse); +gboolean cl_log_get_uselogd(void); +void cl_log_set_facility(int facility); +void cl_log_set_entity(const char * entity); +void cl_log_set_syslogprefix(const char *prefix); +void cl_log_set_logfile(const char * path); +void cl_log_set_debugfile(const char * path); +void cl_inherit_logging_environment(int maxqlen); +int cl_log_set_logd_channel_source( void (*create_callback)(struct IPC_CHANNEL* chan), + GDestroyNotify destroy_callback); +int cl_log_get_logdtime(void); +void cl_log_set_logdtime(int logdintval); + +char * ha_timestamp(TIME_T t); +void cl_glib_msg_handler(const gchar *log_domain +, GLogLevelFlags log_level, const gchar *message +, gpointer user_data); + +void cl_flush_logs(void); +void cl_log_args(int argc, char **argv); +int cl_log_is_logd_fd(int fd); +const char * prio2str(int priority); + +/* cl_log_use_buffered_io and cl_log_do_fflush as optimization for logd, + * so it may buffer a few message lines, then fflush them out in one write. + * Set do_fsync != 0, if you even want it to fsync. */ +void cl_log_do_fflush(int do_fsync); +void cl_log_use_buffered_io(int truefalse); +/* We now keep the file handles open for a potentially very long time. + * Sometimes we may need to close them explicitly. */ +void cl_log_close_log_files(void); + +#endif diff --git a/include/clplumbing/cl_misc.h b/include/clplumbing/cl_misc.h new file mode 100644 index 0000000..6f698b5 --- /dev/null +++ b/include/clplumbing/cl_misc.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005 Guochun Shi <gshi@ncsa.uiuc.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CLPLUMBING_CL_MISC_H +#define _CLPLUMBING_CL_MISC_H +int cl_str_to_boolean(const char*, int*); + +int cl_file_exists(const char* filename); + +char* cl_get_env(const char* env_name); + +int cl_binary_to_int(const char* data, int len); + +long cl_get_msec(const char * input); /* string to msec */ + +#endif diff --git a/include/clplumbing/cl_pidfile.h b/include/clplumbing/cl_pidfile.h new file mode 100644 index 0000000..3dba50f --- /dev/null +++ b/include/clplumbing/cl_pidfile.h @@ -0,0 +1,25 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _LOCKFILE_H_ +#define _LOCKFILE_H_ + +int cl_read_pidfile(const char *filename); +int cl_read_pidfile_no_checking(const char *filename); +int cl_lock_pidfile(const char *filename); +int cl_unlock_pidfile(const char *filename); + +#endif diff --git a/include/clplumbing/cl_plugin.h b/include/clplumbing/cl_plugin.h new file mode 100644 index 0000000..e2431bf --- /dev/null +++ b/include/clplumbing/cl_plugin.h @@ -0,0 +1,29 @@ + + +/* + * cl_manage_plugin.c: This file handle plugin loading and deleting + * + * Copyright (C) 2005 Guochun Shi <gshi@ncsa.uiuc.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __CL_PLUGIN__ +#define __CL_PLUGIN__ + +int cl_remove_plugin(const char* type, const char* pluginname); +void* cl_load_plugin(const char* type, const char* pluginname); + +#endif diff --git a/include/clplumbing/cl_poll.h b/include/clplumbing/cl_poll.h new file mode 100644 index 0000000..1b1908f --- /dev/null +++ b/include/clplumbing/cl_poll.h @@ -0,0 +1,46 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef CLPLUMBING_CL_POLL_H +# define CLPLUMBING_CL_POLL_H + +#include <glib.h> +#include <sys/poll.h> + +/* + * Poll the file descriptors described by the NFDS structures starting at + * FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + * an event to occur; if TIMEOUT is -1, block until an event occurs. + * Returns the number of file descriptors with events, zero if timed out, + * or -1 for errors. + * + * When available, this function uses POSIX signals, and Linux F_SETSIG() + * calls to provide this capability. When it is not available it + * uses the real poll() call. + * + */ +int cl_poll(struct pollfd *fds, unsigned int nfds, int timeout_ms); + +/* + * Call cl_poll_ignore() when you close a file descriptor you monitored + * via cl_poll() before, or if you don't want it monitored any more. + */ +int cl_poll_ignore(int fd); + +/* Select the signal you want us to use (must be a RT signal) */ +int cl_poll_setsig(int nsig); + +int cl_glibpoll(GPollFD* ufds, guint nfsd, gint timeout); +#endif diff --git a/include/clplumbing/cl_quorum.h b/include/clplumbing/cl_quorum.h new file mode 100644 index 0000000..b7798ba --- /dev/null +++ b/include/clplumbing/cl_quorum.h @@ -0,0 +1,44 @@ +/* + * quorum.h: head file for quorum module + * + * Copyright (C) 2005 Guochun Shi <gshi@ncsa.uiuc.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _QUORUM_H_ +#define _QUORUM_H_ + +#define HB_QUORUM_TYPE quorum +#define HB_QUORUM_TYPE_S "quorum" + +#define QUORUM_YES 0 +#define QUORUM_NO 1 +#define QUORUM_TIE 2 +typedef void(*callback_t)(void); +/* + * List of functions provided by implementations of the quorum interface. + */ +struct hb_quorum_fns { + + int (*getquorum) (const char* cluster + , int member_count, int member_quorum_votes + , int total_node_count, int total_quorum_votes); + int (*init) (callback_t notify, const char* cluster, const char* quorum_server); + void (*stop) (void); +}; + + +#endif diff --git a/include/clplumbing/cl_quorumd.h b/include/clplumbing/cl_quorumd.h new file mode 100644 index 0000000..6d282b3 --- /dev/null +++ b/include/clplumbing/cl_quorumd.h @@ -0,0 +1,48 @@ +/* + * quorum.h: head file for quorum module + * + * Author: Huang Zhen <zhenhltc@cn.ibm.com> + * Copyright (C) 2006 International Business Machines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _QUORUMD_H_ +#define _QUORUMD_H_ + +#define HB_QUORUMD_TYPE quorumd +#define HB_QUORUMD_TYPE_S "quorumd" + +#define CONFIGFILE HA_HBCONF_DIR"/quorumd.conf" +#define MAX_DN_LEN 256 +#define quorum_log(priority, fmt...); \ + cl_log(priority, fmt); \ + +#define quorum_debug(priority, fmt...); \ + if ( debug_level > 0 ) { \ + cl_log(priority, fmt); \ + } + +/* List of functions provided by implementations of the quorumd interface. */ +struct hb_quorumd_fns { + int (*test) (void); + int (*init) (void); + int (*load_config_file) (void); + int (*dump_data) (int priority); + int (*on_connect) (int sock, gnutls_session session, const char* CN); +}; + + +#endif diff --git a/include/clplumbing/cl_random.h b/include/clplumbing/cl_random.h new file mode 100644 index 0000000..d1e37ce --- /dev/null +++ b/include/clplumbing/cl_random.h @@ -0,0 +1,81 @@ + +/* + * Copyright (C) 2005 Guochun Shi <gshi@ncsa.uiuc.edu> + * Copyright (C) 2005 International Business Machines Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdlib.h> + +/* Intended usage is srand(cl_randseed()). + * This returns on "as good as it gets" random number usually taken from + * /dev/urandom to have a nice seed for future random numbers generated by + * rand(). */ +unsigned int cl_randseed(void); + +/* get_next_random() currently rand() based. + * + * You probably want to use cl_rand_from_interval instead. + * + * You don't need to srand(), it will seed once with cl_randseed internally. + * + * It is called that way, because it was exposed in the header file for a long + * time, and used to be coded in an attempt to pregenerate a queue of random + * numbers from the mainloop, and it would shift the next random number from + * that queue and trigger generation of new random numbers "at idle time" to + * refill that queue. + * Only that functionality never actually worked, is not interessting anymore + * anyways (rand() is cheap enough), and is now ripped out. + * + * So it now does srand(cl_randseed()) once internally, + * and from there on is equivalent to calling rand() directly, + * and could be called cl_rand(). + * + * If you want your own specific rand seed to re-generate a particular + * sequence, call it once, throw away the return code, then call + * srand(yourseed). Or don't use it anywhere in your code. */ +int get_next_random(void); + +/* generate some random number in the range [a;b]; + * typically used to randomly delay messages. */ +#define HAVE_CL_RAND_FROM_INTERVAL 1 +static inline +int cl_rand_from_interval(const int a, const int b) +{ + /* + * Be careful here, you don't know RAND_MAX at coding time, + * only at compile time. If you think + * (int)(a + (rand()*(b-a)+(RAND_MAX/2))/RAND_MAX); + * was correct, think again with RAND_MAX = INT_MAX, + * which is the case for many rand() implementations nowadays. + * + * Don't do modulo, either, as that will skew the distribution, and + * still has possible wraparounds, or an insufficient input set for too + * small RAND_MAX. + * + * Rather do the whole calculation in 64 bit, which should be correct + * as long as r, a, b, and RAND_MAX are all int. + * Of course, if you prefer, you can do it with floating point as well. + */ +#if 1 /* use long long */ + long long r = get_next_random(); + r = a + (r * (b-a) + RAND_MAX/2)/RAND_MAX; +#else /* use floating point */ + int r = get_next_random(); + r = a + (int)(1.0 / RAND_MAX * r * (b-a) + 0.5); +#endif + return r; +} diff --git a/include/clplumbing/cl_reboot.h b/include/clplumbing/cl_reboot.h new file mode 100644 index 0000000..1c759c8 --- /dev/null +++ b/include/clplumbing/cl_reboot.h @@ -0,0 +1,6 @@ +#ifndef CLPLUMBING_CL_REBOOT_H +#define CLPLUMBING_CL_REBOOT_H 1 +#include <glib.h> +void cl_enable_coredump_before_reboot(gboolean yesno); /* not implemented in all OSes */ +void cl_reboot(int msdelaybeforereboot, const char * reason); +#endif diff --git a/include/clplumbing/cl_signal.h b/include/clplumbing/cl_signal.h new file mode 100644 index 0000000..1a13a6b --- /dev/null +++ b/include/clplumbing/cl_signal.h @@ -0,0 +1,91 @@ +/* + * cl_signal.h: signal handling routines to be used by Linux-HA programmes + * + * Copyright (C) 2002 Horms <horms@verge.net.au> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _CL_SIGNAL_H +#define _CL_SIGNAL_H + +#include <stdio.h> +#include <signal.h> +#include <sys/signal.h> + +typedef struct { + int sig; + void (*handler)(int); + int interrupt; +} cl_signal_mode_t; + +#define CL_SIGNAL(_sig, _handler) \ + cl_signal_set_simple_handler((_sig), (_handler), NULL) +#if HAVE_SIGIGNORE +#define CL_IGNORE_SIG(_sig) sigignore((_sig)) +#else +#define CL_IGNORE_SIG(_sig) CL_SIGNAL((_sig), SIG_IGN) +#endif +#define CL_DEFAULT_SIG(_sig) CL_SIGNAL((_sig), SIG_DFL) + +#define CL_SIGINTERRUPT(_sig, _flag) siginterrupt((_sig), (_flag)) + +#define CL_SIGACTION(_signum, _act, _oldact) \ + sigaction((_signum), (_act), (_oldact)) +#define CL_SIGPROCMASK(_how, _set, _oldset) \ + cl_signal_block_set((_how), (_set), (_oldset)) +#define CL_SIGPENDING(_set) sigpending(_set) +#define CL_SIGSUSPEND(_mask) sigsuspend(_mask) + +#define CL_SIGEMPTYSET(_set) sigemptyset(_set) +#define CL_SIGFILLSET(_set) sigfillset(_set) +#define CL_SIGADDSET(_set, _signum) sigaddset((_set), (_signum)) +#define CL_SIGDELSET(_set, _signum) sigdelset((_set), (_signum)) +#define CL_SIGISMEMBER(_set, _signum) sigmember((_set), (_signum)) + +#define CL_KILL(_pid, _sig) kill((_pid), (_sig)) + +#define CL_PID_EXISTS(_pid) ( CL_KILL((_pid), 0) >= 0 || errno != ESRCH ) + +int +cl_signal_set_handler(int sig, void (*handler)(int), sigset_t *mask +, int flags, struct sigaction *oldact); + +int +cl_signal_set_simple_handler(int sig, void (*handler)(int) +, struct sigaction *oldact); + +int +cl_signal_set_action(int sig, void (*action)(int, siginfo_t *, void *) +, sigset_t *mask, int flags, struct sigaction *oldact); + +int +cl_signal_set_simple_action(int sig, void (*action)(int, siginfo_t *, void *) +, struct sigaction *oldact); + +int +cl_signal_set_interrupt(int sig, int flag); + +int +cl_signal_block(int how, int signal, sigset_t *oldset); + +int +cl_signal_block_set(int how, const sigset_t *set, sigset_t *oldset); + +int +cl_signal_set_handler_mode(const cl_signal_mode_t *mode, sigset_t *set); + + +#endif /* _CL_SIGNAL_H */ diff --git a/include/clplumbing/cl_syslog.h b/include/clplumbing/cl_syslog.h new file mode 100644 index 0000000..a7c1bfa --- /dev/null +++ b/include/clplumbing/cl_syslog.h @@ -0,0 +1,32 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Functions to support syslog. + * David Lee (c) 2005 + */ + +#ifndef _CLPLUMBING_CL_SYSLOG_H +#define _CLPLUMBING_CL_SYSLOG_H + +/* Convert string "auth" to equivalent number "LOG_AUTH" etc. */ +int cl_syslogfac_str2int(const char *); + +/* Convert number "LOG_AUTH" to equivalent string "auth" etc. */ +/* Returns static string; caller must NOT free. */ +const char *cl_syslogfac_int2str(int); + +#endif /* _CLPLUMBING_CL_SYSLOG_H */ diff --git a/include/clplumbing/cl_tiebreaker.h b/include/clplumbing/cl_tiebreaker.h new file mode 100644 index 0000000..11c10c4 --- /dev/null +++ b/include/clplumbing/cl_tiebreaker.h @@ -0,0 +1,35 @@ +/* + * cl_tiebreaker.h: head file for tiebreaker module + * + * Copyright (C) 2005 Guochun Shi <gshi@ncsa.uiuc.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CL_TIEBREAKER_H_ +#define _CL_TIEBREAKER_H_ + +#define HB_TIEBREAKER_TYPE tiebreaker +#define HB_TIEBREAKER_TYPE_S "tiebreaker" + +/* + * List of functions provided by implementations of tiebreaker interface. + */ +struct hb_tiebreaker_fns { + gboolean (*break_tie) (int, int); +}; + + +#endif diff --git a/include/clplumbing/cl_uuid.h b/include/clplumbing/cl_uuid.h new file mode 100644 index 0000000..12542cd --- /dev/null +++ b/include/clplumbing/cl_uuid.h @@ -0,0 +1,40 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CL_UUID_H_ +#define _CL_UUID_H_ +#include <glib.h> + +typedef struct cl_uuid_s{ + unsigned char uuid[16]; +}cl_uuid_t; + +void cl_uuid_copy(cl_uuid_t* dst, cl_uuid_t* src); +void cl_uuid_clear(cl_uuid_t* uu); +int cl_uuid_compare(const cl_uuid_t* uu1, const cl_uuid_t* uu2); +void cl_uuid_generate(cl_uuid_t* out); +int cl_uuid_is_null(cl_uuid_t* uu); +int cl_uuid_parse( char *in, cl_uuid_t* uu); +#define UU_UNPARSE_SIZEOF 37 /* Including NULL byte */ +void cl_uuid_unparse(const cl_uuid_t* uu, char *out); + +/* Suitable for ues as a GHashFunc from glib */ +guint cl_uuid_g_hash(gconstpointer uuid_ptr); +/* Suitable for ues as a GEqualFunc from glib */ +gboolean cl_uuid_g_equal(gconstpointer uuid_ptr_a, gconstpointer uuid_ptr_b); + + +#endif diff --git a/include/clplumbing/coredumps.h b/include/clplumbing/coredumps.h new file mode 100644 index 0000000..4d5ce79 --- /dev/null +++ b/include/clplumbing/coredumps.h @@ -0,0 +1,36 @@ +/* + * Basic Core dump control functions. + * + * Copyright (C) 2004 IBM Corporation + * + * This software licensed under the GNU LGPL. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _CLPLUMBING_COREFILES_H +# define _CLPLUMBING_COREFILES_H 1 + /* Set the root directory of our core directory hierarchy */ +int cl_set_corerootdir(const char * dir); + /* Change directory to the directory our core file needs to go in */ + /* Call after you establish the userid you're running under */ +int cl_cdtocoredir(void); + /* Enable/disable core dumps for ourselves and our child processes */ +int cl_enable_coredumps(int truefalse); +void cl_untaint_coredumps(void); +void cl_set_coredump_signal_handler(int nsig); +void cl_set_all_coredump_signal_handlers(void); + +#endif diff --git a/include/clplumbing/cpulimits.h b/include/clplumbing/cpulimits.h new file mode 100644 index 0000000..f7dd875 --- /dev/null +++ b/include/clplumbing/cpulimits.h @@ -0,0 +1,66 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Functions to put limits on CPU consumption. + * This allows us to better catch runaway realtime processes that + * might otherwise hang the whole system. + * + * The process is basically this: + * - Set the CPU percentage limit with cl_cpu_limit_setpercent() + * according to what you expect the CPU percentage to top out at + * measured over an interval at >= 10 seconds + * - Call cl_cpu_limit_ms_interval() to figure out how often to update + * the CPU limit (it returns milliseconds) + * - At least as often as indicated above, call cl_cpu_limit_update() + * to update our current CPU limit. + * + * These limits are approximate, so be a little conservative. + * If you've gone into an infinite loop, it'll likely get caught ;-) + * + * Note that exceeding the soft CPU limits we set here will cause a + * SIGXCPU signal to be sent. + * + * The default action for this signal is to cause a core dump. + * This is a good choice ;-) + * + * As of this writing, this code will never set the soft CPU limit less + * than two seconds, or greater than 10 seconds. + * + * It will currrently return a limit update interval between 10000 and + * 400000 milliseconds. + * + */ + +/* + * Set expected CPU percentage upper bound + */ +int cl_cpu_limit_setpercent(int ipercent); + +/* + * Update the current CPU limit + */ +int cl_cpu_limit_update(void); + +/* + * How often should we call cl_cpu_limit_update()? + * + * Note: return result is in milliseconds + */ +int cl_cpu_limit_ms_interval(void); + +/* Disable further CPU limits... */ +int cl_cpu_limit_disable(void); diff --git a/include/clplumbing/ipc.h b/include/clplumbing/ipc.h new file mode 100644 index 0000000..4a5e151 --- /dev/null +++ b/include/clplumbing/ipc.h @@ -0,0 +1,788 @@ +/* + * ipc.h IPC abstraction data structures. + * + * author Xiaoxiang Liu <xiliu@ncsa.uiuc.edu>, + * Alan Robertson <alanr@unix.sh> + * + * + * Copyright (c) 2002 International Business Machines + * Copyright (c) 2002 Xiaoxiang Liu <xiliu@ncsa.uiuc.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _IPC_H_ +#define _IPC_H_ +#include <glib.h> +#undef MIN +#undef MAX +#include <sys/types.h> +#include <sys/poll.h> + +#ifdef IPC_TIME_DEBUG +#include <clplumbing/longclock.h> +#define MAXIPCTIME 3000 + +#endif + +/* constants */ +#define DEFAULT_MAX_QLEN 64 +#define MAX_MSGPAD 128 +/* channel and connection status */ +#define IPC_CONNECT 1 /* Connected: can read, write */ +#define IPC_WAIT 2 /* Waiting for connection */ +#define IPC_DISCONNECT 3 /* Disconnected, can't read or write*/ +#define IPC_DISC_PENDING 4 /* Disconnected, can't write but */ + /* may be more data to read */ + +#define MAXFAILREASON 128 + +#define IPC_SERVER 1 +#define IPC_CLIENT 2 +#define IPC_PEER 3 + +#define IPC_ISRCONN(ch) ((ch)->ch_status == IPC_CONNECT \ + || (ch)->ch_status == IPC_DISC_PENDING) + +#define IPC_ISWCONN(ch) ((ch)->ch_status == IPC_CONNECT) + +/* general return values */ +#define IPC_OK 0 +#define IPC_FAIL 1 +#define IPC_BROKEN 2 +#define IPC_INTR 3 +#define IPC_TIMEOUT 4 + +/* + * IPC: Sockets-like Interprocess Communication Abstraction + * + * We have two fundamental abstractions which we maintain. + * Everything else is in support of these two abstractions. + * + * These two main abstractions are: + * + * IPC_WaitConnection: + * A server-side abstraction for waiting for someone to connect. + * + * IPC_Channel: + * An abstraction for an active communications channel. + * + * All the operations on these two abstractions are carried out + * via function tables (channel->ops). Below we refer to the + * function pointers in these tables as member functions. + * + * On the server side, everything starts up with a call to + * ipc_wait_conn_constructor(), which returns an IPC_WaitConnection. + * + * Once the server has the IPC_WaitConnection object in hand, + * it can give the result of the get_select_fd() member function + * to poll or select to inform you when someone tries to connect. + * + * Once select tells you someone is trying to connect, you then + * use the accept_connection() member function to accept + * the connection. accept_connection() returns an IPC_Channel. + * + * With that, the server can talk to the client, and away they + * go ;-) + * + * On the client side, everything starts up with a call to + * ipc_channel_constructor() which we use to talk to the server. + * The client is much easier ;-) + */ + + +typedef struct IPC_WAIT_CONNECTION IPC_WaitConnection; +typedef struct IPC_CHANNEL IPC_Channel; + +typedef struct IPC_MESSAGE IPC_Message; +typedef struct IPC_QUEUE IPC_Queue; +typedef struct IPC_AUTH IPC_Auth; + +typedef struct IPC_OPS IPC_Ops; +typedef struct IPC_WAIT_OPS IPC_WaitOps; + + + +/* wait connection structure. */ +struct IPC_WAIT_CONNECTION{ + int ch_status; /* wait conn. status.*/ + void * ch_private; /* wait conn. private data. */ + IPC_WaitOps *ops; /* wait conn. function table .*/ +}; + + +typedef void(*flow_callback_t)(IPC_Channel*, void*); + +/* channel structure.*/ +struct IPC_CHANNEL{ + int ch_status; /* identify the status of channel.*/ + int refcount; /* reference count */ + pid_t farside_pid; /* far side pid */ + void* ch_private; /* channel private data. */ + /* (may contain conn. info.) */ + IPC_Ops* ops; /* IPC_Channel function table.*/ + + /* number of bytes needed + * at the begginging of <ipcmessage>->msg_body + * it's for msg head needed to tranmit in wire + */ + unsigned int msgpad; + + /* the number of bytes remainng to send for the first message in send queue + 0 means nothing has been sent thus all bytes needs to be send + n != 0 means there are still n bytes needs to be sent + */ + unsigned int bytes_remaining; + + + /* is the send blocking or nonblocking*/ + gboolean should_send_block; + + /* if send would block, should an error be returned or not */ + gboolean should_block_fail; + +/* There are two queues in channel. One is for sending and the other + * is for receiving. + * Those two queues are channel's internal queues. They should not be + * accessed directly. + */ + /* private: */ + IPC_Queue* send_queue; + IPC_Queue* recv_queue; + + /* buffer pool for receive in this channel*/ + struct ipc_bufpool* pool; + + /* the follwing is for send flow control*/ + int high_flow_mark; + int low_flow_mark; + void* high_flow_userdata; + void* low_flow_userdata; + flow_callback_t high_flow_callback; + flow_callback_t low_flow_callback; + + int conntype; + + char failreason[MAXFAILREASON]; + + /* New members to support Multi-level ACLs for the CIB, + * available since libplumb.so.2.1.0, added at the + * end of the struct to maintain backwards ABI compatibility. + * + * If you don't like to care for library versions, + * create your IPC channels with + * c = ipc_wait_conn_constructor(IPC_UDS_CRED, ...), + * and these members will be available. + */ + uid_t farside_uid; /* far side uid */ + gid_t farside_gid; /* far side gid */ +}; + +struct IPC_QUEUE{ + size_t current_qlen; /* Current qlen */ + size_t max_qlen; /* Max allowed qlen */ + GList* queue; /* List of messages */ + /* keep the time of the last max queue warning */ + time_t last_maxqlen_warn; + /* and the number of messages lost */ + unsigned maxqlen_cnt; +}; + +/* authentication information : set of gids and uids */ +struct IPC_AUTH { + GHashTable * uid; /* hash table for user id */ + GHashTable * gid; /* hash table for group id */ +}; + + +/* Message structure. */ +struct IPC_MESSAGE{ + size_t msg_len; + void* msg_buf; + void* msg_body; +/* + * IPC_MESSAGE::msg_done + * the callback function pointer which can be called after this + * message is sent, received or otherwise processed. + * + * Parameter: + * msg: the back pointer to the message which contains this + * function pointer. + * + */ + void (* msg_done)(IPC_Message * msg); + void* msg_private; /* the message private data. */ + /* Belongs to message creator */ + /* May be used by callback function. */ + IPC_Channel * msg_ch; /* Channel the */ + /* message is from/in */ + +}; + +struct IPC_WAIT_OPS{ +/* + * IPC_WAIT_OPS::destroy + * destroy the wait connection and free the memory space used by + * this wait connection. + * + * Parameters: + * wait_conn (IN): the pointer to the wait connection. + * + */ + void (* destroy)(IPC_WaitConnection *wait_conn); +/* + * IPC_WAIT_OPS::get_select_fd + * provide a fd which user can listen on for a new coming connection. + * + * Parameters: + * wait_conn (IN) : the pointer to the wait connection which + * we're supposed to return the file descriptor for + * (the file descriptor can be used with poll too ;-)) + * + * Return values: + * integer >= 0 : the select_fd. + * -1 : can't get the select fd. + * + */ + int (* get_select_fd)(IPC_WaitConnection *wait_conn); +/* + * IPC_WAIT_OPS::accept_connection + * accept and create a new connection and verify the authentication. + * + * Parameters: + * wait_conn (IN) : the waiting connection which will accept + * create the new connection. + * auth_info (IN) : the authentication information which will be + * verified for the new connection. + * + * Return values: + * the pointer to the new IPC channel; NULL if the creation or + * authentication fails. + * + */ + IPC_Channel * (* accept_connection) + (IPC_WaitConnection * wait_conn, IPC_Auth *auth_info); +}; + +/* Standard IPC channel operations */ + +struct IPC_OPS{ +/* + * IPC_OPS::destroy + * brief destroy the channel object. + * + * Parameters: + * ch (IN) : the pointer to the channel which will be destroyed. + * + */ + void (*destroy) (IPC_Channel * ch); +/* + * IPC_OPS::initiate_connection + * used by service user side to set up a connection. + * + * Parameters: + * ch (IN) : the pointer to channel used to initiate the connection. + * + * Return values: + * IPC_OK : the channel set up the connection successfully. + * IPC_FAIL : the connection initiation fails. + * + */ + int (* initiate_connection) (IPC_Channel * ch); +/* + * IPC_OPS::verify_auth + * used by either side to verify the identity of peer on connection. + * + * Parameters + * ch (IN) : the pointer to the channel. + * + * Return values: + * IPC_OK : the peer is trust. + * IPC_FAIL : verifying authentication fails. + */ + int (* verify_auth) (IPC_Channel * ch, IPC_Auth* info); +/* + * IPC_OPS::assert_auth + * service user asserts to be certain qualified service user. + * + * Parameters: + * ch (IN): the active channel. + * auth (IN): the hash table which contains the asserting information. + * + * Return values: + * IPC_OK : assert the authentication successfully. + * IPC_FAIL : assertion fails. + * + * NOTE: This operation is a bit obscure. It isn't needed with + * UNIX domain sockets at all. The intent is that some kinds + * of IPC (like FIFOs), do not have an intrinsic method to + * authenticate themselves except through file permissions. + * The idea is that you must tell it how to chown/grp your + * FIFO so that the other side and see that if you can write + * this, you can ONLY be the user/group they expect you to be. + * But, I think the parameters may be wrong for this ;-) + */ + int (* assert_auth) (IPC_Channel * ch, GHashTable * auth); +/* + * IPC_OPS::send + * send the message through the sending connection. + * + * Parameters: + * ch (IN) : the channel which contains the connection. + * msg (IN) : pointer to the sending message. User must + * allocate the message space. + * + * Return values: + * IPC_OK : the message was either sent out successfully or + * appended to the send_queue. + * IPC_FAIL : the send operation failed. + * IPC_BROKEN : the channel is broken. + * +*/ + int (* send) (IPC_Channel * ch, IPC_Message* msg); + +/* + * IPC_OPS::recv + * receive the message through receving queue. + * + * Parameters: + * ch (IN) : the channel which contains the connection. + * msg (OUT): the IPC_MESSAGE** pointer which contains the pointer + * to the received message or NULL if there is no + * message available. + * + * Return values: + * IPC_OK : receive operation is completed successfully. + * IPC_FAIL : operation failed. + * IPC_BROKEN : the channel is broken (disconnected) + * + * Note: + * return value IPC_OK doesn't mean the message is already + * sent out to (or received by) the peer. It may be pending + * in the send_queue. In order to make sure the message is no + * longer needed, please specify the msg_done function in the + * message structure and once this function is called, the + * message is no longer needed. + * + * is_sending_blocked() is another way to check if there is a message + * pending in the send_queue. + * + */ + int (* recv) (IPC_Channel * ch, IPC_Message** msg); + +/* + * IPC_OPS::waitin + * Wait for input to become available + * + * Parameters: + * ch (IN) : the channel which contains the connection. + * + * Side effects: + * If output becomes unblocked while waiting, it will automatically + * be resumed without comment. + * + * Return values: + * IPC_OK : a message is pending or output has become unblocked. + * IPC_FAIL : operation failed. + * IPC_BROKEN : the channel is broken (disconnected) + * IPC_INTR : waiting was interrupted by a signal + */ + int (* waitin) (IPC_Channel * ch); +/* + * IPC_OPS::waitout + * Wait for output to finish + * + * Parameters: + * ch (IN) : the channel which contains the connection. + * + * Side effects: + * If input becomes available while waiting, it will automatically + * be read into the channel queue without comment. + * + * Return values: + * IPC_OK : output no longer blocked + * IPC_FAIL : operation failed. + * IPC_BROKEN : the channel is broken (disconnected) + * IPC_INTR : waiting was interrupted by a signal + */ + int (* waitout) (IPC_Channel * ch); + +/* + * IPC_OPS::is_message_pending + * check to see if there is any messages ready to read, or hangup has + * occurred. + * + * Parameters: + * ch (IN) : the pointer to the channel. + * + * Return values: + * TRUE : there are messages ready to read, or hangup. + * FALSE: there are no messages ready to be read. + */ + gboolean (* is_message_pending) (IPC_Channel * ch); + +/* + * IPC_OPS::is_sending_blocked + * check the send_queue to see if there are any messages blocked. + * + * Parameters: + * ch (IN) : the pointer to the channel. + * + * Return values: + * TRUE : there are messages blocked (waiting) in the send_queue. + * FALSE: there are no message blocked (waiting) in the send_queue. + * + * See also: + * get_send_select_fd() + */ + gboolean (* is_sending_blocked) (IPC_Channel *ch); + +/* + * IPC_OPS::resume_io + * Resume all possible IO operations through the IPC transport + * + * Parameters: + * the pointer to the channel. + * + * Return values: + * IPC_OK : resume all the possible I/O operation successfully. + * IPC_FAIL : the operation fails. + * IPC_BROKEN : the channel is broken. + * + */ + int (* resume_io) (IPC_Channel *ch); +/* + * IPC_OPS::get_send_select_fd() + * return a file descriptor which can be given to select/poll. This fd + * is used by the IPC code for sending. It is intended that this be + * ONLY used with select, poll, or similar mechanisms, not for direct I/O. + * Note that due to select(2) and poll(2) semantics, you must check + * is_sending_blocked() to see whether you should include this FD in + * your poll for writability, or you will loop very fast in your + * select/poll loop ;-) + * + * Parameters: + * ch (IN) : the pointer to the channel. + * + * Return values: + * integer >= 0 : the send fd for selection. + * -1 : there is no send fd. + * + * See also: + * is_sending_blocked() + */ + int (* get_send_select_fd) (IPC_Channel * ch); +/* + * IPC_OPS::get_recv_select_fd + * return a file descriptor which can be given to select. This fd + * is for receiving. It is intended that this be ONLY used with select, + * poll, or similar mechanisms, NOT for direct I/O. + * + * Parameters: + * ch (IN) : the pointer to the channel. + * + * Return values: + * integer >= 0 : the recv fd for selection. + * -1 : there is no recv fd. + * + * NOTE: This file descriptor is often the same as the send + * file descriptor. + */ + int (* get_recv_select_fd) (IPC_Channel * ch); +/* + * IPC_OPS::set_send_qlen + * allow user to set the maximum send_queue length. + * + * Parameters + * ch (IN) : the pointer to the channel. + * q_len (IN) : the max length for the send_queue. + * + * Return values: + * IPC_OK : set the send queue length successfully. + * IPC_FAIL : there is no send queue. (This isn't supposed + * to happen). + * It means something bad happened. + * + */ + int (* set_send_qlen) (IPC_Channel * ch, int q_len); +/* + * IPC_OPS::set_recv_qlen + * allow user to set the maximum recv_queue length. + * + * Parameters: + * ch (IN) : the pointer to the channel. + * q_len (IN) : the max length for the recv_queue. + * + * Return values: + * IPC_OK : set the recv queue length successfully. + * IPC_FAIL : there is no recv queue. + * + */ + int (* set_recv_qlen) (IPC_Channel * ch, int q_len); + + +/* + * IPC_OPS: set callback for high/low flow mark + * ch (IN) : the pointer to the channel + * callback (IN) : the callback function + * user_data(IN) : a pointer to user_data + * callback will be called with channel and + * this user_data as parameters + * + * Return values: + * void + * + */ + + + void (* set_high_flow_callback) (IPC_Channel* ch , + flow_callback_t callback, + void* user_data); + + void (* set_low_flow_callback) (IPC_Channel* ch , + flow_callback_t callback, + void* user_data); + +/* + * IPC_OPS::new_ipcmsg + * ch (IN) : the pointer to the channel + * data (IN) : data to be copied to the message body + * len (IN) : data len + * private (IN): the pointer value to set as in the message + * + * Return values: + * the pointer to a new created message will be + * returned if success or NULL if failure + * + */ + + IPC_Message* (*new_ipcmsg)(IPC_Channel* ch, const void* data, + int len, void* private); + + +/* + * IPC_OPS::nget_chan_status + * ch (IN) : the pointer to the channel + * + * Return value: + * channel status. + * + */ + int (*get_chan_status)(IPC_Channel* ch); + + +/* + * These two functions returns true if the corresponding queue + * is full, otherwise it returns false + */ + + gboolean (*is_sendq_full)(struct IPC_CHANNEL * ch); + gboolean (*is_recvq_full)(struct IPC_CHANNEL * ch); + + + /* Get the connection type for the channel + * it can be IPC_SERVER, IPC_CLIENT, IPC_PEER + */ + + int (*get_conntype)(struct IPC_CHANNEL* ch); + + int (*disconnect)(struct IPC_CHANNEL* ch); + +}; + + +/* + * ipc_wait_conn_constructor: + * the common constructor for ipc waiting connection. + * Use ch_type to identify the connection type. Usually it's only + * needed by server side. + * + * Parameters: + * ch_type (IN) : the type of the waiting connection to create. + * ch_attrs (IN) : the hash table which contains the attributes + * needed by this waiting connection in name/value + * pair format. + * + * For example, the only attribute needed by UNIX + * domain sockets is path name. + * + * Return values: + * the pointer to a new waiting connection or NULL if the connection + * can't be created. + * Note: + * current implementation supports + * IPC_ANYTYPE: This is what program code should typically use. + * Internally it is an alias to IPC_UDS_CRED. + * IPC_UDS_CRED: Unix Domain Sockets, + * farside uid + gid credentials is available. + * Available since libplumb.so.2.1.0. + * IPC_DOMAIN_SOCKET: An other alias to Unix Domain Sockets; + * internally it is equivalent to both above. + * Using this explicitly, your code will work + * even with libplumb.so.2.0.0. + * Which also means that you MUST NOT use the + * farside_uid/gid functionality then. + */ +extern IPC_WaitConnection * ipc_wait_conn_constructor(const char * ch_type +, GHashTable* ch_attrs); + +/* + * ipc_channel_constructor: + * brief the common constructor for ipc channel. + * Use ch_type to identify the channel type. + * Usually this function is only called by client side. + * + * Parameters: + * ch_type (IN): the type of the channel you want to create. + * ch_attrs (IN): the hash table which contains the attributes needed + * by this channel. + * For example, the only attribute needed by UNIX domain + * socket is path name. + * + * Return values: + * the pointer to the new channel whose status is IPC_DISCONNECT + * or NULL if the channel can't be created. + * + * Note: + * See comments for ipc_wait_conn_constructor above + * for currently implemented ch_type channel types. + */ +extern IPC_Channel * ipc_channel_constructor(const char * ch_type +, GHashTable* ch_attrs); + +/* + * ipc_channel_pair: + * Construct a pair of connected IPC channels in a fashion analogous + * to pipe(2) or socketpair(2). + * + * Parameters: + * channels: an array of two IPC_Channel pointers for return result + */ +int ipc_channel_pair(IPC_Channel* channels[2]); + +/* + * ipc_set_auth: + * A helper function used to convert array of uid and gid into + * an authentication structure (IPC_Auth) + * + * Parameters: + * a_uid (IN): the array of a set of user ids. + * a_gid (IN): the array of a set of group ids. + * num_uid (IN): the number of user ids. + * num_gid (IN): the number of group ids. + * + * Return values: + * the pointer to the authentication structure which contains the + * set of uid and the set of gid. Or NULL if this structure can't + * be created. + * + */ + + +IPC_Auth* ipc_str_to_auth(const char * uidlist, int, const char * gidlist, int); + +extern IPC_Auth * ipc_set_auth(uid_t * a_uid, gid_t * a_gid +, int num_uid, int num_gid); + +/* Destroys an object constructed by ipc_set_auth or ipc_str_to_auth() */ +extern void ipc_destroy_auth(IPC_Auth * auth); + +extern void ipc_set_pollfunc(int (*)(struct pollfd*, unsigned int, int)); +extern void ipc_bufpool_dump_stats(void); + +#ifdef IPC_TIME_DEBUG + +enum MSGPOS_IN_IPC{ + MSGPOS_ENQUEUE, + MSGPOS_SEND, + MSGPOS_RECV, + MSGPOS_DEQUEUE +}; + +#endif + + +struct SOCKET_MSG_HEAD{ + int msg_len; + unsigned int magic; +#ifdef IPC_TIME_DEBUG + longclock_t enqueue_time; + longclock_t send_time; + longclock_t recv_time; + longclock_t dequeue_time; +#endif + +}; + + +/* MAXMSG is the maximum final message size on the wire. */ +#define MAXMSG (256*1024) +/* MAXUNCOMPRESSED is the maximum, raw data size prior to compression. */ +/* 1:8 compression ratio is to be expected on data such as xml */ +#define MAXUNCOMPRESSED (2048*1024) +#define HEADMAGIC 0xabcd +#define POOL_SIZE (4*1024) +struct ipc_bufpool{ + + int refcount; + char* currpos; + char* consumepos; + char* startpos; + char* endpos; + int size; +}; + +struct ipc_bufpool* ipc_bufpool_new(int); + +void ipc_bufpool_del(struct ipc_bufpool* pool); + +int ipc_bufpool_spaceleft(struct ipc_bufpool* pool); + +int ipc_bufpool_update(struct ipc_bufpool* pool, + struct IPC_CHANNEL * ch, + int msg_len, + IPC_Queue* rqueue); + +gboolean ipc_bufpool_full(struct ipc_bufpool* pool, + struct IPC_CHANNEL* ch, + int*); +int ipc_bufpool_partial_copy(struct ipc_bufpool* dstpool, + struct ipc_bufpool* srcpool); + +void ipc_bufpool_ref(struct ipc_bufpool* pool); + +void ipc_bufpool_unref(struct ipc_bufpool* pool); + +void set_ipc_time_debug_flag(gboolean flag); + +/* pathname attribute */ +#define IPC_PATH_ATTR "path" +/* socket mode attribute */ +#define IPC_MODE_ATTR "sockmode" +/* Unix domain socket, used by old code. + * See also the comment block above ipc_wait_conn_constructor() */ +#define IPC_DOMAIN_SOCKET "uds" +/* Unix domain socket with farside uid + gid credentials. + * Available since libplumb.so.2.1.0 */ +#define IPC_UDS_CRED "uds_c" + +#ifdef IPC_UDS_CRED +# define IPC_ANYTYPE IPC_UDS_CRED +#else +# error "No IPC types defined(!)" +#endif + +#endif diff --git a/include/clplumbing/loggingdaemon.h b/include/clplumbing/loggingdaemon.h new file mode 100644 index 0000000..ba986f5 --- /dev/null +++ b/include/clplumbing/loggingdaemon.h @@ -0,0 +1,32 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Messages sent to the logging daemon */ +#define LD_LOGIT 2 +#define MAXENTITY 64 + +/* Message contains following header, followed by the text (char[]) itself */ +struct LogDaemonMsgHdr_s { + int msgtype; + int facility; + int priority; + int msglen; + gboolean use_pri_str; + int entity_pid; + char entity[MAXENTITY]; + TIME_T timestamp; +}; +typedef struct LogDaemonMsgHdr_s LogDaemonMsgHdr; diff --git a/include/clplumbing/longclock.h b/include/clplumbing/longclock.h new file mode 100644 index 0000000..ae95b28 --- /dev/null +++ b/include/clplumbing/longclock.h @@ -0,0 +1,143 @@ +/* + * Longclock operations + * + * Copyright (c) 2002 International Business Machines + * Author: Alan Robertson <alanr@unix.sh> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _LONGCLOCK_H +# define _LONGCLOCK_H +/* + * A longclock_t object is a lot like a clock_t object, except that it + * won't wrap in the lifetime of the earth. It is guaranteed to be at + * least 64 bits. This means it should go for around 2 billion years. + * + * It is also supposed to be proof against changes in the local time on + * the computer. This is easy if you have a properly-working times(2) + * for us to use. + * + * longclock_t's are definitely not comparable between computers, and in + * some implementations, not even between processes on the same computer. + * + * + * The functions provided here are: + * + * unsigned long cl_times(void); + * A rational wrapper for the times(2) call + * for those cases where only the return value + * is wanted. + * longclock_t time_longclock(void); + * Returns current time as a longclock_t. + * + * longclock_t msto_longclock(unsigned long); + * Converts quantity in milliseconds to longclock_t + * + * unsigned long longclockto_ms(longclock_t); + * Converts quantity in longclock_t to milliseconds + * NOTE: Can overflow! + * + * unsigned long longclockto_long(longclock_t); + * Converts quantity in longclock_t to clock_t + * NOTE: Can overflow! + * + * longclock_t secsto_longclock(unsigned long); + * Converts quantity in seconds to longclock_t + * + * longclock_t add_longclock(longclock_t l, longclock_t r); + * Adds two longclock_t values + * + * int cmp_longclock(longclock_t l, longclock_t r); + * Returns negative, zero or positive value + * + * longclock_t sub_longclock(longclock_t l, longclock_t r); + * Subtracts two longclock_t values + * NOTE: Undefined if l is < r + * + * longclock_t dsecsto_longclock(double); + * Converts quantity in seconds (as a double) + * to a longclock_t + * + * unsigned hz_longclock(void); + * Returns frequency of longclock_t clock. + * + * We provide this constant: + * + * extern const longclock_t zero_longclock; + */ +extern unsigned long cl_times(void); + +#ifdef CLOCK_T_IS_LONG_ENOUGH +# ifndef HAVE_LONGCLOCK_ARITHMETIC +# define HAVE_LONGCLOCK_ARITHMETIC +# endif + +# include <sys/times.h> + + typedef clock_t longclock_t; + +#else /* clock_t isn't at least 64 bits */ + typedef unsigned long long longclock_t; +#endif + +longclock_t time_longclock(void); + +extern const longclock_t zero_longclock; + +unsigned hz_longclock(void); +longclock_t secsto_longclock(unsigned long); +longclock_t dsecsto_longclock(double); +longclock_t msto_longclock(unsigned long); +unsigned long longclockto_ms(longclock_t); /* Can overflow! */ +long longclockto_long(longclock_t); /* May overflow! */ + + +#ifndef HAVE_LONGCLOCK_ARITHMETIC + +longclock_t add_longclock(longclock_t l, longclock_t r); + + /* Undefined if l is < r according to cmp_longclock() */ +longclock_t sub_longclock(longclock_t l, longclock_t r); + +int cmp_longclock(longclock_t l, longclock_t r); + + +#else /* We HAVE_LONGCLOCK_ARITHMETIC */ + +# define longclockto_long(lc) ((long)(lc)) + +# define add_longclock(l,r) \ + ((longclock_t)(l) + (longclock_t)(r)) + +# define sub_longclock(l,r) \ + ((longclock_t)(l) - (longclock_t)(r)) + +# define cmp_longclock(l,r) \ + (((longclock_t)(l) < (longclock_t)(r)) \ + ? -1 \ + : (((longclock_t)(l) > (longclock_t)(r)) \ + ? +1 : 0)) +#endif + + +/* N.B: Possibly not the best place for this, but it will do for now */ +/* This is consistent with OpenBSD, and is a good choice anyway */ +#define TIME_T unsigned long +#define TIME_F "%lu" +#define TIME_X "%lx" + +#endif diff --git a/include/clplumbing/lsb_exitcodes.h b/include/clplumbing/lsb_exitcodes.h new file mode 100644 index 0000000..e46b5be --- /dev/null +++ b/include/clplumbing/lsb_exitcodes.h @@ -0,0 +1,92 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* LSB status exit codes. + * + * All of these and the supporting text are taken from the LSB. + * + * If the status command is given, the init script will return + * the following exit status codes. + * + * 0 program is running or service is OK + * 1 program is dead and /var/run pid file exists + * 2 program is dead and /var/lock lock file exists + * 3 program is stopped + * 4 program or service status is unknown + * 5-99 reserved for future LSB use + * 100-149 reserved for distribution use + * 150-199 reserved for application use + * 200-254 reserved + */ + +#define LSB_STATUS_OK 0 +#define LSB_STATUS_VAR_PID 1 +#define LSB_STATUS_VAR_LOCK 2 +#define LSB_STATUS_STOPPED 3 +#define LSB_STATUS_UNKNOWN 4 +#define LSB_STATUS_LSBRESERVED 5 +#define LSB_STATUS_DISTRESERVED 100 +#define LSB_STATUS_APPRESERVED 150 +#define LSB_STATUS_RESERVED 200 +/* + * + * In the case of init script commands other than "status" + * (i.e., "start", "stop", "restart", "reload", and "force-reload"), + * the init script must return an exit status of zero if the action + * described by the argument has been successful. Otherwise, the + * exit status shall be non-zero, as defined below. In addition + * to straightforward success, the following situations are also + * to be considered successful: + * + * restarting a service (instead of reloading it) with the + * "force-reload" argument + * running "start" on a service already running + * running "stop" on a service already stopped or not running + * running "restart" on a service already stopped or not running + * In case of an error, while processing any init script action + * except for "status", the init script must print an error + * message and return one of the following non-zero exit + * status codes. + * + * 1 generic or unspecified error (current practice) + * 2 invalid or excess argument(s) + * 3 unimplemented feature (for example, "reload") + * 4 user had insufficient privilege + * 5 program is not installed + * 6 program is not configured + * 7 program is not running + * 8-99 reserved for future LSB use + * 100-149 reserved for distribution use + * 150-199 reserved for application use + * 200-254 reserved + * + * All error messages must be printed on standard error. + * All status messages must be printed on standard output. + * (This does not prevent scripts from calling the logging + * functions such as log_failure_msg). + */ +#define LSB_EXIT_OK 0 +#define LSB_EXIT_GENERIC 1 +#define LSB_EXIT_EINVAL 2 +#define LSB_EXIT_ENOTSUPPORTED 3 +#define LSB_EXIT_EPERM 4 +#define LSB_EXIT_NOTINSTALLED 5 +#define LSB_EXIT_NOTCONFIGED 6 +#define LSB_EXIT_NOTRUNNING 7 +#define LSB_EXIT_LSBRESERVED 8 +#define LSB_EXIT_DISTRESERVED 100 +#define LSB_EXIT_APPRESERVED 150 +#define LSB_EXIT_RESERVED 200 diff --git a/include/clplumbing/md5.h b/include/clplumbing/md5.h new file mode 100644 index 0000000..95b2c33 --- /dev/null +++ b/include/clplumbing/md5.h @@ -0,0 +1,49 @@ +/* + * md5.h: MD5 and keyed-MD5 algorithms + * + * Author: Sun Jiang Dong <sunjd@cn.ibm.com> + * Copyright (c) 2005 International Business Machines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _MD5_H_ +#define _MD5_H__ + +/* + * MD5: The MD5 Message-Digest Algorithm ( RFC 1321 ) + * return value: 0 - success + * <0 - fail + * Note: The digest buffer should be not less than 16. + * + */ +int MD5( const unsigned char *data + , unsigned long data_len + , unsigned char * digest); + +/* + * HMAC: Keyed-Hashing for Message Authentication + * return value: 0 - success + * <0 - fail + * Note: The digest buffer should be not less than 16. + */ +int HMAC( const unsigned char * key + , unsigned int key_len + , const unsigned char * data + , unsigned long data_len + , unsigned char * digest); + +#endif diff --git a/include/clplumbing/mkstemp_mode.h b/include/clplumbing/mkstemp_mode.h new file mode 100644 index 0000000..ff5f893 --- /dev/null +++ b/include/clplumbing/mkstemp_mode.h @@ -0,0 +1,34 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * A slightly safer version of mkstemp(3) + * + * In this version, the file is initially created mode 0, (using umask) and + * then chmod-ed to the requested permissions after calling mkstemp(3). + * This guarantees that the file is not even momentarily open beyond the + * requested permissions. + * + * Return values: + * + * Like mkstemp, it returns the file descriptor of the open file, or -1 + * on error. + * + * In addition to the errno values documented for mkstemp(3), this functio + * can also fail with any of the errno values documented for chmod(2). + * + */ +int mkstemp_mode(char* template, mode_t requested_filemode); diff --git a/include/clplumbing/netstring.h b/include/clplumbing/netstring.h new file mode 100644 index 0000000..ef24e8f --- /dev/null +++ b/include/clplumbing/netstring.h @@ -0,0 +1,48 @@ +/* + * Intracluster message object (struct ha_msg) + * + * Copyright (C) 1999, 2000 Guochun Shi<gshi@unix.sh> + * This software licensed under the GNU LGPL. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef NET_STRING_H +#define NET_STRING_H +#include <stdlib.h> +#include <stdio.h> +#include <ha_msg.h> + +extern gboolean cl_msg_quiet_fmterr; + +/* Convert a message to netstring data */ +char* msg2netstring(const struct ha_msg*, size_t*); +char * msg2netstring_noauth(const struct ha_msg *m, size_t * slen); + +/* Convert netstring data to a message */ +struct ha_msg * netstring2msg(const char*, size_t, int); + +/* Is this netstring authentic? */ +int is_auth_netstring(const char* datap, size_t datalen, + const char* authstring, size_t authlen); + +void cl_set_authentication_computation_method(int (*method)(int authmethod +, const void * data +, size_t datalen +, char * authstr +, size_t authlen)); + +#endif diff --git a/include/clplumbing/proctrack.h b/include/clplumbing/proctrack.h new file mode 100644 index 0000000..975ff1b --- /dev/null +++ b/include/clplumbing/proctrack.h @@ -0,0 +1,120 @@ +/* + * Process tracking object. + * + * Copyright (c) 2002 International Business Machines + * Author: Alan Robertson <alanr@unix.sh> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _PROCTRACK_H +# define _PROCTRACK_H +#include <sys/types.h> +#include <sys/times.h> +#include <clplumbing/longclock.h> + +/* + * We track processes, mainly so we can do something appropriate + * when they die, and find processes should we need to kill them... + */ + +typedef struct _ProcTrack ProcTrack; +typedef struct _ProcTrack_ops ProcTrack_ops; +typedef struct _ProcTrackKillInfo ProcTrackKillInfo; + +/* + * The levels of logging possible for our process + */ +enum _ProcTrackLogType { + PT_LOGNONE = 2, /* Exits never automatically logged */ + PT_LOGNORMAL, /* Automatically log abnormal exits */ + PT_LOGVERBOSE /* Automatically log every exit */ +}; +typedef enum _ProcTrackLogType ProcTrackLogType; + +#define proctrack_pid(p) (p)->pid +#define proctrack_data(p) (p)->privatedata +#define reset_proctrack_data(p) (p)->privatedata = NULL +#define proctrack_timedout(p) ((p)->timeoutseq > 0) + +struct _ProcTrack { + pid_t pid; + int isapgrp; + ProcTrackLogType loglevel; + void * privatedata; + ProcTrack_ops* ops; + + longclock_t startticks; + TIME_T starttime; + unsigned timerid; + int timeoutseq; + ProcTrackKillInfo* killinfo; +}; + +/* + * The set of operations to perform on our tracked processes. + */ +struct _ProcTrack_ops { + + /* Called when a process dies */ + void (*procdied) + (ProcTrack* p, int status, int signo, int exitcode + , int waslogged); + + /* Called when a process registers */ + void (*procregistered) + (ProcTrack*p); + + /* Returns a "name" for a process (for messages) */ + /* (may have to be copied, because it may be a static value) */ + const char * + (*proctype) + (ProcTrack* p); +}; + +struct _ProcTrackKillInfo { + long mstimeout; /* Timeout in milliseconds */ + int signalno; /* Signal number to issue @ timeout */ +}; + +/* A function for calling by the process table iterator */ +typedef void (*ProcTrackFun) (ProcTrack* p, void * data); + +/* Call this function to activate the procdied member function */ +/* Returns TRUE if 'pid' was registered */ +int ReportProcHasDied(int pid, int status); + +/* Create/Log a new tracked process */ +void NewTrackedProc(pid_t pid, int isapgrp, ProcTrackLogType loglevel +, void * privatedata , ProcTrack_ops* ops); + +/* "info" is 0-terminated (terminated by a 0 signal) */ +int SetTrackedProcTimeouts(pid_t pid, ProcTrackKillInfo* info); +void RemoveTrackedProcTimeouts(pid_t pid); + +/* Return information associated with the given PID (or NULL) */ +ProcTrack* GetProcInfo(pid_t pid); + +/* + * Iterate over the set of tracked processes. + * If proctype is NULL, then walk through them all, otherwise only those + * of the given type ("f") + */ +void ForEachProc(ProcTrack_ops* proctype, ProcTrackFun f, void * data); + +void DisableProcLogging(void); /* Useful for shutdowns */ +void EnableProcLogging(void); +#endif diff --git a/include/clplumbing/realtime.h b/include/clplumbing/realtime.h new file mode 100644 index 0000000..45eb76c --- /dev/null +++ b/include/clplumbing/realtime.h @@ -0,0 +1,65 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CLPLUMBING_REALTIME_H +# define _CLPLUMBING_REALTIME_H +# include <sched.h> + +#if defined(SCHED_RR) && defined(_POSIX_PRIORITY_SCHEDULING) && !defined(ON_DARWIN) +# define DEFAULT_REALTIME_POLICY SCHED_RR +#endif + +/* + * + * make_realtime() will make the current process a soft realtime process + * and lock it into memory after growing the heap by heapgrowK*1024 bytes + * + * If you set spolicy or priority to <= 0, then defaults will be used. + * Otherwise you need to use a value for spolicy from <sched.h> + * and use an appropriate priority for the given spolicy. + * + * WARNING: badly behaved programs which use the make_realtime() function + * can easily hang the machine. + */ + +void cl_make_realtime +( int spolicy, /* SCHED_RR or SCHED_FIFO (or SCHED_OTHER) */ + int priority, /* typically 1-99 */ + int stackgrowK, /* Amount to grow stack by */ + int heapgrowK /* Amount to grow heap by */ +); + +void cl_make_normaltime(void); + +/* Cause calls to make_realtime() to be ignored */ +void cl_disable_realtime(void); + +/* Cause calls to make_realtime() to be accepted. + * This is the default behaviour */ +void cl_enable_realtime(void); + +/* Sleep a really short (the shortest) time */ +int cl_shortsleep(void); + +/* Print messages if we've done (more) non-realtime mallocs */ +void cl_realtime_malloc_check(void); + +/* Number of times we "go to the well" for memory after becoming realtime */ +int cl_nonrealtime_malloc_count(void); +/* Number of bytes we "got from the well" for memory after becoming realtime */ +unsigned long cl_nonrealtime_malloc_size(void); + +#endif diff --git a/include/clplumbing/replytrack.h b/include/clplumbing/replytrack.h new file mode 100644 index 0000000..f98fe48 --- /dev/null +++ b/include/clplumbing/replytrack.h @@ -0,0 +1,208 @@ +/* + * Process tracking object. + * + * Copyright (c) 2007 Alan Robertson + * Author: Alan Robertson <alanr@unix.sh> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _REPLYTRACK_H +# define _REPLYTRACK_H +#include <sys/types.h> +#include <sys/times.h> +#include <clplumbing/longclock.h> +#include <clplumbing/cl_uuid.h> + +/* + * We track replies - so we can tell when all expected replies were received. + * + * There is a problem in clusters where a message is sent to each node, and a + * reply is expected from each node of knowing when all the replies have been + * received. + * + * If all nodes are up, it's easy to see when all replies are received. + * But, if some nodes are down, we really don't want to wait for a timeout + * before we decide that we've gotten all the replies we're going to get, + * since nodes can be down for potentially very long periods of time, and + * waiting for a long timeout can delay things a great deal again and + * again - causing significant delays and user frustration. + * + * That's where these functions come in! + * Instead, inform these functions what nodes are up and what ones are down, + * and when you receive a reply, and it will tell you when you've gotten + * them all - managing all that tedious bookwork for you. + */ + +typedef enum _replytrack_completion_type replytrack_completion_type_t; +typedef enum _nodetrack_change nodetrack_change_t; +typedef struct _replytrack replytrack_t; +typedef struct _nodetrack nodetrack_t; +typedef struct _nodetrack_intersection nodetrack_intersection_t; + +/* + * The levels of logging possible for our process + */ +enum _replytrack_completion_type { + REPLYT_ALLRCVD = 2, /* All replies received */ + REPLYT_TIMEOUT, /* Timeout occurred with replies missing */ +}; + + +typedef void (*replytrack_callback_t) +( replytrack_t * rl +, gpointer user_data +, replytrack_completion_type_t reason); + +typedef void (*replytrack_iterator_t) +( replytrack_t* rl +, gpointer user_data +, const char* node +, cl_uuid_t uuid); + +typedef void (*nodetrack_iterator_t) +( nodetrack_t* rl +, gpointer user_data +, const char* node +, cl_uuid_t uuid); + + +/* + * Note: + * If you use the timeout feature of this code, it relies on you using glib mainloop + * for your scheduling. timeout_ms should be zero for no timeout. + */ +replytrack_t* replytrack_new(nodetrack_t* membership +, replytrack_callback_t callback +, unsigned long timeout_ms +, gpointer user_data); + +void replytrack_del(replytrack_t *rl); +gboolean replytrack_gotreply(replytrack_t *rl +, const char * node +, cl_uuid_t uuid); + /* Returns TRUE if this was the final expected reply */ +/* + * Iterate over the set of outstanding replies: + * return count of how many items in the iteration + */ +int replytrack_outstanding_iterate(replytrack_t* rl +, replytrack_iterator_t i, gpointer user_data); +int replytrack_outstanding_count(replytrack_t* rl); + +/* + * The functions above operate using a view of membership which is established + * through the functions below. + * + * This can either be through the heartbeat low-level membership API, or any + * other view of membership you wish. Mentioning a node as either up or down + * will automatically add that node to our view of potential membership. + * + * These functions only support one view of membership per process. + * + * The general idea of how to use these functions: + * Initially: + * 1) iterate through init membership and call nodetrack_node(up|down) for + * each node to start things off. + * + * On an ongoing basis: + * 2) call nodetrack_node_up whenever a node comes up + * We expect a reply from nodes that are up. + * 3) call nodetrack_node_down whenever a node goes down + * We don't expect a reply from nodes that are down. + * + * For each set of replies you want tracked: + * 4) Create a replytrack_t for a set of expected replies + * 5) call replytrack_gotreply() each time you get an expected reply + * 6) replist_gotreply() returns TRUE when the final message was received. + * (it does this by comparing against the membership as defined below) + * 7) you will get a callback when timeout occurs or final message is received + * n. b.: + * No callback function => manage timeouts yourself + * 8) call replytrack_del() when you're done with the reply list + * n. b.: + * If you have replies outstanding, and you have a timeout and + * a callback function set, you will get a warning for destroying + * a replytrack_t object 'prematurely'. + * You will also log a warning if you call replytrack_gotreply() after + * all replies were received or a timeout occurred. + * + */ + +/* + * The levels of logging possible for our process + */ +enum _nodetrack_change { + NODET_UP = 2, /* This node came up */ + NODET_DOWN, /* This node went down */ +}; + +typedef void (*nodetrack_callback_t) +( nodetrack_t * mbr +, const char * node +, cl_uuid_t u +, nodetrack_change_t reason +, gpointer user_data); + +nodetrack_t* nodetrack_new(nodetrack_callback_t callback +, gpointer user_data); +void nodetrack_del(nodetrack_t*); +gboolean nodetrack_nodeup(nodetrack_t* mbr, const char * node +, cl_uuid_t u); +gboolean nodetrack_nodedown(nodetrack_t* mbr, const char * node +, cl_uuid_t u); +gboolean nodetrack_ismember(nodetrack_t* mbr, const char * node +, cl_uuid_t u); +int nodetrack_iterate(nodetrack_t* mbr +, nodetrack_iterator_t i, gpointer user_data); + +/* An intesection nodetrack table + * A node is put into the "intersection" nodetrack_t table when it is in all + * the underlying constituent nodetrack_t tables, and removed when it is + * removed from any of them. + * Note that you can set a callback to be informed when these "intersection" + * membership changes occur. + */ +nodetrack_intersection_t* + nodetrack_intersection_new(nodetrack_t** tables, int ntables +, nodetrack_callback_t callback, gpointer user_data); +void nodetrack_intersection_del(nodetrack_intersection_t*); +nodetrack_t* nodetrack_intersection_table(nodetrack_intersection_t*); + +#if 0 +/* + * I don't know if this should be in this library, or just in + * the CCM. Probably only the CCM _should_ be using it (when I write it) + */ +/* + * Use of the nodetrack_hb_* functions implies you're using the heartbeat + * peer-connectivity information as your source of information. This is + * really only suitable if you're using heartbeat's low-level group membership + * for your source of who to expect replies from. + * If you're using nodetrack_hb_init, this replaces step (1) above. + */ +void nodetrack_hb_init(void) +/* + * If you're using nodetrack_hb_statusmsg, just pass it all status messages + * and all peer-connectivity status messages or even all heartbeat messages + * (non-status messages will be ignored). + * This replaces steps (2) and (3) above _if_ you're using heartbeat low + * level membership for your source of who to expect replies from. + */ +void nodetrack_hb_statusmsg(struct ha_msg* statusmsg); +#endif /*0*/ + +#endif diff --git a/include/clplumbing/setproctitle.h b/include/clplumbing/setproctitle.h new file mode 100644 index 0000000..5caeef0 --- /dev/null +++ b/include/clplumbing/setproctitle.h @@ -0,0 +1,64 @@ +/* + * setproctitle.h + * + * The code in this file, setproctitle.h is heavily based on code from + * proftpd, please see the licening information below. + * + * This file added to the heartbeat tree by Horms <horms@vergenet.net> + * + * Code to portably change the title of a programme as displayed + * by ps(1). + * + * heartbeat: Linux-HA heartbeat code + * + * Copyright (C) 1999,2000,2001 Alan Robertson <alanr@unix.sh> + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * ProFTPD - FTP server daemon + * Copyright (c) 1997, 1998 Public Flood Software + * Copyright (C) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net> + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu + * and other respective copyright holders give permission to link this program + * with OpenSSL, and distribute the resulting executable, without including + * the source code for OpenSSL in the source distribution. + */ + +#ifndef _HA_SETPROCTITLE_H +#define _HA_SETPROCTITLE_H + +#include <glib.h> +int init_set_proc_title(int argc, char *argv[], char *envp[]); + +void set_proc_title(const char *fmt,...) G_GNUC_PRINTF(1,2); + +#endif /* _HA_SETPROCTITLE_H */ diff --git a/include/clplumbing/timers.h b/include/clplumbing/timers.h new file mode 100644 index 0000000..669ac21 --- /dev/null +++ b/include/clplumbing/timers.h @@ -0,0 +1,23 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CLPLUMBING_TIMERS_H +# define _CLPLUMBING_TIMERS_H +int setmsrepeattimer(long ms); +int setmsalarm(long ms); +int cancelmstimer(void); +long mssleep(long ms); +#endif diff --git a/include/clplumbing/uids.h b/include/clplumbing/uids.h new file mode 100644 index 0000000..89ba303 --- /dev/null +++ b/include/clplumbing/uids.h @@ -0,0 +1,32 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CLPLUMBING_UIDS_H +# define CLPLUMBING_UIDS_H +#include <sys/types.h> + +/* Tell us who you want to be - or zero for nobody */ +int drop_privs(uid_t uid, gid_t gid); + +/* Return to original privileged state */ +int return_to_orig_privs(void); + +/* Drop down to (probably nobody) privileges again */ +int return_to_dropped_privs(void); + +/* Return TRUE if we have full privileges at the moment */ +int cl_have_full_privs(void); +#endif diff --git a/include/compress.h b/include/compress.h new file mode 100644 index 0000000..9cd733c --- /dev/null +++ b/include/compress.h @@ -0,0 +1,50 @@ +/* + * compress.h: Compression functions for Linux-HA + * + * Copyright (C) 2005 Guochun Shi <gshi@ncsa.uiuc.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _COMPRESS_H_ +#define _COMPRESS_H_ + +#define HB_COMPRESS_TYPE compress +#define HB_COMPRESS_TYPE_S "compress" + +/* + * List of functions provided by implementations of the heartbeat + * compress interface. + */ +struct hb_compress_fns { + int (*compress) (char*, size_t*, const char*, size_t); + int (*decompress) (char*, size_t* , const char*, size_t); + const char* (*getname) (void); +}; + +struct ha_msg; + +/* set the compression method*/ +int cl_compress_remove_plugin(const char* pluginname); +int cl_compress_load_plugin(const char* pluginname); +struct hb_compress_fns* cl_get_compress_fns(void); +int cl_set_compress_fns(const char*); +char* cl_compressmsg(struct ha_msg*m, size_t* len); +struct ha_msg* cl_decompressmsg(struct ha_msg* m); +gboolean is_compressed_msg(struct ha_msg* m); +int cl_compress_field(struct ha_msg* msg, int index, char* buf, size_t* buflen); +int cl_decompress_field(struct ha_msg* msg, int index, char* buf, size_t* buflen); + +#endif diff --git a/include/glue_config.h.in b/include/glue_config.h.in new file mode 100644 index 0000000..0850a63 --- /dev/null +++ b/include/glue_config.h.in @@ -0,0 +1,104 @@ +/* include/config.h.in. Generated from configure.in by autoheader. */ + +/* Location for daemons */ +#undef GLUE_DAEMON_DIR + +/* Group to run daemons as */ +#undef GLUE_DAEMON_GROUP + +/* User to run daemons as */ +#undef GLUE_DAEMON_USER + +/* Where to keep state files and sockets */ +#undef GLUE_STATE_DIR + +/* Location of shared data */ +#undef GLUE_SHARED_DIR + +/* User to run daemons as */ +#undef HA_CCMUSER + +/* Group to run daemons as */ +#undef HA_APIGROUP + +/* Location for daemons */ +#undef HA_LIBHBDIR + +/* top directory of area to drop core files in */ +#undef HA_COREDIR + +/* top directory for LRM related files */ +#undef LRM_VARLIBDIR + +/* CIB secrets */ +#undef LRM_CIBSECRETS + +/* Logging Daemon IPC socket name */ +#undef HA_LOGDAEMON_IPC + +/* Default logging facility */ +#undef HA_LOG_FACILITY + +/* Default plugin search path */ +#undef PILS_BASE_PLUGINDIR + +/* Where to find plugins */ +#undef HA_PLUGIN_DIR + +/* Location of system configuration files */ +#undef HA_SYSCONFDIR + +/* Web site base URL */ +#undef HA_URLBASE + +/* Whatever this used to mean */ +#undef HA_VARLIBHBDIR + +#undef HA_VARLIBDIR + +/* System lock directory */ +#undef HA_VARLOCKDIR + +/* Where Heartbeat keeps state files and sockets - old name */ +#undef HA_VARRUNDIR + +/* Location for v1 Heartbeat RAs */ +#undef HB_RA_DIR + +/* Where to find LRM plugins */ +#undef LRM_PLUGIN_DIR + +/* Location for LSB RAs */ +#undef LSB_RA_DIR + +/* Location for OCF RAs */ +#undef OCF_RA_DIR + +/* OCF root directory - specified by the OCF standard */ +#undef OCF_ROOT_DIR + +/* Compiling for Darwin platform */ +#undef ON_DARWIN + +/* Compiling for Linux platform */ +#undef ON_LINUX + +/* Current glue version */ +#undef GLUE_VERSION + +/* Build version */ +#undef GLUE_BUILD_VERSION + +/* Location of non-pluing stonith scripts */ +#undef STONITH_EXT_PLUGINDIR + +/* Location of RHCS stonith scripts */ +#undef STONITH_RHCS_PLUGINDIR + +/* Location of stonith plugins */ +#undef STONITH_MODULES + +/* Stonith plugin domain */ +#undef ST_TEXTDOMAIN + +#undef HA_HBCONF_DIR diff --git a/include/ha_msg.h b/include/ha_msg.h new file mode 100644 index 0000000..fcb6cf6 --- /dev/null +++ b/include/ha_msg.h @@ -0,0 +1,464 @@ +/* + * Intracluster message object (struct ha_msg) + * + * Copyright (C) 1999, 2000 Alan Robertson <alanr@unix.sh> + * This software licensed under the GNU LGPL. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _HA_MSG_H +# define _HA_MSG_H 1 +#include <stdio.h> +#include <clplumbing/cl_log.h> +#include <clplumbing/ipc.h> +#include <clplumbing/longclock.h> +#include <clplumbing/cl_uuid.h> +#include <compress.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + + +enum cl_netstring_type{ + FT_STRING = 0, + FT_BINARY, + FT_STRUCT, + FT_LIST, + FT_COMPRESS, + FT_UNCOMPRESS +}; + +enum cl_msgfmt{ + MSGFMT_NVPAIR, + MSGFMT_NETSTRING +}; + + +#define NEEDHEAD 1 +#define NOHEAD 0 +#define HA_MSG_ASSERT(X) do{ if(!(X)){ \ + cl_log(LOG_ERR, "Assertion failed on line %d in file \"%s\"" \ + , __LINE__, __FILE__); \ + abort(); \ + } \ + }while(0) + +typedef struct hb_msg_stats_s { + unsigned long totalmsgs; /* Total # of messages */ + /* ever handled */ + unsigned long allocmsgs; /* # Msgs currently allocated */ + longclock_t lastmsg; +}hb_msg_stats_t; + +struct ha_msg { + int nfields; + int nalloc; + char ** names; + size_t* nlens; + void ** values; + size_t* vlens; + int * types; +}; + +typedef struct ha_msg HA_Message; + +struct fieldtypefuncs_s{ + + /* memfree frees the memory involved*/ + void (*memfree)(void*); + + /* dup makes a complete copy of the field*/ + void* (*dup)(const void*, size_t); + + /* display printout the field*/ + void (*display)(int, int, char* , void*, int); + + /* add the field into a message*/ + int (*addfield) (struct ha_msg* msg, char* name, size_t namelen, + void* value, size_t vallen, int depth); + + /* return the string length required to add this field*/ + int (*stringlen) (size_t namlen, size_t vallen, const void* value); + + /* return the netstring length required to add this field*/ + int (*netstringlen) (size_t namlen, size_t vallen, const void* value); + + /* print the field into the provided buffer, convert it first */ + /* if ncecessary*/ + int (*tostring)(char*, char*, void* ,size_t,int); + + /* print the field into the provided buffer*/ + int (*tonetstring)(char*, char*, char*, size_t, + void*, size_t, int, size_t*); + + /* convert the given string to a field + note: this functions involves allocate memory for + for the field + */ + int (*stringtofield)(void*, size_t, int depth, void**, size_t* ); + + /* convert the given netstring to a field + note: this functions involves allocate memory for + for the field + */ + int (*netstringtofield)(const void*, size_t, void**, size_t*); + + /* action before packing*/ + int (*prepackaction)(struct ha_msg* m, int index); + + /* action before a user get the value of a field*/ + int (*pregetaction)(struct ha_msg* m, int index); + +}; + +#define NUM_MSG_TYPES 6 +extern struct fieldtypefuncs_s fieldtypefuncs[NUM_MSG_TYPES]; + +#define MSG_NEEDAUTH 0x01 +#define MSG_ALLOWINTR 0X02 +#define MSG_NEEDCOMPRESS 0x04 +#define MSG_NOSIZECHECK 0x08 + +#define IFACE "!^!\n" +#define MSG_START ">>>\n" +#define MSG_END "<<<\n" +#define MSG_START_NETSTRING "###\n" +#define MSG_END_NETSTRING "%%%\n" +#define EQUAL "=" + +#define MAXDEPTH 16 /* Maximum recursive message depth */ +#define MAXLENGTH 1024 + + /* Common field names for our messages */ +#define F_TYPE "t" /* Message type */ +#define F_SUBTYPE "subt" /* Message type */ +#define F_ORIG "src" /* Real Originator */ +#define F_ORIGUUID "srcuuid" /* Real Originator uuid*/ +#define F_NODE "node" /* Node being described */ +#define F_NODELIST "nodelist" /* Node list being described */ +#define F_DELNODELIST "delnodelist" /* Del node list being described */ +#define F_TO "dest" /* Destination (optional) */ +#define F_TOUUID "destuuid" /* Destination uuid(optional) */ +#define F_STATUS "st" /* New status (type = status) */ +#define F_WEIGHT "weight" /* weight of node */ +#define F_SITE "site" /* site of node */ +#define F_PROTOCOL "protocol" /* Protocol number for communication*/ +#define F_CLIENTNAME "cn" /* Client name */ +#define F_CLIENTSTATUS "cs" /* Client status */ +#define F_TIME "ts" /* Timestamp */ +#define F_SEQ "seq" /* Sequence number */ +#define F_LOAD "ld" /* Load average */ +#define F_COMMENT "info" /* Comment */ +#define F_TTL "ttl" /* Time To Live */ +#define F_AUTH "auth" /* Authentication string */ +#define F_HBGENERATION "hg" /* Heartbeat generation number */ +#define F_CLIENT_GENERATION "client_gen" /* client generation number*/ +#define F_FIRSTSEQ "firstseq" /* Lowest seq # to retransmit */ +#define F_LASTSEQ "lastseq" /* Highest seq # to retransmit */ +#define F_RESOURCES "rsc_hold" /* What resources do we hold? */ +#define F_FROMID "from_id" /* from Client id */ +#define F_TOID "to_id" /* To client id */ +#define F_PID "pid" /* PID of client */ +#define F_UID "uid" /* uid of client */ +#define F_GID "gid" /* gid of client */ +#define F_ISSTABLE "isstable" /* true/false for RESOURCES */ +#define F_APIREQ "reqtype" /* API request type for "hbapi" */ +#define F_APIRESULT "result" /* API request result code */ +#define F_IFNAME "ifname" /* Interface name */ +#define F_PNAME "pname" /* Parameter name */ +#define F_PVALUE "pvalue" /* Parameter name */ +#define F_DEADTIME "deadtime" /* Dead time interval in ms. */ +#define F_KEEPALIVE "keepalive" /* Keep alive time interval in ms. */ +#define F_LOGFACILITY "logfacility" /* Suggested cluster syslog facility */ +#define F_NODETYPE "nodetype" /* Type of node */ +#define F_NUMNODES "numnodes" /* num of total nodes(excluding ping nodes*/ +#define F_RTYPE "rtype" /* Resource type */ +#define F_ORDERSEQ "oseq" /* Order Sequence number */ +#define F_DT "dt" /* Dead time field for heartbeat*/ +#define F_ACKSEQ "ackseq" /* The seq number this msg is acking*/ +#define F_CRM_DATA "crm_xml" +#define F_XML_TAGNAME "__name__" +#define F_STATE "state" /*used in ccm for state info*/ + + + /* Message types */ +#define T_STATUS "status" /* Status (heartbeat) */ +#define T_IFSTATUS "ifstat" /* Interface status */ +#define T_ASKRESOURCES "ask_resources" /* Let other node ask my resources */ +#define T_ASKRELEASE "ip-request" /* Please give up these resources... */ +#define T_ACKRELEASE "ip-request-resp"/* Resources given up... */ +#define T_QCSTATUS "query-cstatus" /* Query client status */ +#define T_RCSTATUS "respond-cstatus"/* Respond client status */ +#define T_STONITH "stonith" /* Stonith return code */ +#define T_SHUTDONE "shutdone" /* External Shutdown complete */ +#define T_CRM "crmd" /* Cluster resource manager message */ +#define T_ATTRD "attrd" /* Cluster resource manager message */ +#define T_ADDNODE "addnode" /* Add node message*/ +#define T_DELNODE "delnode" /* Delete node message*/ +#define T_SETWEIGHT "setweight" /* Set node weight*/ +#define T_SETSITE "setsite" /* Set node site*/ +#define T_REQNODES "reqnodes" /* Request node list */ +#define T_REPNODES "repnodes" /* reply node list rquest*/ + +#define T_APIREQ "hbapi-req" /* Heartbeat API request */ +#define T_APIRESP "hbapi-resp" /* Heartbeat API response */ +#define T_APICLISTAT "hbapi-clstat" /* Client status notification" */ + +#define NOSEQ_PREFIX "NS_" /* PREFIX: Give no sequence number */ + /* Used for messages which can't be retransmitted */ + /* Either they're protocol messages or from dumb (ping) endpoints */ +#define T_REXMIT NOSEQ_PREFIX "rexmit" /* Rexmit request */ +#define T_NAKREXMIT NOSEQ_PREFIX "nak_rexmit" /* NAK Rexmit request */ +#define T_NS_STATUS NOSEQ_PREFIX "st" /* ping status */ +#define T_ACKMSG NOSEQ_PREFIX "ackmsg" /* ACK message*/ + +/* Messages associated with nice_failback */ +#define T_STARTING "starting" /* Starting Heartbeat */ + /* (requesting resource report) */ +#define T_RESOURCES "resource" /* Resources report */ + +/* Messages associated with stonith completion results */ +#define T_STONITH_OK "OK" /* stonith completed successfully */ +#define T_STONITH_BADHOST "badhost" /* stonith failed */ +#define T_STONITH_BAD "bad" /* stonith failed */ +#define T_STONITH_NOTCONFGD "n_stnth" /* no stonith device configured */ +#define T_STONITH_UNNEEDED "unneeded" /* STONITH not required */ + +/* Set up message statistics area */ + +int netstring_extra(int); +int cl_msg_stats_add(longclock_t time, int size); + +void cl_msg_setstats(volatile hb_msg_stats_t* stats); +void cl_dump_msgstats(void); +void cl_set_compression_threshold(size_t threadhold); +void cl_set_traditional_compression(gboolean value); + +/* Allocate new (empty) message */ +struct ha_msg * ha_msg_new(int nfields); + +/* Free message */ +void ha_msg_del(struct ha_msg *msg); + +/* Copy message */ +struct ha_msg* ha_msg_copy(const struct ha_msg *msg); + +int ha_msg_expand(struct ha_msg* msg ); + +/*Add a null-terminated name and binary value to a message*/ +int ha_msg_addbin(struct ha_msg * msg, const char * name, + const void * value, size_t vallen); + +int ha_msg_adduuid(struct ha_msg * msg, const char * name, + const cl_uuid_t* uuid); + +/* Add null-terminated name and a value to the message */ +int ha_msg_add(struct ha_msg * msg + , const char* name, const char* value); + +int cl_msg_remove(struct ha_msg* msg, const char* name); +int cl_msg_remove_value(struct ha_msg* msg, const void* value); +int cl_msg_remove_offset(struct ha_msg* msg, int offset); + +/* Modify null-terminated name and a value to the message */ +int cl_msg_modstring(struct ha_msg * msg, + const char* name, + const char* value); +int cl_msg_modbin(struct ha_msg * msg, + const char* name, + const void* value, + size_t vlen); + +int cl_msg_moduuid(struct ha_msg * msg, const char * name, + const cl_uuid_t* uuid); + +int cl_msg_modstruct(struct ha_msg * msg, + const char* name, + const struct ha_msg* value); +#define ha_msg_mod(msg, name, value) cl_msg_modstring(msg, name, value) +int cl_msg_replace(struct ha_msg* msg, int index, + const void* value, size_t vlen, int type); +int cl_msg_replace_value(struct ha_msg* msg, const void *old_value, + const void* value, size_t vlen, int type); + +/* Add name, value (with known lengths) to the message */ +int ha_msg_nadd(struct ha_msg * msg, const char * name, int namelen + , const char * value, int vallen); + +/* Add a name/value/type to a message (with sizes for name and value) */ +int ha_msg_nadd_type(struct ha_msg * msg, const char * name, int namelen + , const char * value, int vallen, int type); + +/* Add name=value string to a message */ +int ha_msg_add_nv(struct ha_msg* msg, const char * nvline, const char * bufmax); + + +/* Return value associated with particular name */ +#define ha_msg_value(m,name) cl_get_string(m, name) + +/* Call wait(in|out) but only for a finite time */ +int cl_ipc_wait_timeout( + IPC_Channel * chan, int (*waitfun)(IPC_Channel * chan), unsigned int timeout); + +/* Reads an IPC stream -- converts it into a message */ +struct ha_msg * msgfromIPC_timeout(IPC_Channel *ch, int flag, unsigned int timeout, int *rc_out); +struct ha_msg * msgfromIPC(IPC_Channel * f, int flag); + +IPC_Message * ipcmsgfromIPC(IPC_Channel * ch); + +/* Reads a stream -- converts it into a message */ +struct ha_msg * msgfromstream(FILE * f); + +/* Reads a stream with string format--converts it into a message */ +struct ha_msg * msgfromstream_string(FILE * f); + +/* Reads a stream with netstring format--converts it into a message */ +struct ha_msg * msgfromstream_netstring(FILE * f); + +/* Same as above plus copying the iface name to "iface" */ +struct ha_msg * if_msgfromstream(FILE * f, char *iface); + +/* Writes a message into a stream */ +int msg2stream(struct ha_msg* m, FILE * f); + +/* Converts a message into a string and adds the iface name on start */ +char * msg2if_string(const struct ha_msg *m, const char * iface); + +/* Converts a string gotten via UDP into a message */ +struct ha_msg * string2msg(const char * s, size_t length); + +/* Converts a message into a string */ +char * msg2string(const struct ha_msg *m); + +/* Converts a message into a string in the provided buffer with certain +depth and with or without start/end */ +int msg2string_buf(const struct ha_msg *m, char* buf, + size_t len, int depth, int needhead); + +/* Converts a message into wire format */ +char* msg2wirefmt(struct ha_msg *m, size_t* ); +char* msg2wirefmt_noac(struct ha_msg*m, size_t* len); + +/* Converts wire format data into a message */ +struct ha_msg* wirefmt2msg(const char* s, size_t length, int flag); + +/* Convets wire format data into an IPC message */ +IPC_Message* wirefmt2ipcmsg(void* p, size_t len, IPC_Channel* ch); + +/* Converts an ha_msg into an IPC message */ +IPC_Message* hamsg2ipcmsg(struct ha_msg* m, IPC_Channel* ch); + +/* Converts an IPC message into an ha_msg */ +struct ha_msg* ipcmsg2hamsg(IPC_Message*m); + +/* Outputs a message to an IPC channel */ +int msg2ipcchan(struct ha_msg*m, IPC_Channel*ch); + +/* Outpus a message to an IPC channel without authencating +the message */ +struct ha_msg* msgfromIPC_noauth(IPC_Channel * ch); + +/* Reads from control fifo, and creates a new message from it */ +/* This adds the default sequence#, load avg, etc. to the message */ +struct ha_msg * controlfifo2msg(FILE * f); + +/* Check if the message is authenticated */ +gboolean isauthentic(const struct ha_msg * msg); + +/* Get the required string length for the given message */ +int get_stringlen(const struct ha_msg *m); + +/* Get the requried netstring length for the given message*/ +int get_netstringlen(const struct ha_msg *m); + +/* Add a child message to a message as a field */ +int ha_msg_addstruct(struct ha_msg * msg, const char * name, const void* ptr); + +int ha_msg_addstruct_compress(struct ha_msg*, const char*, const void*); + +/* Get binary data from a message */ +const void * cl_get_binary(const struct ha_msg *msg, const char * name, size_t * vallen); + +/* Get uuid data from a message */ +int cl_get_uuid(const struct ha_msg *msg, const char * name, cl_uuid_t* retval); + +/* Get string data from a message */ +const char * cl_get_string(const struct ha_msg *msg, const char *name); + +/* Get the type for a field from a message */ +int cl_get_type(const struct ha_msg *msg, const char *name); + +/* Get a child message from a message*/ +struct ha_msg *cl_get_struct(struct ha_msg *msg, const char* name); + +/* Log the contents of a message */ +void cl_log_message (int log_level, const struct ha_msg *m); + +/* Supply messaging system with old style authentication/authorization method */ +void cl_set_oldmsgauthfunc(gboolean (*authfunc)(const struct ha_msg*)); + +/* Set default messaging format */ +void cl_set_msg_format(enum cl_msgfmt mfmt); + +/* Add a string to a list*/ +int cl_msg_list_add_string(struct ha_msg* msg, const char* name, const char* value); + +/* Return length of a list*/ +int cl_msg_list_length(struct ha_msg* msg, const char* name); + +/* Return nth element of a list*/ +void* cl_msg_list_nth_data(struct ha_msg* msg, const char* name, int n); + +/* Functions to add/mod/get an integer */ +int ha_msg_add_int(struct ha_msg * msg, const char * name, int value); +int ha_msg_mod_int(struct ha_msg * msg, const char * name, int value); +int ha_msg_value_int(const struct ha_msg * msg, const char * name, int* value); + +/* Functions to add/mod/get an unsigned long */ +int ha_msg_add_ul(struct ha_msg * msg, const char * name, unsigned long value); +int ha_msg_mod_ul(struct ha_msg * msg, const char * name, unsigned long value); +int ha_msg_value_ul(const struct ha_msg * msg, const char * name, unsigned long* value); + +/* Functions to add/get a string list*/ +GList* ha_msg_value_str_list(struct ha_msg * msg, const char * name); + +int cl_msg_add_list_int(struct ha_msg* msg, const char* name, + int* buf, size_t n); +int cl_msg_get_list_int(struct ha_msg* msg, const char* name, + int* buf, size_t* n); +GList* cl_msg_get_list(struct ha_msg* msg, const char* name); +int cl_msg_add_list(struct ha_msg* msg, const char* name, GList* list); +int cl_msg_add_list_str(struct ha_msg* msg, const char* name, + char** buf, size_t n); + +/* Function to add/get a string hash table*/ +GHashTable* ha_msg_value_str_table(struct ha_msg * msg, const char * name); +int ha_msg_add_str_table(struct ha_msg * msg, const char * name, + GHashTable* hash_table); +int ha_msg_mod_str_table(struct ha_msg * msg, const char * name, + GHashTable* hash_table); + +/*internal use for list type*/ +size_t string_list_pack_length(const GList* list); +int string_list_pack(GList* list, char* buf, char* maxp); +GList* string_list_unpack(const char* packed_str_list, size_t length); +void list_cleanup(GList* list); + +gboolean must_use_netstring(const struct ha_msg*); + + +#endif /* __HA_MSG_H */ diff --git a/include/lha_internal.h b/include/lha_internal.h new file mode 100644 index 0000000..bae10a0 --- /dev/null +++ b/include/lha_internal.h @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2001 Alan Robertson <alanr@unix.sh> + * This software licensed under the GNU LGPL. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + */ + +#ifndef LHA_INTERNAL_H +# define LHA_INTERNAL_H + +#define EOS '\0' +#define DIMOF(a) ((int) (sizeof(a)/sizeof(a[0])) ) +#define STRLEN_CONST(conststr) ((size_t)((sizeof(conststr)/sizeof(char))-1)) +#define STRNCMP_CONST(varstr, conststr) strncmp((varstr), conststr, STRLEN_CONST(conststr)+1) +#define STRLEN(c) STRLEN_CONST(c) +#define MALLOCT(t) ((t *) malloc(sizeof(t))) + +#define HADEBUGVAL "HA_DEBUG" /* current debug value (if nonzero) */ +#define HALOGD "HA_LOGD" /* whether we use logging daemon or not */ + +/* Needs to be defined before any other includes, otherwise some system + * headers do not behave as expected! Major black magic... */ +#undef _GNU_SOURCE /* in case it was defined on the command line */ +#define _GNU_SOURCE + +/* Please leave this as the first #include - Solaris needs it there */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/param.h> +#ifdef BSD +# define SCANSEL_CAST (void *) +#else +# define SCANSEL_CAST /* Nothing */ +#endif + +#if defined(ANSI_ONLY) && !defined(inline) +# define inline /* nothing */ +# undef NETSNMP_ENABLE_INLINE +# define NETSNMP_NO_INLINE 1 +#endif + +#ifndef HAVE_DAEMON + /* We supply a replacement function, but need a prototype */ +int daemon(int nochdir, int noclose); +#endif /* HAVE_DAEMON */ + +#ifndef HAVE_SETENV + /* We supply a replacement function, but need a prototype */ +int setenv(const char *name, const char * value, int why); +#endif /* HAVE_SETENV */ + +#ifndef HAVE_UNSETENV + /* We supply a replacement function, but need a prototype */ +int unsetenv(const char *name); +#endif /* HAVE_UNSETENV */ + +#ifndef HAVE_STRERROR + /* We supply a replacement function, but need a prototype */ +char * strerror(int errnum); +#endif /* HAVE_STRERROR */ + +#ifndef HAVE_SCANDIR + /* We supply a replacement function, but need a prototype */ +# include <dirent.h> +int +scandir (const char *directory_name, + struct dirent ***array_pointer, + int (*select_function) (const struct dirent *), +#ifdef USE_SCANDIR_COMPARE_STRUCT_DIRENT + /* This is what the Linux man page says */ + int (*compare_function) (const struct dirent**, const struct dirent**) +#else + /* This is what the Linux header file says ... */ + int (*compare_function) (const void *, const void *) +#endif + ); +#endif /* HAVE_SCANDIR */ + +#ifndef HAVE_ALPHASORT +# include <dirent.h> +int +alphasort(const void *dirent1, const void *dirent2); +#endif /* HAVE_ALPHASORT */ + +#ifndef HAVE_INET_PTON + /* We supply a replacement function, but need a prototype */ +int +inet_pton(int af, const char *src, void *dst); + +#endif /* HAVE_INET_PTON */ + +#ifndef HAVE_STRNLEN + size_t strnlen(const char *s, size_t maxlen); +#else +# define USE_GNU +#endif + +#ifndef HAVE_STRNDUP + char *strndup(const char *str, size_t len); +#else +# define USE_GNU +#endif +#ifndef HAVE_STRLCPY + size_t strlcpy(char * dest, const char *source, size_t len); +#endif +#ifndef HAVE_STRLCAT + size_t strlcat(char * dest, const char *source, size_t len); +#endif + +#ifndef HAVE_NFDS_T + typedef unsigned int nfds_t; +#endif + +#ifdef HAVE_STRUCT_UCRED_DARWIN +# include <sys/utsname.h> +# ifndef SYS_NMLN +# define SYS_NMLN _SYS_NAMELEN +# endif /* SYS_NMLN */ +#endif + +#define POINTER_TO_SIZE_T(p) ((size_t)(p)) /*pointer cast as size_t*/ +#define POINTER_TO_SSIZE_T(p) ((ssize_t)(p)) /*pointer cast as ssize_t*/ +#define POINTER_TO_ULONG(p) ((unsigned long)(p)) /*pointer cast as unsigned long*/ + /* Sometimes we get a const g_something *, but need to pass it internally + * to other functions taking a non-const g_something *, which results + * with gcc and -Wcast-qual in a compile time warning, and with -Werror + * even to a compile time error. + * Workarounds have been to e.g. memcpy(&list, _list); or similar, + * the reason of which is non-obvious to the casual reader. + * This macro achieves the same, and annotates why it is done. + */ +#define UNCONST_CAST_POINTER(t, p) ((t)(unsigned long)(p)) + +#define HAURL(url) HA_URLBASE url + +/* + * Some compilers may not have defined __FUNCTION__. + */ +#ifndef __FUNCTION__ + +/* Sun studio compiler */ +# ifdef __SUNPRO_C +# define __FUNCTION__ __func__ +# endif + +/* Similarly add your compiler here ... */ + +#endif + +/* You may need to change this for your compiler */ +#ifdef HAVE_STRINGIZE +# define ASSERT(X) {if(!(X)) ha_assert(#X, __LINE__, __FILE__);} +#else +# define ASSERT(X) {if(!(X)) ha_assert("X", __LINE__, __FILE__);} +#endif + +/* shamelessly stolen from linux kernel */ +/* Force a compilation error if condition is true */ +#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition)) +/* Force a compilation error if condition is true, but also produce a + * result (of value 0 and type size_t), so the expression can be used + * e.g. in a structure initializer (or where-ever else comma expressions + * aren't permitted). */ +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) +#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) + +#endif /* LHA_INTERNAL_H */ diff --git a/include/lrm/Makefile.am b/include/lrm/Makefile.am new file mode 100644 index 0000000..ec4f5a5 --- /dev/null +++ b/include/lrm/Makefile.am @@ -0,0 +1,22 @@ +# +# Author: Sun Jiang Dong <sunjd@cn.ibm.com> +# Copyright (c) 2004 International Business Machines +# +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +MAINTAINERCLEANFILES = Makefile.in + +idir=$(includedir)/heartbeat/lrm +i_HEADERS = lrm_api.h lrm_msg.h racommon.h raexec.h diff --git a/include/lrm/lrm_api.h b/include/lrm/lrm_api.h new file mode 100644 index 0000000..cebff1b --- /dev/null +++ b/include/lrm/lrm_api.h @@ -0,0 +1,455 @@ +/* + * Client-side Local Resource Manager API. + * + * Author: Huang Zhen <zhenh@cn.ibm.com> + * Copyright (C) 2004 International Business Machines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * + * By Huang Zhen <zhenhltc@cn.ibm.com> 2004/2/23 + * + * It is based on the works of Alan Robertson, Lars Marowsky Bree, + * Andrew Beekhof. + * + * The Local Resource Manager needs to provide the following functionalities: + * 1. Provide the information of the resources holding by the node to its + * clients, including listing the resources and their status. + * 2. Its clients can add new resources to lrm or remove from it. + * 3. Its clients can ask lrm to operate the resources, including start, + * restart, stop and so on. + * 4. Provide the information of the lrm itself, including what types of + * resource are supporting by lrm. + * + * The typical clients of lrm are crm and lrmadmin. + */ + + /* + * Notice: + * "status" indicates the exit status code of "status" operation + * its value is defined in LSB, OCF... + * + * "state" indicates the state of resource, maybe LRM_RSC_BUSY, LRM_RSC_IDLE + * + * "op_status" indicates how the op exit. like LRM_OP_DONE,LRM_OP_CANCELLED, + * LRM_OP_TIMEOUT,LRM_OP_NOTSUPPORTED. + * + * "rc" is the return code of an opertioan. it's value is in following enum + * which is defined in "raexec.h" + * enum UNIFORM_RET_EXECRA { + * EXECRA_EXEC_UNKNOWN_ERROR = -2, + * EXECRA_NO_RA = -1, + * EXECRA_OK = 0, + * EXECRA_UNKNOWN_ERROR = 1, + * EXECRA_INVALID_PARAM = 2, + * EXECRA_UNIMPLEMENT_FEATURE = 3, + * EXECRA_INSUFFICIENT_PRIV = 4, + * EXECRA_NOT_INSTALLED = 5, + * EXECRA_NOT_CONFIGURED = 6, + * EXECRA_NOT_RUNNING = 7, + * + * EXECRA_RA_DEAMON_DEAD1 = 11, + * EXECRA_RA_DEAMON_DEAD2 = 12, + * EXECRA_RA_DEAMON_STOPPED = 13, + * EXECRA_STATUS_UNKNOWN = 14 + * }; + */ + +#ifndef __LRM_API_H +#define __LRM_API_H 1 + +#include <glib.h> +#include <lrm/raexec.h> +#include <clplumbing/GSource.h> + +#define LRM_PROTOCOL_MAJOR 0 +#define LRM_PROTOCOL_MINOR 1 +#define LRM_PROTOCOL_VERSION ((LRM_PROTCOL_MAJOR << 16) | LRM_PROTOCOL_MINOR) + +#define RID_LEN 128 + +/*lrm's client uses this structure to access the resource*/ +typedef struct +{ + char* id; + char* type; + char* class; + char* provider; + GHashTable* params; + struct rsc_ops* ops; +}lrm_rsc_t; + + +/*used in struct lrm_op_t to show how an operation exits*/ +typedef enum { + LRM_OP_PENDING = -1, + LRM_OP_DONE, + LRM_OP_CANCELLED, + LRM_OP_TIMEOUT, + LRM_OP_NOTSUPPORTED, + LRM_OP_ERROR +}op_status_t; + +/*for all timeouts: in milliseconds. 0 for no timeout*/ + +/*this structure is the information of the operation.*/ + +#define EVERYTIME -1 +#define CHANGED -2 + +/* Notice the interval and target_rc + * + * when interval==0, the operation will be executed only once + * when interval>0, the operation will be executed repeatly with the interval + * + * when target_rc==EVERYTIME, the client will be notified every time the + * operation executed. + * when target_rc==CHANGED, the client will be notified when the return code + * is different with the return code of last execute of the operation + * when target_rc is other value, only when the return code is the same of + * target_rc, the client will be notified. + */ + +typedef struct{ + /*input fields*/ + char* op_type; + GHashTable* params; + int timeout; + char* user_data; + int user_data_len; + int interval; + int start_delay; + int copyparams; /* copy parameters to the rsc */ + int target_rc; + + /*output fields*/ + op_status_t op_status; + int rc; + int call_id; + char* output; + char* rsc_id; + char* app_name; + char* fail_reason; + unsigned long t_run; /* when did the op run (as age) */ + unsigned long t_rcchange; /* last rc change (as age) */ + unsigned long exec_time; /* time it took the op to run */ + unsigned long queue_time; /* time spent in queue */ + int rsc_deleted; /* resource just deleted? */ +}lrm_op_t; + +extern const lrm_op_t lrm_zero_op; /* an all-zeroes lrm_op_t value */ + +lrm_op_t* lrm_op_new(void); +void lrm_free_op(lrm_op_t* op); +void lrm_free_rsc(lrm_rsc_t* rsc); +void lrm_free_str_list(GList* list); +void lrm_free_op_list(GList* list); +void lrm_free_str_table(GHashTable* table); + + +/*this enum is used in get_cur_state*/ +typedef enum { + LRM_RSC_IDLE, + LRM_RSC_BUSY +}state_flag_t; + +/* defaults for the asynchronous resource failures */ +enum { DEFAULT_FAIL_RC = EXECRA_UNKNOWN_ERROR }; +#define DEFAULT_FAIL_REASON "asynchronous monitor error" +#define ASYNC_OP_NAME "asyncmon" + +/* in addition to HA_OK and HA_FAIL */ +#define HA_RSCBUSY 2 + +struct rsc_ops +{ +/* + *perform_op: Performs the operation on the resource. + *Notice: op is the operation which need to pass to RA and done asyn + * + *op: the structure of the operation. Caller can create the op by + * lrm_op_new() and release the op using lrm_free_op() + * + *return: All operations will be asynchronous. + * The call will return the call id or failed code immediately. + * The call id will be passed to the callback function + * when the operation finished later. + */ + int (*perform_op) (lrm_rsc_t*, lrm_op_t* op); + + +/* + *cancel_op: cancel the operation on the resource. + * + *callid: the call id returned by perform_op() + * + *return: HA_OK for success, HA_FAIL for failure op not found + * or other failure + * NB: the client always gets a notification over callback + * even for operations which were idle (of course, if + * the request has been accepted for processing) + */ + int (*cancel_op) (lrm_rsc_t*, int call_id); + +/* + *flush_ops: throw away all operations queued for this resource, + * and return them as cancelled. + * + *return: HA_OK for success, HA_FAIL for failure + * NB: op is not flushed unless it is idle; + * in that case this call will block + */ + int (*flush_ops) (lrm_rsc_t*); + +/* + *get_cur_state: + * return the current state of the resource + * + *cur_state: current state of the resource + * + *return: cur_state should be in LRM_RSC_IDLE or LRM_RSC_BUSY. + * and the function returns a list of ops. + * the list includes: + * 1. last ops for each type (start/stop/etc) from current client + * 2. current pending ops + * 3. all recurring ops waiting to execute + * the list is sorted by the call_id of ops. + * client can release the list using lrm_free_op_list() + */ + GList* (*get_cur_state) (lrm_rsc_t*, state_flag_t* cur_state); + +/* + *get_last_result: + * return the last op of given type from current client + * + *op_type: the given type + * + *return: the last op. if there is no such op, return NULL. + * client can release the op using lrm_free_op() + */ + lrm_op_t* (*get_last_result)(lrm_rsc_t*, const char *op_type); +}; + + +/* + *lrm_op_done_callback_t: + * this type of callback functions are called when some + * asynchronous operation is done. + * client can release op by lrm_free_op() + */ +typedef void (*lrm_op_done_callback_t) (lrm_op_t* op); + + +typedef struct ll_lrm +{ + struct lrm_ops* lrm_ops; +}ll_lrm_t; + +struct lrm_ops +{ + int (*signon) (ll_lrm_t*, const char * app_name); + + int (*signoff) (ll_lrm_t*); + + int (*delete) (ll_lrm_t*); + + int (*set_lrm_callback) (ll_lrm_t*, + lrm_op_done_callback_t op_done_callback_func); + +/* + *set_lrmd_param: set lrmd parameter + *get_lrmd_param: get lrmd parameter + * + *return: HA_OK for success, HA_FAIL for failure + * NB: currently used only for max_child_count + */ + int (*set_lrmd_param)(ll_lrm_t*, const char *name, const char *value); + char* (*get_lrmd_param)(ll_lrm_t*, const char *name); + +/* + int (*set_parameters)(ll_lrm_t*, const GHashTable* option); + + GHashTable* (*get_all_parameters)(ll_lrm_t*); + + char * (*get_parameter)(ll_lrm_t *, const char * paramname); + + char * (*get_parameter_description)(ll_lrm_t*); +*/ + +/* + *get_rsc_class_supported: + * Returns the resource classes supported. + * e.g. ocf, heartbeat,lsb... + * + *return: a list of the names of supported resource classes. + * caller can release the list by lrm_free_str_list(). + */ + GList* (*get_rsc_class_supported)(ll_lrm_t*); + +/* + *get_rsc_type_supported: + * Returns the resource types supported of class rsc_class. + * e.g. drdb, apache,IPaddr... + * + *return: a list of the names of supported resource types. + * caller can release the list by lrm_free_str_list(). + */ + GList* (*get_rsc_type_supported)(ll_lrm_t*, const char* rsc_class); + +/* + *get_rsc_provider_supported: + * Returns the provider list of the given resource types + * e.g. heartbeat, failsafe... + * + *rsc_provider: if it is null, the default one will used. + * + *return: a list of the names of supported resource provider. + * caller can release the list by lrm_free_str_list(). + */ + GList* (*get_rsc_provider_supported)(ll_lrm_t*, + const char* rsc_class, const char* rsc_type); + +/* + *get_rsc_type_metadata: + * Returns the metadata of the resource type + * + *rsc_provider: if it is null, the default one will used. + * + *return: the metadata. use g_free() to free. + * + */ + char* (*get_rsc_type_metadata)(ll_lrm_t*, const char* rsc_class, + const char* rsc_type, const char* rsc_provider); + +/* + *get_all_type_metadatas: + * Returns all the metadata of the resource type of the class + * + *return: A GHashtable, the key is the RA type, + * the value is the metadata. + * Now only default RA's metadata will be returned. + * please use lrm_free_str_table() to free the return value. + */ + GHashTable* (*get_all_type_metadata)(ll_lrm_t*, const char* rsc_class); + +/* + *get_all_rscs: + * Returns all resources. + * + *return: a list of id of resources. + * caller can release the list by lrm_free_str_list(). + */ + GList* (*get_all_rscs)(ll_lrm_t*); + + +/* + *get_rsc: Gets one resource pointer by the id + * + *return: the lrm_rsc_t type pointer, NULL for failure + * caller can release the pointer by lrm_free_rsc(). + */ + lrm_rsc_t* (*get_rsc)(ll_lrm_t*, const char* rsc_id); + +/* + *add_rsc: Adds a new resource to lrm. + * lrmd holds nothing when it starts. + * crm or lrmadmin should add resources to lrm using + * this function. + * + *rsc_id: An id which sould be generated by client, + * 128byte(include '\0') UTF8 string + * + *class: the class of the resource + * + *type: the type of the resource. + * + *rsc_provider: if it is null, the default provider will used. + * + *params: the parameters for the resource. + * + *return: HA_OK for success, HA_FAIL for failure + */ + int (*add_rsc)(ll_lrm_t*, const char* rsc_id, const char* class, + const char* type, const char* provider, GHashTable* params); + +/* + *delete_rsc: delete the resource by the rsc_id + * + *return: HA_OK for success, HA_FAIL for failure + * NB: resource removal is delayed until all operations are + * removed; the client, however, gets the reply immediately + */ + int (*delete_rsc)(ll_lrm_t*, const char* rsc_id); + +/* + *fail_rsc: fail a resource + * Allow asynchronous monitor failures. Notifies all clients + * which have operations defined for the resource. + * The fail_rc parameter should be set to one of the OCF + * return codes (if non-positive it defaults to + * OCF_ERR_GENERIC). The fail_reason parameter should + * contain the description of the failure (i.e. "daemon + * panicked" or similar). If NULL is passed or empty string, + * it defaults to "asynchronous monitor failure". + * + *return: HA_OK for success, HA_FAIL for failure + */ + int (*fail_rsc)(ll_lrm_t* lrm, const char* rsc_id, + const int fail_rc, const char* fail_reason); +/* + *ipcchan: Return the IPC channel which can be used for determining + * when messages are ready to be read. + *return: the IPC Channel + */ + + IPC_Channel* (*ipcchan)(ll_lrm_t*); + +/* + *msgready: Returns TRUE (1) when a message is ready to be read. + */ + gboolean (*msgready)(ll_lrm_t*); + +/* + *rcvmsg: Cause the next message to be read - activating callbacks for + * processing the message. If no callback processes the message + * it will be ignored. The message is automatically disposed of. + * + *return: the count of message was received. + */ + int (*rcvmsg)(ll_lrm_t*, int blocking); + +}; + +/* + *ll_lrm_new: + * initializes the lrm client library. + * + *llctype: "lrm" + * + */ +ll_lrm_t* ll_lrm_new(const char * llctype); + +/* + *execra_code2string: + * Translate the return code of the operation to string + * + *code: the rc field in lrm_op_t structure + */ +const char *execra_code2string(uniform_ret_execra_t code); +#endif /* __LRM_API_H */ + diff --git a/include/lrm/lrm_msg.h b/include/lrm/lrm_msg.h new file mode 100644 index 0000000..6f671e1 --- /dev/null +++ b/include/lrm/lrm_msg.h @@ -0,0 +1,160 @@ +/* + * Message Define For Local Resource Manager + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * By Huang Zhen <zhenh@cn.ibm.com> 2004/2/23 + * + */ +/* + * Notice: + *"status" indicates the exit status code of "status" operation + * its value is defined in LSB + *"state" indicates the state of resource, maybe LRM_RSC_BUSY, LRM_RSC_IDLE + *"opstate" indicates how the op exit.like LRM_OP_DONE,LRM_OP_CANCELLED, + * LRM_OP_TIMEOUT,LRM_OP_NOTSUPPORTED. + */ +#ifndef __LRM_MSG_H +#define __LRM_MSG_H 1 + +#include <lrm/lrm_api.h> + +#define LRM_CMDPATH HA_VARRUNDIR"/heartbeat/lrm_cmd_sock" +#define LRM_CALLBACKPATH HA_VARRUNDIR"/heartbeat/lrm_callback_sock" + +/*define the field type used by lrm*/ +#define F_LRM_TYPE "lrm_t" +#define F_LRM_APP "lrm_app" +#define F_LRM_PID "lrm_pid" +#define F_LRM_UID "lrm_uid" +#define F_LRM_GID "lrm_gid" +#define F_LRM_RID "lrm_rid" +#define F_LRM_RTYPE "lrm_rtype" +#define F_LRM_RTYPES "lrm_rtypes" +#define F_LRM_RCLASS "lrm_rclass" +#define F_LRM_RPROVIDER "lrm_rprovider" +#define F_LRM_RPROVIDERS "lrm_rproviders" +#define F_LRM_PARAM "lrm_param" +#define F_LRM_COPYPARAMS "lrm_copyparams" +#define F_LRM_TIMEOUT "lrm_timeout" +#define F_LRM_OP "lrm_op" +#define F_LRM_OPCNT "lrm_opcount" +#define F_LRM_OPSTATUS "lrm_opstatus" +#define F_LRM_RC "lrm_rc" +#define F_LRM_RET "lrm_ret" +#define F_LRM_CALLID "lrm_callid" +#define F_LRM_RCOUNT "lrm_rcount" +#define F_LRM_RIDS "lrm_rids" +#define F_LRM_DATALEN "lrm_datalen" +#define F_LRM_DATA "lrm_data" +#define F_LRM_STATE "lrm_state" +#define F_LRM_INTERVAL "lrm_interval" +#define F_LRM_TARGETRC "lrm_targetrc" +#define F_LRM_LASTRC "lrm_lastrc" +#define F_LRM_STATUS "lrm_status" +#define F_LRM_RSCDELETED "lrm_rscdeleted" +#define F_LRM_METADATA "lrm_metadata" +#define F_LRM_USERDATA "lrm_userdata" +#define F_LRM_DELAY "lrm_delay" +#define F_LRM_T_RUN "lrm_t_run" +#define F_LRM_T_RCCHANGE "lrm_t_rcchange" +#define F_LRM_EXEC_TIME "lrm_exec_time" +#define F_LRM_QUEUE_TIME "lrm_queue_time" +#define F_LRM_FAIL_REASON "lrm_fail_reason" +#define F_LRM_ASYNCMON_RC "lrm_asyncmon_rc" +#define F_LRM_LRMD_PARAM_NAME "lrm_lrmd_param_name" +#define F_LRM_LRMD_PARAM_VAL "lrm_lrmd_param_val" + +#define PRINT printf("file:%s,line:%d\n",__FILE__,__LINE__); + + +/*define the message typs between lrmd and client lib*/ +#define REGISTER "reg" +#define GETRSCCLASSES "rclasses" +#define GETRSCTYPES "rtypes" +#define GETPROVIDERS "rproviders" +#define GETRSCMETA "rmetadata" +#define GETALLRCSES "getall" +#define GETRSC "getrsc" +#define GETLASTOP "getlastop" +#define GETRSCSTATE "getstate" +#define SETMONITOR "setmon" +#define GETMONITORS "getmons" +#define FLUSHRSC "flush" +#define ADDRSC "addrsc" +#define DELRSC "delrsc" +#define FAILRSC "failrsc" +#define PERFORMOP "op" +#define ISOPSUPPORT "opspt" +#define OPDONE "opdone" +#define MONITOR "monitor" +#define RETURN "return" +#define FLUSHOPS "flushops" +#define CANCELOP "cancelop" +#define SETLRMDPARAM "setparam" +#define GETLRMDPARAM "getparam" + +#define MAX_INT_LEN 64 +#define MAX_NAME_LEN 255 +#define MAX_VALUE_LEN 255 +#define MAX_PARAM_LEN 1024 + + +GHashTable* copy_str_table(GHashTable* hash_table); +GHashTable* merge_str_tables(GHashTable* old, GHashTable* new); +void free_str_table(GHashTable* hash_table); + + /* + * message for no parameter, like unreg,types,getall + * they do not include any paramters + */ +struct ha_msg* create_lrm_msg(const char* msg); + +/* + * message for only one parameter - resource id, + * like getrsc,delrsc,flush,getstate,getmons + */ +struct ha_msg* create_lrm_rsc_msg(const char* rid, const char* msg); + +/* register client message */ +struct ha_msg* create_lrm_reg_msg(const char* app_name); + +/* + * add new resource + * according to the opinion of Lars, it is awkward that we combine all + * parameters in to one string. I think so too. So this call may changed soon + */ +struct ha_msg* create_lrm_addrsc_msg(const char* rid, const char* class, + const char* type, const char* provider, GHashTable* parameter); + +/* + * + *the return message from lrmd for reg,unreg,addrsc,delrsc,isopsupport. + *these return messages only include return code. + * + */ +struct ha_msg* create_lrm_ret(int rc, int fields); + + +/* + * the return message for a status change monitoring. + */ + +struct ha_msg* create_rsc_perform_op_msg (const char* rid, lrm_op_t* op); + +#endif /* __LRM_MSG_H */ diff --git a/include/lrm/racommon.h b/include/lrm/racommon.h new file mode 100644 index 0000000..b16aa24 --- /dev/null +++ b/include/lrm/racommon.h @@ -0,0 +1,29 @@ +/* + * Author: Sun Jiang Dong <sunjd@cn.ibm.com> + * Copyright (c) 2004 International Business Machines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RACOMMON_H +#define RACOMMON_H + +void get_ra_pathname(const char* class_path, const char* type, const char* provider, char pathname[]); +gboolean filtered(char * file_name); +int get_runnable_list(const char* class_path, GList ** rsc_info); +int get_failed_exec_rc(void); +void closefiles(void); + +#endif /* RACOMMON_H */ diff --git a/include/lrm/raexec.h b/include/lrm/raexec.h new file mode 100644 index 0000000..0b69831 --- /dev/null +++ b/include/lrm/raexec.h @@ -0,0 +1,157 @@ +/* + * raexec.h: The universal interface of RA Execution Plugin + * + * Author: Sun Jiang Dong <sunjd@cn.ibm.com> + * Copyright (c) 2004 International Business Machines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RAEXEC_H +#define RAEXEC_H +#include <glib.h> +#include <lrm/racommon.h> + +/* Uniform return value of executing RA */ +enum UNIFORM_RET_EXECRA { + EXECRA_EXEC_UNKNOWN_ERROR = -2, + EXECRA_NO_RA = -1, + EXECRA_OK = 0, + EXECRA_UNKNOWN_ERROR = 1, + EXECRA_INVALID_PARAM = 2, + EXECRA_UNIMPLEMENT_FEATURE = 3, + EXECRA_INSUFFICIENT_PRIV = 4, + EXECRA_NOT_INSTALLED = 5, + EXECRA_NOT_CONFIGURED = 6, + EXECRA_NOT_RUNNING = 7, + EXECRA_RUNNING_MASTER = 8, + EXECRA_FAILED_MASTER = 9, + + /* For status command only */ + EXECRA_RA_DEAMON_DEAD1 = 11, + EXECRA_RA_DEAMON_DEAD2 = 12, + EXECRA_RA_DEAMON_STOPPED = 13, + EXECRA_STATUS_UNKNOWN = 14 +}; +typedef enum UNIFORM_RET_EXECRA uniform_ret_execra_t; + +#define RA_MAX_NAME_LENGTH 240 +#define RA_MAX_DIRNAME_LENGTH 200 +#define RA_MAX_BASENAME_LENGTH 40 + +/* + * RA Execution Interfaces + * The plugin usage is divided into two step. First to send out a command to + * execute a resource agent via calling function execra. Execra is a unblock + * function, always return at once. Then to call function post_query_result to + * get the RA exection result. +*/ +struct RAExecOps { + /* + * Description: + * Launch a exection of a resource agent -- normally is a script + * + * Parameters: + * rsc_id: The resource instance id. + * rsc_type: The basename of a RA. + * op_type: The operation that hope RA to do, such as "start", + * "stop" and so on. + * cmd_params: The command line parameters need to be passed to + * the RA for a execution. + * env_params: The enviroment parameters need to be set for + * affecting the action of a RA execution. As for + * OCF style RA, it's the only way to pass + * parameter to the RA. + * + * Return Value: + * 0: RA execution is ok, while the exec_key is a valid value. + * -1: The RA don't exist. + * -2: There are invalid command line parameters. + * -3: Other unkown error when launching the execution. + */ + int (*execra)( + const char * rsc_id, + const char * rsc_type, + const char * provider, + const char * op_type, + const int timeout, + GHashTable * params); + + /* + * Description: + * Map the specific ret value to a uniform value. + * + * Parameters: + * ret_execra: the RA type specific ret value. + * op_type: the operation type + * std_output: the output which the RA write to stdout. + * + * Return Value: + * A uniform value without regarding RA type. + */ + uniform_ret_execra_t (*map_ra_retvalue)( + int ret_execra + , const char * op_type + , const char * std_output); + + /* + * Description: + * List all resource info of this class + * + * Parameters: + * rsc_info: a GList which item data type is rsc_info_t as + * defined above, containing all resource info of + * this class in the local machine. + * + * Return Value: + * >=0 : succeed. the RA type number of this RA class + * -1: failed due to invalid RA directory such as not existing. + * -2: failed due to other factors + */ + int (*get_resource_list)(GList ** rsc_info); + + /* + * Description: + * List all providers of this type + * + * Parameters: + * providers: a GList which item data type is string. + * the name of providers of the resource agent + * + * Return Value: + * >=0 : succeed. the provider number of this RA + * -1: failed due to invalid RA directory such as not existing. + * -2: failed due to other factors + */ + int (*get_provider_list)(const char* ra_type, GList ** providers); + + /* + * Description: + * List the metadata of the resource agent this class + * + * Parameters: + * rsc_type: the type of the ra + * + * Return Value: + * !NULL : succeed. the RA metadata. + * NULL: failed + */ + char* (*get_resource_meta)(const char* rsc_type, const char* provider); +}; + +#define RA_EXEC_TYPE RAExec +#define RA_EXEC_TYPE_S "RAExec" + +#endif /* RAEXEC_H */ diff --git a/include/pils/Makefile.am b/include/pils/Makefile.am new file mode 100644 index 0000000..4b6c6a0 --- /dev/null +++ b/include/pils/Makefile.am @@ -0,0 +1,25 @@ +# +# linux-ha: Linux-HA heartbeat code +# +# Copyright (C) 2001 Michael Moerz +# This instance created by Horms +# +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +MAINTAINERCLEANFILES = Makefile.in + +idir=$(includedir)/pils + +i_HEADERS = generic.h interface.h plugin.h diff --git a/include/pils/generic.h b/include/pils/generic.h new file mode 100644 index 0000000..83bf3e3 --- /dev/null +++ b/include/pils/generic.h @@ -0,0 +1,118 @@ +#ifndef PILS_GENERIC_H +#define PILS_GENERIC_H +/* + * Copyright (C) 2000 Alan Robertson <alanr@unix.sh> + * This software licensed under the GNU LGPL. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Generic interface (implementation) manager + * + * This manager will manage any number of types of interfaces. + * + * This means that when any implementations of our client interfaces register + * or unregister, it is us that makes their interfaces show up in the outside + * world. + * + * And, of course, we have to do this in a very generic way, since we have + * no idea about the client programs or interface types, or anything else. + * + * We do that by getting a parameter passed to us which tell us the names + * of the interface types we want to manage, and the address of a GHashTable + * for each type that we put the implementation in when they register + * themselves. + * + * So, each type of interface that we manage gets its own private + * GHashTable of the implementations of that type that are currently + * registered. + * + * For example, if we manage communication modules, their exported + * interfaces will be registered in a hash table. If we manage + * authentication modules, they'll have their (separate) hash table that + * their exported interfaces are registered in. + * + */ +#include <pils/interface.h> + +/* + * Header defintions for using the generic interface/implementation + * manager plugin. + */ + +/* + * Notification types for the callback function. + */ +typedef enum { + PIL_REGISTER, /* Someone has registered an implementation */ + PIL_UNREGISTER /* Someone has unregistered an implementation */ +}GenericPILCallbackType; + +/* A user callback for the generic interface manager */ +typedef int (*GenericPILCallback) +( GenericPILCallbackType type /* Event type */ +, PILPluginUniv* univ /* pointer to plugin universe */ +, const char * iftype /* Interface type */ +, const char * ifname /* Implementation (interface) name */ +, void * userptr /* Whatever you want it to be ;-) */ +); + +/* + * Structures to declare the set of interface types we're managing. + */ +typedef struct { + const char * iftype; /* What type of interface is this? */ + GHashTable** ifmap; /* Table with implementation info */ + void* importfuns; /* Functions for interface to import */ + GenericPILCallback callback; /* Function2call when events occur */ + void* userptr; /* Passed to Callback function */ +}PILGenericIfMgmtRqst; +/* + * What does this look like in practice? + * + * GHashTable* authmodules = NULL; + * GHashTable* commmodules = NULL; + * PILGenericIfMgmtRqst RegisterRequests[] = + * { + * {"auth", &authmodules, &authimports, NULL, NULL}, + * {"comm", &commmodules, &commimports, NULL, NULL}, + * {NULL, NULL, NULL, NULL, NULL} + // NULL entry must be here + * }; + * + * PILPlugin* PluginUniverse; + * + * PluginUniverse = NewPILPlugin("/usr/lib/whatever/plugins"); + * + * PILLoadPlugin(PluginUniverse, "InterfaceMgr", "generic", &RegisterRequests); + * // N. B.: Passing RegisterRequests as an argument is essential + * + * Then, when you load an auth module, its exported interface gets added + * to "authmodules". When you unload an auth module, it gets removed + * from authmodules. + * + * Then, when you load a comm module, its exported interfaces gets added + * to "commodules". When you unload a comm module, its exported + * interfaces get removed from "commodules" + * + * If there are simple changes that would be useful for this generic + * plugin manager, then "patches are being accepted" :-) + * + * On the other hand, If you don't like the way this plugin manager works + * in a broader way, you're free to write your own - it's just another + * plugin ;-) + */ +#endif diff --git a/include/pils/interface.h b/include/pils/interface.h new file mode 100644 index 0000000..5a5114e --- /dev/null +++ b/include/pils/interface.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2000 Alan Robertson <alanr@unix.sh> + * This software licensed under the GNU LGPL. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef PILS_INTERFACE_H +# define PILS_INTERFACE_H +# ifndef PILS_PLUGIN_H +# include <pils/plugin.h> +# endif + +/***************************************************************************** + * + * The most basic interface type is the "IFManager" interface. + * Each interface manager registers and deals with interfaces of a given type. + * + * Such an interface must be loaded before any plugins of it's type can + * be loaded. + * + * In order to register any plugin of type "foo", we must load a interface of + * type "Interface" named "foo". This interface then manages the + * registration of all interfaces of type foo. + * + * To bootstrap, we load a interface of type "Interface" named "Interface" + * during the initialization of the plugin system. + * + * IFManagers will be autoloaded if certain conditions are met... + * + * If a IFManager is to be autoloaded, there must be one interface manager + * per file, and the file must be named according to the type of the + * interface it implements, and loaded in the directory named PI_IFMANAGER + * ("Interface"). + * + */ + + +/* + * I'm unsure exactly which of the following structures + * are needed to write a interface, or a interface manager. + * We'll get that figured out and scope the defintions accordingly... + */ + +/* + * PILInterface (AKA struct PILInterface_s) holds the information + * we use to track a single interface manager. + */ + + +struct PILInterface_s { + unsigned long MagicNum; + PILInterfaceType* interfacetype; /* Parent pointer */ + char * interfacename; /* malloced interface name */ + PILInterface* ifmanager; /* plugin managing us */ + void* exports; /* Exported Functions */ + /* for this interface */ + PILInterfaceFun if_close; /* Interface close operation*/ + void* ud_interface; /* per-interface user data */ + int refcnt; /* Ref count for plugin */ + PILPlugin* loadingpi; /* Plugin that loaded us */ +}; +/* + * PILInterfaceType (AKA struct PILInterfaceType_s) holds the info + * we use to track the set of all interfaces of a single kind. + */ +struct PILInterfaceType_s { + unsigned long MagicNum; + char* typename; /* Our interface type name */ + GHashTable* interfaces; /* The set of interfaces + * of our type. The + * "values" are all + * PILInterface * objects + */ + void* ud_if_type; /* per-interface-type user + data*/ + PILInterfaceUniv* universe; /* Pointer to parent (up) */ + PILInterface* ifmgr_ref; /* Pointer to our interface + manager */ +}; + +/* + * PILInterfaceUniv (AKA struct PILInterfaceUniv_s) holds the information + * for all interfaces of all types. From our point of view this is + * our universe ;-) + */ + +struct PILInterfaceUniv_s{ + unsigned long MagicNum; + GHashTable* iftypes; /* + * Set of Interface Types + * The values are all + * PILInterfaceType objects + */ + struct PILPluginUniv_s* piuniv; /* parallel universe of + * plugins + */ +}; + +#ifdef ENABLE_PLUGIN_MANAGER_PRIVATE +/* + * From here to the end is specific to interface managers. + * This data is only needed by interface managers, and the interface + * management system itself. + * + */ +typedef struct PILInterfaceOps_s PILInterfaceOps; + + +/* Interfaces imported by a IFManager interface */ +struct PILInterfaceImports_s { + + /* Return current reference count */ + int (*RefCount)(PILInterface * eifinfo); + + /* Incr/Decr reference count */ + int (*ModRefCount)(PILInterface*eifinfo, int plusminus); + + /* Unregister us as a interface */ + void (*ForceUnRegister)(PILInterface *eifinfo); + + /* For each client */ + void (*ForEachClientDel)(PILInterface* manangerif + , gboolean(*f)(PILInterface* clientif, void * other) + , void* other); + +}; + +/* Interfaces exported by an InterfaceManager interface */ +struct PILInterfaceOps_s{ +/* + * These are the interfaces exported by an InterfaceManager to the + * interface management infrastructure. These are not imported + * by interfaces - only the interface management infrastructure. + */ + + /* RegisterInterface - register this interface */ + PIL_rc (*RegisterInterface)(PILInterface* newif + , void** imports); + + PIL_rc (*UnRegisterInterface)(PILInterface*ifinfo); /* Unregister IF*/ + /* And destroy PILInterface object */ +}; + +#endif /* ENABLE_PLUGIN_MANAGER_PRIVATE */ +#endif /* PILS_INTERFACE_H */ diff --git a/include/pils/plugin.h.in b/include/pils/plugin.h.in new file mode 100644 index 0000000..cb67d91 --- /dev/null +++ b/include/pils/plugin.h.in @@ -0,0 +1,736 @@ +/* + * Copyright (C) 2000 Alan Robertson <alanr@unix.sh> + * This software licensed under the GNU LGPL. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef PILS_PLUGIN_H +# define PILS_PLUGIN_H +# include <ltdl.h> +# include <glue_config.h> + +/* Glib headers generate warnings - so we make them go away */ + +#define time FOOtime +#define index FOOindex +#include <glib.h> +#undef index +#undef time + +/***************************************************************************** + * PILS - Universal Plugin and Interface loading system + ***************************************************************************** + * + * An Overview of PILS... + * + * PILS is fairly general and reasonably interesting plugin loading system. + * We manage both plugins and their interfaces + * + * This plugin / interface management system is quite general, and should be + * directly usable by basically any project on any platform on which it runs + * - which should be many, since everything is build with automake + * and libtool. + * + * Some terminology... + * + * There are two basic kinds of objects we deal with here: + * + * Plugins: dynamically loaded chunks of code which implement one or more + * interfaces. The system treats all plugins as the same. + * In UNIX, these are dynamically loaded ".so" files. + * + * Interface: A set of functions which implement a particular capability + * (or interface) + * Generally interfaces are registered as part of a plugin. + * The system treats all interfaces of the same type the same. + * It is common to have exactly one interface inside of each plugin. + * In this case, the interface name should match the plugin name. + * + * Each interface implementation exports certain functions for its clients + * to use. We refer to these those "Ops". Every interface of the same type + * "imports" the same interfaces from its interface manager, + * and exports the same "Ops". + * + * Each interface implementation is provided certain interfaces which it + * imports when it from its interface manager when it is registered. + * We refer to these as "Imports". Every interface of a given type + * imports the same interfaces. + * + * The story with plugins is a little different... + * + * Every plugin exports a certain set of interfaces, regardless of what type + * of interfaces is implemented by it. These are described in the + * PILPluginOps structure. + * + * Every plugin imports a certain set of interfaces, regardless of what type + * of interfaces it may implement. These are described by the + * PILPluginImports structure. + * + * In the function parameters below, the following notation will + * sometimes appear: + * + * (OP) == Output Parameter - a parameter which is modified by the + * function being called + * + * + ***************************************************************************** + * + * The basic structures we maintain about plugins are as follows: + * + * PILPlugin The data which represents a plugin. + * PILPluginType The data common to all plugins of a given type + * PILPluginUniv The set of all plugin types in the Universe + * (well... at least *this* universe) + * + * The basic structures we maintain about interfaces are as follows: + * PILInterface The data which represents a interface + * PILInterfaceType The data which is common to all + * interfaces of a given type + * PILPluginUniv The set of all interface types in the Universe + * (well... at least *this* universe) + * + * Regarding "Universe"s. It is our intent that a given program can deal + * with plugins in more than one universe. This might occur if you have two + * independent libraries each of which uses the plugin loading environment + * to manage their own independent interface components. There should be + * no restriction in creating a program which uses both of these libraries. + * At least that's what we hope ;-) + * + * + *************************************************************************** + * SOME MORE DETAILS ABOUT PLUGINS... + *************************************************************************** + * + * Going back to more detailed data structures about plugins... + * + * PILPluginImports The set of standard functions all plugins + * import. + * This includes: + * register_plugin() + * unregister_plugin() + * register_interface() + * unregister_interface() + * load_plugin() + * log() Preferred logging function + * + * PILPluginOps The set of standard operations all plugins + * export. + * This includes: + * pluginversion() + * pluginname() + * getdebuglevel() + * setdebuglevel() + * close() Prepare for unloading... + * + * Although we treat plugins pretty much the same, they are still + * categorized into "types" - one type per directory. These types + * generally correspond to interface types. + * + * One can only cause a plugin to be loaded - not a interface. But it is + * common to assume that loading a plugin named foo of type bar will + * cause a interface named foo of type bar to be registered. If one + * wants to implement automatic plugin loading in a given interface type, + * this assumption is necessary. + * + * The general way this works is... + * + * - A request is made to load a particular plugin of a particular type. + * + * - The plugin is loaded from the appropriate directory for plugins + * of that type. + * + * - The ml_plugin_init() function is called once when the plugin is + * loaded. + * + * The ml_plugin_init() function is passed a vector of functions which + * point to functions it can call to register itself, etc. + * (it's of type PILPluginImports) + * + * The ml_plugin_init function then uses this set of imported functions + * to register itself and its interfaces. + * + * The mechanism of registering a interface is largely the same for + * every interface. However, the semantics of registering a interfaces + * is determined by the interface manager for the particular type of + * interface being discussed. + * + *************************************************************************** + * SOME MORE DETAILS ABOUT PLUGINS... + *************************************************************************** + * + * There is only one built in type of interface. That's the Interface + * manager interface. + * The interface manager for the interface of type "InterfaceMgr", + * named "InterfaceMgr" inserts itself into the system in order + * to bootstrap things... + * + * When an attempt is made to register a interface of an unknown type, + * then the appropriate Interface manager is loaded automatically. + * + * The name of an interface manager determines the type of + * interface it manages. + * + * It handles requests for interfaces whose type is the same + * as its interface name. If the interface manager's interface name + * is foo, then it is the interface manager for all interfaces whose + * type is foo. + * + * Types associated with interfaces of type Interface + * + * PILInterfaceOps The set of interfaces that every interface + * manager exports + * PILInterfaceImports The set of interfaces which are supplied to + * (imported by) every interface of type + * Interface. (that is, every interface + * manager). + * + ***************************************************************************** + * + * Each plugin has only one entry point which is exported directly, regardless + * of what kind of interface(s) it may implement... + * + * This entrypoint is named ml_plugin_init() {more or less - see below} + * + * The ml_plugin_init() function is called once when the plugin is loaded. + * + * + * All other function pointers are registered (exported) through parameters + * passed to ml_plugin_init() + * + * It is the purpose of the Ml_plugin_init() to register the plugin, + * and all the interfaces which this plugin implements. A pointer to + * the registration function is in the parameters which are passed + * to ml_plugin_init(). + * + ***************************************************************************** + * + * THINGS IN THIS DESIGN WHICH ARE PROBABLY BROKEN... + * + * It may also be the case that the plugin loading environment needs + * to be able to have some kind of user_data passed to it which it can + * also pass along to any interface ... + * + * Maybe this should be handled by a sort of global user_data registration + * structure, so globals can be passed to interfaces when they're registered. + * + * A sort of "user_data" registry. One for each interface type and one + * for each interface... Or maybe it could be even more flexible... + * + * This is all so that these nice pristene, beautiful concepts can come out + * and work well in the real world where interfaces need to interact with + * some kind of global system view, and with each other... + * + * Probably need some better way of managing interface versions, etc. + * + **************************************************************************** + */ + +/* + * If you want to use this funky export stuff, then you need to #define + * PIL_PLUGINTYPE and PIL_PLUGIN *before* including this file. + * + * The way to use this stuff is to declare your primary entry point this way: + * + * This example is for an plugin of type "auth" named "sha1" + * + * #define PIL_PLUGINTYPE auth + * #define PIL_PLUGIN sha1 + * #include <upmls/PILPlugin.h> + * + * static const char* Ourpluginversion (void); + * static const char* Ourpluginname (void); + * static int Ourgetdebuglevel(void); + * static void Oursetdebuglevel(int); + * static void Ourclose (PILPlugin*); + * + * static struct PILPluginOps our_exported_plugin_operations = + * { Ourpluginversion, + * , Ourpluginname + * , Ourgetdebuglevel + * , Oursetdebuglevel + * , Ourclose + * }; + * + * static const PILPluginImports* PluginOps; + * static PILPlugin* OurPlugin; + * + * // Our plugin initialization and registration function + * // It gets called when the plugin gets loaded. + * PIL_rc + * PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports) + * { + * PluginOps = imports; + * OurPlugin = us; + * + * // Register ourself as a plugin * / + * imports->register_plugin(us, &our_exported_plugin_operations); + * + * // Register our interfaces + * imports->register_interface(us, "interfacetype", "interfacename" + * // Be sure and define "OurExports" and OurImports + * // above... + * , &OurExports + * , &OurImports); + * // Repeat for all interfaces in this plugin... + * + * } + * + * Except for the PIL_PLUGINTYPE and the PIL_PLUGIN definitions, and changing + * the names of various static variables and functions, every single plugin is + * set up pretty much the same way + * + */ + +/* + * No doubt there is a fancy preprocessor trick for avoiding these + * duplications but I don't have time to figure it out. Patches are + * being accepted... + */ +#define mlINIT_FUNC _pil_plugin_init +#define mlINIT_FUNC_STR "_pil_plugin_init" +#define PIL_INSERT _LTX_ +#define PIL_INSERT_STR "_LTX_" + +/* + * snprintf-style format string for initialization entry point name: + * arguments are: (plugintype, pluginname) + */ +#define PIL_FUNC_FMT "%s" PIL_INSERT_STR "%s" mlINIT_FUNC_STR + +#ifdef __STDC__ +# define EXPORTHELPER1(plugintype, insert, pluginname, function) \ + plugintype##insert##pluginname##function +#else +# define EXPORTHELPER1(plugintype, insert, pluginname, function) \ + plugintype/**/insert/**/pluginname/**/function +#endif + +#define EXPORTHELPER2(a, b, c, d) EXPORTHELPER1(a, b, c, d) +#define PIL_PLUGIN_INIT \ + EXPORTHELPER2(PIL_PLUGINTYPE,PIL_INSERT,PIL_PLUGIN,mlINIT_FUNC) + +/* + * Plugin loading return codes. OK will always be zero. + * + * There are many ways to fail, but only one kind of success ;-) + */ + +typedef enum { + PIL_OK=0, /* Success */ + PIL_INVAL=1, /* Invalid Parameters */ + PIL_BADTYPE=2, /* Bad plugin/interface type */ + PIL_EXIST=3, /* Duplicate Plugin/Interface name */ + PIL_OOPS=4, /* Internal Error */ + PIL_NOPLUGIN=5 /* No such plugin or Interface */ +}PIL_rc; /* Return code from Plugin fns*/ + +const char * PIL_strerror(PIL_rc rc); + +typedef struct PILPluginImports_s PILPluginImports; +typedef struct PILPluginOps_s PILPluginOps; +typedef struct PILPlugin_s PILPlugin; +typedef struct PILPluginUniv_s PILPluginUniv; +typedef struct PILPluginType_s PILPluginType; + +typedef struct PILInterface_s PILInterface; +typedef struct PILInterfaceImports_s PILInterfaceImports; +typedef struct PILInterfaceUniv_s PILInterfaceUniv; +typedef struct PILInterfaceType_s PILInterfaceType; + +typedef PIL_rc(*PILInterfaceFun)(PILInterface*, void* ud_interface); + +#define PIL_MAGIC_PLUGIN 0xFEEDBEEFUL +#define PIL_MAGIC_PLUGINTYPE 0xFEEDCEEFUL +#define PIL_MAGIC_PLUGINUNIV 0xFEEDDEEFUL +#define PIL_MAGIC_INTERFACE 0xFEEDEEEFUL +#define PIL_MAGIC_INTERFACETYPE 0xFEEDFEEFUL +#define PIL_MAGIC_INTERFACEUNIV 0xFEED0EEFUL + +#define IS_PILPLUGIN(s) ((s)->MagicNum == PIL_MAGIC_PLUGIN) +#define IS_PILPLUGINTYPE(s) ((s)->MagicNum == PIL_MAGIC_PLUGINTYPE) +#define IS_PILPLUGINUNIV(s) ((s)->MagicNum == PIL_MAGIC_PLUGINUNIV) +#define IS_PILINTERFACE(s) ((s)->MagicNum == PIL_MAGIC_INTERFACE) +#define IS_PILINTERFACETYPE(s) ((s)->MagicNum == PIL_MAGIC_INTERFACETYPE) +#define IS_PILINTERFACEUNIV(s) ((s)->MagicNum == PIL_MAGIC_INTERFACEUNIV) + +/* The type of a Plugin Initialization Function */ +typedef PIL_rc (*PILPluginInitFun) (PILPlugin*us +, PILPluginImports* imports +, void* plugin_user_data); + +/* + * struct PILPluginOps_s (typedef PILPluginOps) defines the set of functions + * exported by all plugins... + */ +struct PILPluginOps_s { + const char* (*pluginversion) (void); + int (*getdebuglevel) (void); + void (*setdebuglevel) (int); + const char* (*license) (void); + const char* (*licenseurl) (void); + void (*close) (PILPlugin*); +}; + +/* + * Logging levels for the "standard" log interface. + */ + +typedef enum { + PIL_FATAL= 1, /* BOOM! Causes program to stop */ + PIL_CRIT = 2, /* Critical -- serious error */ + PIL_WARN = 3, /* Warning */ + PIL_INFO = 4, /* Informative message */ + PIL_DEBUG= 5 /* Debug message */ +}PILLogLevel; +typedef void (*PILLogFun)(PILLogLevel priority, const char * fmt, ...) + G_GNUC_PRINTF(2,3); + +/* + * The size glib2 type du jour? + * (once, this used to be size_t, so this change could break + * distributions with older glib2 versions; if so, just add an + * #ifelse below) + */ +#if GLIB_MINOR_VERSION <= 14 + typedef gulong glib_size_t; +#else + typedef gsize glib_size_t; +#endif + +/* + * struct PILPluginImports_s (typedef PILPluginImports) defines + * the functions and capabilities that every plugin imports when it is loaded. + */ + + +struct PILPluginImports_s { + PIL_rc (*register_plugin)(PILPlugin* piinfo + , const PILPluginOps* commonops); + PIL_rc (*unregister_plugin)(PILPlugin* piinfo); +/* + * A little explanation of the close_func parameter to register_interface + * is in order. + * + * It is an exported operation function, just like the Ops structure. + * However, the Ops vector is exported to applications that + * are using the interface. Unlike the Ops structure, close_func is + * exported only to the interface system, since applications shouldn't + * call it directly, but should manage the reference counts for the + * interfaces instead. + * The generic interface system doesn't have any idea how to call + * any functions in the operations vector. So, it's a separate + * parameter for two good reasons. + */ + PIL_rc (*register_interface)(PILPlugin* piinfo + , const char * interfacetype /* Type of interface */ + , const char * interfacename /* Name of interface */ + , void* Ops /* Info (functions) exported + by this interface */ + /* Function to call to shut down this interface */ + , PILInterfaceFun close_func + + , PILInterface** interfaceid /* Interface id (OP) */ + , void** Imports + , void* ud_interface); /* interface user data */ + + PIL_rc (*unregister_interface)(PILInterface* interfaceid); + PIL_rc (*load_plugin)(PILPluginUniv* universe + , const char * plugintype, const char * pluginname + , void* plugin_private); + + void (*log) (PILLogLevel priority, const char * fmt, ...) + G_GNUC_PRINTF(2,3); + gpointer (*alloc)(glib_size_t size); + gpointer (*mrealloc)(gpointer space, glib_size_t size); + void (*mfree)(gpointer space); + char* (*mstrdup)(const char *s); +}; + +/* + * Function for logging with the given logging function + * The reason why it's here is so we can get printf arg checking + * You can't get that when you call a function pointer directly. + */ +void PILCallLog(PILLogFun logfun, PILLogLevel priority, const char * fmt, ...) + G_GNUC_PRINTF(3,4); + +/* + * EXPORTED INTERFACES... + */ + +/* Create a new plugin universe - start the plugin loading system up */ +PILPluginUniv* NewPILPluginUniv(const char * baseplugindirectory); + +/* Change memory allocation functions right after creating universe */ +void PilPluginUnivSetMemalloc(PILPluginUniv* +, gpointer (*alloc)(glib_size_t size) +, gpointer (*mrealloc)(gpointer, glib_size_t size) +, void (*mfree)(void* space) +, char* (*mstrdup)(const char *s)); + + +void PilPluginUnivSetLog(PILPluginUniv* +, void (*log) (PILLogLevel priority, const char * fmt, ...) + G_GNUC_PRINTF(2,3)); + + +/* Delete a plugin universe - shut the plugin loading system down */ +/* Best if used carefully ;-) */ +void DelPILPluginUniv(PILPluginUniv*); + +/* Set the debug level for the plugin system itself */ +void PILpisysSetDebugLevel (int level); + +/* Return a list of plugins of the given type */ +char ** PILListPlugins(PILPluginUniv* u, const char *plugintype +, int* plugincount /*can be NULL*/); + +/* Free the plugin list returned by PILFreeListPlugins */ +void PILFreePluginList(char ** pluginlist); + +/* Load the requested plugin */ +PIL_rc PILLoadPlugin(PILPluginUniv* piuniv +, const char * plugintype +, const char * pluginname +, void * pi_private); + +/* Return PIL_OK if the given plugin exists */ +PIL_rc PILPluginExists(PILPluginUniv* piuniv +, const char * plugintype +, const char * pluginname); + +/* Either or both of pitype and piname may be NULL */ +void PILSetDebugLevel(PILPluginUniv*u, const char * pitype +, const char * piname +, int level); + +/* Neither pitype nor piname may be NULL */ +int PILGetDebugLevel(PILPluginUniv* u, const char * pitype +, const char * piname); + +PIL_rc PILIncrIFRefCount(PILPluginUniv* piuniv +, const char * interfacetype +, const char * interfacename +, int plusminus); + +int PILGetIFRefCount(PILPluginUniv* piuniv +, const char * interfacetype +, const char * interfacename); + +void PILLogMemStats(void); +/* The plugin/interface type of a interface manager */ + +#define PI_IFMANAGER "InterfaceMgr" +#define PI_IFMANAGER_TYPE InterfaceMgr + +/* + * These functions are standard exported functions for all plugins. + */ + +#define PIL_PLUGIN_BOILERPLATE_PROTOTYPES_GENERIC(PluginVersion, DebugName) \ +/* \ + * Prototypes for boilerplate functions \ + */ \ +static const char* Ourpluginversion(void); \ +static int GetOurDebugLevel(void); \ +static void SetOurDebugLevel(int); \ +static const char * ReturnOurLicense(void); \ +static const char * ReturnOurLicenseURL(void); + +#define PIL_PLUGIN_BOILERPLATE_FUNCS(PluginVersion, DebugName) \ +/* \ + * Definitions of boilerplate functions \ + */ \ +static const char* \ +Ourpluginversion(void) \ +{ return PluginVersion; } \ + \ +static int DebugName = 0; \ + \ +static int \ +GetOurDebugLevel(void) \ +{ return DebugName; } \ + \ +static void \ +SetOurDebugLevel(int level) \ +{ DebugName = level; } \ + \ +static const char * \ +ReturnOurLicense(void) \ +{ return PIL_PLUGINLICENSE; } \ + \ +static const char * \ +ReturnOurLicenseURL(void) \ +{ return PIL_PLUGINLICENSEURL; } + +#define PIL_PLUGIN_BOILERPLATE(PluginVersion, DebugName, CloseName) \ +PIL_PLUGIN_BOILERPLATE_PROTOTYPES_GENERIC(PluginVersion, DebugName) \ +static void CloseName(PILPlugin*); \ +/* \ + * Initialize Plugin Exports structure \ + */ \ +static PILPluginOps OurPIExports = \ +{ Ourpluginversion \ +, GetOurDebugLevel \ +, SetOurDebugLevel \ +, ReturnOurLicense \ +, ReturnOurLicenseURL \ +, CloseName \ +}; \ +PIL_PLUGIN_BOILERPLATE_FUNCS(PluginVersion, DebugName) + +#define PIL_PLUGIN_BOILERPLATE2(PluginVersion, DebugName) \ +PIL_PLUGIN_BOILERPLATE_PROTOTYPES_GENERIC(PluginVersion, DebugName) \ +/* \ + * Initialize Plugin Exports structure \ + */ \ +static PILPluginOps OurPIExports = \ +{ Ourpluginversion \ +, GetOurDebugLevel \ +, SetOurDebugLevel \ +, ReturnOurLicense \ +, ReturnOurLicenseURL \ +, NULL \ +}; \ +PIL_PLUGIN_BOILERPLATE_FUNCS(PluginVersion, DebugName) + + +/* A few sample licenses and URLs. We can easily add to this */ + +#define LICENSE_GPL "gpl" +#define URL_GPL "http://www.fsf.org/licenses/gpl.html" + +#define LICENSE_LGPL "lgpl" +#define URL_LGPL "http://www.fsf.org/licenses/lgpl.html" + +#define LICENSE_X11 "x11" +#define URL_X11 "http://www.x.org/terms.htm" + +#define LICENSE_PUBDOM "publicdomain" +#define URL_PUBDOM "file:///dev/null" + +#define LICENSE_MODBSD "modbsd" +#define URL_MODBSD "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5" + +#define LICENSE_OLDBSD "origbsd" +#define URL_OLDBSD "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#6" + +#define LICENSE_EXPAT "expat" +#define URL_EXPAT "http://www.jclark.com/xml/copying.txt" + +#define LICENSE_ZLIB "zlib" +#define URL_ZLIB "http://www.gzip.org/zlib/zlib_license.html" + +#define LICENSE_APACHE_10 "apache1_0" +#define URL_APACHE_10 "http://www.apache.org/LICENSE-1.0" + +#define LICENSE_APACHE_11 "apache1_1" +#define URL_APACHE_11 "http://www.apache.org/LICENSE-1.1" + +#define LICENSE_MPL "mpl" +#define URL_MPL "http://www.mozilla.org/MPL/MPL-1.1.html" + +#define LICENSE_PROP "proprietary" +#define URL_PROP "" + +#define LICENSE_IBMPL "ibmpl" +#define URL_IBMPL "http://oss.software.ibm.com/developerworks/opensource/license10.html" + +#ifdef ENABLE_PIL_DEFS_PRIVATE +/* Perhaps these should be moved to a different header file */ + +/* + * PILPluginType is the "class" for the basic plugin loading mechanism. + * + * To enable loading of plugins from a particular plugin type + * one calls NewPILPluginType with the plugin type name, the plugin + * base directory, and the set of functions to be imported to the plugin. + * + * + * The general idea of these structures is as follows: + * + * The PILPluginUniv object contains information about all plugins of + * all types. + * + * The PILPluginType object contains information about all the plugins of a + * specific type. + * + * Note: for plugins which implement a single interface, the plugin type name + * should be the same as the interface type name. + * + * For other plugins that implement more than one interface, one of + * the interface names should normally match the plugin name. + */ + + +/* + * struct PILPlugin_s (typedef PILPlugin) is the structure which + * represents/defines a plugin, and is used to identify which plugin is + * being referred to in various function calls. + * + * NOTE: It may be the case that this definition should be moved to + * another header file - since no one ought to be messing with them anyway ;-) + * + * I'm not sure that we're putting the right stuff in here, either... + */ + +struct PILPlugin_s { + unsigned long MagicNum; + char* plugin_name; + PILPluginType* plugintype; /* Parent structure */ + int refcnt; /* Reference count for this plugin */ + lt_dlhandle dlhandle; /* Reference to D.L. object */ + PILPluginInitFun dlinitfun; /* Initialization function */ + const PILPluginOps* pluginops; /* Exported plugin operations */ + + void* ud_plugin; /* Plugin-Private data */ + /* Other stuff goes here ... (?) */ +}; + +/* + * PILPluginType Information about all plugins of a given type. + * (i.e., in a given directory) + * (AKA struct PILPluginType_s) + */ + +struct PILPluginType_s { + unsigned long MagicNum; + char * plugintype; + PILPluginUniv* piuniv; /* The universe to which we belong */ + GHashTable* Plugins; + /* Key is plugin type, value is PILPlugin */ + + char** (*listplugins)(PILPluginType*, int* listlen); +}; + +/* + * PILPluginUniv (aka struct PILPluginUniv_s) is the structure which + * represents the universe of all PILPluginType objects. + * There is one PILPluginType object for each Plugin type. + */ + +struct PILPluginUniv_s { + unsigned long MagicNum; + char ** rootdirlist; + /* key is plugin type, data is PILPluginType* */ + GHashTable* PluginTypes; + struct PILInterfaceUniv_s*ifuniv; /* Universe of interfaces */ + PILPluginImports* imports; +}; + +# endif /* ENABLE_PIL_DEFS_PRIVATE */ +#endif /*PILS_PLUGIN_H */ diff --git a/include/replace_uuid.h b/include/replace_uuid.h new file mode 100644 index 0000000..d6bca89 --- /dev/null +++ b/include/replace_uuid.h @@ -0,0 +1,50 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * uuid: wrapper declarations. + * + * heartbeat originally used "uuid" functionality by calling directly, + * and only, onto the "e2fsprogs" implementation. + * + * The run-time usages in the code have since been abstracted, funnelled + * through a thin, common interface layer: a Good Thing. + * + * Similarly, the compile-time usages of "include <uuid/uuid.h>" are + * replaced, being funnelled through a reference to this header file. + * + * This header file interfaces onto the actual underlying implementation. + * In the case of the "e2fsprogs" implementation, it is simply a stepping + * stone onto "<uuid/uuid.h>". As other implementations are accommodated, + * so their header requirements can be accommodated here. + * + * Copyright (C) 2004 David Lee <t.d.lee@durham.ac.uk> + */ + +#ifndef REPLACE_UUID_H +#define REPLACE_UUID_H + +typedef unsigned char uuid_t[16]; +void uuid_clear(uuid_t uu); +int uuid_compare(const uuid_t uu1, const uuid_t uu2); +void uuid_copy(uuid_t dst, const uuid_t src); +void uuid_generate(uuid_t out); +void uuid_generate_random(uuid_t out); +int uuid_is_null(const uuid_t uu); +int uuid_parse(const char *in, uuid_t uu); +void uuid_unparse(const uuid_t uu, char *out); + +#endif /* REPLACE_UUID_H */ diff --git a/include/stonith/Makefile.am b/include/stonith/Makefile.am new file mode 100644 index 0000000..9e67a2a --- /dev/null +++ b/include/stonith/Makefile.am @@ -0,0 +1,25 @@ +# +# linux-ha: Linux-HA heartbeat code +# +# Copyright (C) 2001 Michael Moerz +# This instance created by Horms +# +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +MAINTAINERCLEANFILES = Makefile.in + +idir=$(includedir)/stonith + +i_HEADERS = expect.h stonith.h stonith_plugin.h st_ttylock.h diff --git a/include/stonith/expect.h b/include/stonith/expect.h new file mode 100644 index 0000000..6084ef1 --- /dev/null +++ b/include/stonith/expect.h @@ -0,0 +1,61 @@ +/* + * Expect simple tokens. Simple expect infrastructure for STONITH API + * + * Copyright (c) 2000 Alan Robertson <alanr@unix.sh> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __EXPECT_H +# define __EXPECT_H +/* + * If we find any of the given tokens in the input stream, + * we return it's "toktype", so we can tell which one was + * found. + * + */ + +struct Etoken { + const char * string; /* The token to look for */ + int toktype; /* The type to return on match */ + int matchto; /* Modified during matches */ +}; + +int ExpectToken(int fd +, struct Etoken * toklist /* List of tokens to match against */ + /* Final token has NULL string */ +, int to_secs /* Timeout value in seconds */ +, char * buf /* If non-NULL, then all the text + * matched/skipped over by this match */ +, int maxline, +, int debug); /* debug level */ + + +/* + * A handy little routine. It runs the given process + * with it's standard output redirected into our *readfd, and + * its standard input redirected from our *writefd + * + * Doing this with all the pipes, etc. required for doing this + * is harder than it sounds :-) + */ + +int StartProcess(const char * cmd, int* readfd, int* writefd); + +#ifndef EOS +# define EOS '\0' +#endif +#endif /*__EXPECT_H*/ diff --git a/include/stonith/st_ttylock.h b/include/stonith/st_ttylock.h new file mode 100644 index 0000000..5b5c7fd --- /dev/null +++ b/include/stonith/st_ttylock.h @@ -0,0 +1,21 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __STONITH_ST_TTYLOCK_H +# define __STONITH_ST_TTYLOCK_H +int st_ttylock(const char *serial_device); +int st_ttyunlock(const char *serial_device); +#endif /*__STONITH_ST_TTYLOCK_H*/ diff --git a/include/stonith/stonith.h b/include/stonith/stonith.h new file mode 100644 index 0000000..93fbaac --- /dev/null +++ b/include/stonith/stonith.h @@ -0,0 +1,187 @@ +/* + * S hoot + * T he + * O ther + * N ode + * I n + * T he + * H ead + * + * Cause the other machine to reboot or die - now. + * + * We guarantee that when we report that the machine has been + * rebooted, then it has been (barring misconfiguration or hardware + * errors) + * + * A machine which we have STONITHed won't do anything more to its + * peripherials etc. until it goes through the reboot cycle. + */ + +/* + * + * Copyright (c) 2000 Alan Robertson <alanr@unix.sh> + * Copyright (c) 2004 International Business Machines, Inc. + * + * Author: Alan Robertson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __STONITH_H +# define __STONITH_H +#include <glib.h> +#include <ctype.h> + +#include <pils/plugin.h> +#define STONITH_VERS 2 + +/* + * Return codes from "Stonith" operations + */ + +#define S_OK 0 /* Machine correctly reset */ +#define S_BADCONFIG 1 /* Bad config info given */ +#define S_ACCESS 2 /* Can't access STONITH device */ + /* (login/passwd problem?) */ +#define S_INVAL 3 /* Bad/illegal argument */ +#define S_BADHOST 4 /* Bad/illegal host/node name */ +#define S_RESETFAIL 5 /* Reset failed */ +#define S_TIMEOUT 6 /* Timed out in the dialogues */ +#define S_ISOFF 7 /* Can't reboot: Outlet is off */ +#define S_OOPS 8 /* Something strange happened */ + +typedef struct stonith { + char * stype; +}Stonith; + +/* An array of StonithNVpairs is terminated by a NULL s_name */ +typedef struct { + char * s_name; + char * s_value; +}StonithNVpair; + +/* + * Operation requested by reset_req() + */ +#define ST_GENERIC_RESET 1 /* Reset the machine any way you can */ +#define ST_POWERON 2 /* Power the node on */ +#define ST_POWEROFF 3 /* Power the node off */ +/* + * Type of information requested by the get_info() call + */ +#define ST_CONF_XML 1 /* XML config info */ +#define ST_DEVICEID 2 /* Device Type Identification */ +#define ST_DEVICENAME 3 /* Unique Individual Device Identification */ + /* (only after stonith_set_config() call) */ +#define ST_DEVICEDESCR 4 /* Device Description text */ +#define ST_DEVICEURL 5 /* Manufacturer/Device URL */ + +extern PILPluginUniv *StonithPIsys; + +char ** stonith_types(void); /* NULL-terminated list */ + /* valid until next call of stonith_types() */ +Stonith*stonith_new(const char * type); +void stonith_delete(Stonith *); + +const char * const * stonith_get_confignames (Stonith* s); + /* static/global return */ + /* Return number and list of valid s_names */ + +const char* /* static/global return - lots of things! */ + stonith_get_info (Stonith* s, int infotype); + +void stonith_set_debug (Stonith* s, int debuglevel); +void stonith_set_log (Stonith* s + , PILLogFun); + +int stonith_set_config (Stonith* s, StonithNVpair* list); +int stonith_set_config_file(Stonith* s, const char * configname); + /* uses get_confignames to determine which + * names to look for in file configname, which + * is passed in by the -F option */ +int stonith_set_config_info(Stonith* s, const char * info); + /* uses get_confignames to determine which + * names to look for in string info, which + * is passed in by the -p option */ + /* + * Must call stonith_set_config() before calling functions below... + */ +char** stonith_get_hostlist (Stonith* s); +void stonith_free_hostlist (char** hostlist); +int stonith_get_status (Stonith* s); +int stonith_req_reset (Stonith* s, int operation, const char* node); + +StonithNVpair* stonith_env_to_NVpair(Stonith* s); + +/* Stonith 1 compatibility: Convert string to an NVpair set */ +StonithNVpair* + stonith1_compat_string_to_NVpair(Stonith* s, const char * str); +StonithNVpair* + stonith_ghash_to_NVpair(GHashTable* stringtable); +void free_NVpair(StonithNVpair*); /* Free result from above 2 functions */ +void strdown(char *str); /* simple replacement for g_strdown */ + +/* + * The ST_DEVICEID info call is intended to return the type of the Stonith + * device. Note that it may return a different result once it has attempted + * to talk to the device (like after a status() call). This is because + * a given STONITH module may be able to talk to more than one kind of + * model of STONITH device, and can't tell which type is out there + * to until it talks to it. For example, Baytech 3, Baytech 5 and + * Baytech 5a are all supported by one module, and this module actually + * captures the particular model number after it talks to it. + * + * The ST_DEVICEDESCR info call is intended to return information identifying + * the type of STONITH device supported by this STONITH object. This is so + * users can tell if they have this kind of device or not. + * + * SHOULD THIS BE IN THE XML SO IT CAN BE SUPPLIED IN SEVERAL LANGUAGES?? + * But, this would mean the STONITH command would have to parse XML. + * Sigh... I'd rather not... Or maybe it can be supplied duplicately + * in the XML if that is thought to be desirable... + * + * The ST_DEVICEURL info call is intended to return the URL of a web site + * related to the device in question. This might be the manufacturer, + * a pointer to the product line, or the individual product itself. + * + * A good way for a GUI to work which configures STONITH devices would be to + * use the result of the stonith_types() call in a pulldown menu. + * + * Once the type is selected, create a Stonith object of the selected type. + * One can then create a dialog box to create the configuration info for the + * device using return from the ST_CONF_XML info call to direct the + * GUI in what information to ask for to fill up the StonithNVpair + * argument to the stonith_set_config() call. This information would then + * be prompted for according to the XML information, and then put into + * a NULL-terminated array of StonithNVpair objects. + * + * Once this has been done, it can be tested for syntactic + * validity with stonith_set_config(). + * + * If it passes set_config(), it can be further validated using status() + * which will then actually try and talk to the STONITH device. If status() + * returns S_OK, then communication with the device was successfully + * established. + * + * Normally that would mean that logins, passwords, device names, and IP + * addresses, etc. have been validated as required by the particular device. + * + * At this point, you can ask the device which machines it knows how to reset + * using the stonith_get_hostlist() function. + * + */ + +#endif /*__STONITH_H*/ diff --git a/include/stonith/stonith_plugin.h b/include/stonith/stonith_plugin.h new file mode 100644 index 0000000..9091a6e --- /dev/null +++ b/include/stonith/stonith_plugin.h @@ -0,0 +1,125 @@ +/* + * S hoot + * T he + * O ther + * N ode + * I n + * T he + * H ead + * + * Cause the other machine to reboot or die - now. + * + * We guarantee that when we report that the machine has been + * rebooted, then it has been (barring misconfiguration or hardware errors) + * + * A machine which we have STONITHed won't do anything more to its + * peripherials etc. until it goes through the reboot cycle. + */ + +/* + * + * Copyright (c) 2004 International Business Machines, Inc. + * + * Author: Alan Robertson <alanr@unix.sh> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __STONITH_PLUGIN_H +# define __STONITH_PLUGIN_H + +#include <stonith/stonith.h> +#include <glib.h> + +typedef struct stonith_plugin StonithPlugin; + +#define NUM_STONITH_FNS 7 + +struct stonith_ops { + StonithPlugin * (*new) (const char*); /* mini-Constructor */ + void (*destroy) (StonithPlugin*); /*(full) Destructor */ + + const char* (*get_info) (StonithPlugin*, int infotype); + const char * const * (*get_confignames) (StonithPlugin*); + int (*set_config) (StonithPlugin*, StonithNVpair* list); + /* Finishes construction */ + /* + * Must call set_config before calling any of + * the member functions below... + */ + + int (*get_status) (StonithPlugin*s); + int (*req_reset) (StonithPlugin*, int op, const char* node); + + + char** (*get_hostlist) (StonithPlugin*); + /* Returns list of hosts it supports */ +}; + +struct stonith_plugin { + Stonith s; + struct stonith_ops* s_ops; + gboolean isconfigured; +}; + +#define STONITH_TYPE stonith2 +#define STONITH_TYPE_S "stonith2" +typedef struct StonithImports_s StonithImports; + +struct Etoken { + const char * string; /* The token to look for */ + int toktype; /* The type to return on match */ + int matchto; /* Modified during matches */ +}; + +/* An array of StonithNamesToGet is terminated by a NULL s_name */ +typedef struct { + const char * s_name; + char * s_value; +}StonithNamesToGet; + +#define TELNET_PORT 23 +#define TELNET_SERVICE "telnet" + +struct StonithImports_s { + int (*ExpectToken)(int fd, struct Etoken * toklist, int to_secs + , char * buf, int maxline, int debug); + int (*StartProcess)(const char * cmd, int * readfd, int * writefd); + int (*OpenStreamSocket) (const char * host, int port + , const char * service); + /* Service can be NULL, port can be <= 0, but not both... */ + const char* (*GetValue)(StonithNVpair*, const char * name); + int (*CopyAllValues) (StonithNamesToGet* out, StonithNVpair* in); + char **(*StringToHostList)(const char * hlstring); + char **(*CopyHostList)(const char * const * hlstring); + void (*FreeHostList)(char** hostlist); + int (*TtyLock)(const char* tty); + int (*TtyUnlock)(const char* tty); +}; + + +/* + * A few standardized parameter names + */ + +#define ST_HOSTLIST "hostlist" +#define ST_IPADDR "ipaddr" +#define ST_LOGIN "login" +#define ST_PASSWD "password" +#define ST_COMMUNITY "community" /* SNMP community */ +#define ST_TTYDEV "ttydev" /* TTY device name */ + +#endif /*__STONITH__PLUGIN_H*/ |