diff --git a/configure.ac b/configure.ac index 033d2513..d5aa87e9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,668 +1,668 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # bootstrap / init AC_PREREQ([2.61]) AC_INIT([corosync], m4_esyscmd([build-aux/git-version-gen .tarball-version]), [openais@lists.osdl.org]) AM_INIT_AUTOMAKE([-Wno-portability]) AC_CONFIG_SRCDIR([lib/cpg.c]) AC_CONFIG_HEADER([include/corosync/config.h include/corosync/cs_config.h]) AC_CANONICAL_HOST AC_LANG([C]) dnl Fix default variables - "prefix" variable if not specified if test "$prefix" = "NONE"; then prefix="/usr" dnl Fix "localstatedir" variable if not specified if test "$localstatedir" = "\${prefix}/var"; then localstatedir="/var" fi dnl Fix "sysconfdir" variable if not specified if test "$sysconfdir" = "\${prefix}/etc"; then sysconfdir="/etc" fi dnl Fix "libdir" variable if not specified if test "$libdir" = "\${exec_prefix}/lib"; then if test -e /usr/lib64; then libdir="/usr/lib64" else libdir="/usr/lib" fi fi fi if test "$srcdir" = "."; then AC_MSG_NOTICE([building in place srcdir:$srcdir]) AC_DEFINE([BUILDING_IN_PLACE], 1, [building in place]) else AC_MSG_NOTICE([building out of tree srcdir:$srcdir]) fi # Checks for programs. # check stolen from gnulib/m4/gnu-make.m4 if ! ${MAKE-make} --version /cannot/make/this >/dev/null 2>&1; then AC_MSG_ERROR([you don't seem to have GNU make; it is required]) fi sinclude(coroysync-default.m4) AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_RANLIB AC_CHECK_PROGS([GROFF], [groff]) AC_CHECK_PROGS([PKGCONFIG], [pkg-config]) AC_CHECK_PROGS([AUGTOOL], [augtool]) AC_CHECK_PROGS([DOT], [dot]) AC_CHECK_PROGS([DOXYGEN], [doxygen]) # Checks for libraries. AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([socket], [socket]) AC_CHECK_LIB([nsl], [t_open]) AC_CHECK_LIB([rt], [sched_getscheduler]) PKG_CHECK_MODULES([LIBQB], [libqb]) # Checks for header files. AC_FUNC_ALLOCA AC_HEADER_DIRENT AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stdint.h \ stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h \ sys/time.h syslog.h unistd.h sys/types.h getopt.h malloc.h \ sys/sockio.h utmpx.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_UID_T AC_C_INLINE AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T AC_TYPE_INT8_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_HEADER_TIME AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T AC_C_VOLATILE # Checks for library functions. AC_FUNC_CLOSEDIR_VOID AC_FUNC_ERROR_AT_LINE AC_REPLACE_FNMATCH AC_FUNC_FORK AC_PROG_GCC_TRADITIONAL AC_FUNC_MALLOC AC_FUNC_MEMCMP AC_FUNC_REALLOC AC_FUNC_SELECT_ARGTYPES AC_TYPE_SIGNAL AC_FUNC_VPRINTF AC_CHECK_FUNCS([alarm alphasort atexit bzero dup2 endgrent endpwent fcntl \ getcwd getpeerucred getpeereid gettimeofday inet_ntoa memmove \ memset mkdir scandir select socket strcasecmp strchr strdup \ strerror strrchr strspn strstr pthread_setschedparam \ sched_get_priority_max sched_setscheduler]) AC_CONFIG_FILES([Makefile exec/Makefile include/Makefile init/Makefile lcr/Makefile lib/Makefile man/Makefile pkgconfig/Makefile services/Makefile test/Makefile cts/Makefile cts/agents/Makefile cts/CTSvars.py tools/Makefile conf/Makefile Doxyfile]) ### Local business dnl =============================================== dnl Functions / global M4 variables dnl =============================================== dnl Global list of LIB names m4_define([local_soname_list], [])dnl dnl Upcase parameter m4_define([local_upcase], [translit([$*], [a-z], [A-Z])])dnl dnl M4 macro for include lib/lib$1.soname and subst that m4_define([LIB_SONAME_IMPORT],[dnl m4_define([local_libname], local_upcase($1)[_SONAME])dnl m4_define([local_soname], translit(m4_sinclude(lib/lib$1.verso), [ ], []))dnl local_libname="local_soname"dnl m4_define([local_soname_list], m4_defn([local_soname_list])[,]local_libname[,]local_upcase($1))dnl AC_SUBST(local_libname)dnl ])dnl dnl M4 macro for print padspaces (used in LIB_MSG_RESULT). It takes 2 arguments, length of string to pad and desired dnl (padded) length m4_define([m4_printpadspace],[ifelse(m4_eval([$2 - $1 < 1]),[1],,[ ][m4_printpadspace([$1],m4_eval([$2 - 1]))])])dnl dnl Show AC_MSG_RESULT for specific libraries m4_define([LIB_MSG_RESULT], [ifelse([$#], [1], ,[dnl AC_MSG_RESULT([ $2 Library SONAME m4_printpadspace(len($2),8) = ${$1}]) LIB_MSG_RESULT(m4_shift(m4_shift($@)))dnl ])])dnl # =============================================== # Helpers # =============================================== ## helper for CC stuff cc_supports_flag() { - local CFLAGS="$@" + local CPPFLAGS="$CPPFLAGS $@" AC_MSG_CHECKING([whether $CC supports "$@"]) - AC_COMPILE_IFELSE([int main(){return 0;}] , + AC_PREPROC_IFELSE([AC_LANG_PROGRAM([])], [RC=0; AC_MSG_RESULT([yes])], [RC=1; AC_MSG_RESULT([no])]) return $RC } ## cleanup AC_MSG_NOTICE(Sanitizing prefix: ${prefix}) case $prefix in NONE) prefix=/usr/local;; esac AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix}) case $exec_prefix in dnl For consistency with Corosync, map NONE->$prefix NONE) exec_prefix=$prefix;; prefix) exec_prefix=$prefix;; esac ## local defines PACKAGE_FEATURES="" LINT_FLAGS="-weak -unrecog +posixlib +ignoresigns -fcnuse \ -badflag -D__gnuc_va_list=va_list -D__attribute\(x\)=" # default libraries SONAME SOMAJOR="4" SOMINOR="0" SOMICRO="0" SONAME="${SOMAJOR}.${SOMINOR}.${SOMICRO}" # specific libraries SONAME LIB_SONAME_IMPORT([cfg]) LIB_SONAME_IMPORT([confdb]) LIB_SONAME_IMPORT([cpg]) LIB_SONAME_IMPORT([evs]) LIB_SONAME_IMPORT([pload]) LIB_SONAME_IMPORT([quorum]) LIB_SONAME_IMPORT([sam]) LIB_SONAME_IMPORT([votequorum]) # local options AC_ARG_ENABLE([ansi], [ --enable-ansi : force to build with ANSI standards. ], [ default="no" ]) AC_ARG_ENABLE([fatal-warnings], [ --enable-fatal-warnings : enable fatal warnings. ], [ default="no" ]) AC_ARG_ENABLE([debug], [ --enable-debug : enable debug build. ], [ default="no" ]) AC_ARG_ENABLE([user-flags], [ --enable-user-flags : rely on user environment. ], [ default="no" ]) AC_ARG_ENABLE([coverage], [ --enable-coverage : coverage analysis of the codebase. ], [ default="no" ]) AC_ARG_ENABLE([small-memory-footprint], [ --enable-small-memory-footprint : Use small message queues and small messages sizes. ], [ default="no" ]) AC_ARG_ENABLE([nss], [ --enable-nss : Network Security Services encryption. ],, [ enable_nss="yes" ]) AC_ARG_ENABLE([dbus], [ --enable-dbus : dbus events. ],, [ enable_dbus="no" ]) AC_ARG_ENABLE([testagents], [ --enable-testagents : Install Test Agents. ],, [ default="no" ]) AC_ARG_ENABLE([rdma], [ --enable-rdma : Infiniband RDMA transport support ],, [ enable_rdma="no" ]) AM_CONDITIONAL(BUILD_RDMA, test x$enable_rdma = xyes) AC_ARG_ENABLE([monitoring], [ --enable-monitoring : resource monitoring ],, [ default="no" ]) AM_CONDITIONAL(BUILD_MONITORING, test x$enable_monitoring = xyes) AC_ARG_ENABLE([watchdog], [ --enable-watchdog : Watchdog support ],, [ default="no" ]) AM_CONDITIONAL(BUILD_WATCHDOG, test x$enable_watchdog = xyes) AC_ARG_ENABLE([augeas], [ --enable-augeas : Install the augeas lens for corosync.conf ],, [ enable_augeas="no" ]) AM_CONDITIONAL(INSTALL_AUGEAS, test x$enable_augeas = xyes) AC_ARG_ENABLE([systemd], [ --enable-systemd : Install systemd service files],, [ enable_systemd="no" ]) AM_CONDITIONAL(INSTALL_SYSTEMD, test x$enable_systemd = xyes) AC_ARG_WITH([initddir], [ --with-initddir=DIR : path to init script directory. ], [ INITDDIR="$withval" ], [ INITDDIR="$sysconfdir/init.d" ]) AC_ARG_WITH([lcrso-dir], [ --with-lcrso-dir=DIR : corosync lcrso files. ], [ LCRSODIR="$withval" ], [ LCRSODIR="$libexecdir/lcrso" ]) AC_ARG_WITH([socket-dir], [ --with-socket-dir=DIR : corosync socket dir. ], [ SOCKETDIR="$withval" ], [ SOCKETDIR="$localstatedir/run" ]) AC_ARG_ENABLE([snmp], [ --enable-snmp : SNMP protocol support ], [ default="no" ]) # OS detection # THIS SECTION MUST DIE! CP=cp OS_LDL="-ldl" have_linux="no" case "$host_os" in *linux*) AC_DEFINE_UNQUOTED([COROSYNC_LINUX], [1], [Compiling for Linux platform]) OS_CFLAGS="" OS_CPPFLAGS="-D_GNU_SOURCE" OS_LDFLAGS="" OS_DYFLAGS="-rdynamic" DARWIN_OPTS="" have_linux="yes" ;; darwin*) AC_DEFINE_UNQUOTED([COROSYNC_DARWIN], [1], [Compiling for Darwin platform]) CP=rsync OS_CFLAGS="" OS_CPPFLAGS="" OS_LDFLAGS="" OS_DYFLAGS="" DARWIN_OPTS="-dynamiclib -bind_at_load \ -current_version ${SONAME} \ -compatibility_version ${SONAME} -install_name \$(libdir)/\$(@)" AC_DEFINE_UNQUOTED([MAP_ANONYMOUS], [MAP_ANON], [Shared memory define for Darwin platform]) AC_DEFINE_UNQUOTED([PATH_MAX], [4096], [Number of chars in a path name including nul]) AC_DEFINE_UNQUOTED([NAME_MAX], [255], [Number of chars in a file name]) ;; *bsd*) AC_DEFINE_UNQUOTED([COROSYNC_BSD], [1], [Compiling for BSD platform]) AC_DEFINE_UNQUOTED([MAP_ANONYMOUS], [MAP_ANON], [Shared memory define for Darwin platform]) OS_CFLAGS="" OS_CPPFLAGS="-I/usr/local/include" OS_LDFLAGS="-L/usr/local/lib" OS_DYFLAGS="-export-dynamic" DARWIN_OPTS="" OS_LDL="" case "$host_os" in *freebsd[[234567]]*) ;; *freebsd*) AC_DEFINE_UNQUOTED([COROSYNC_FREEBSD_GE_8], [1], [Compiling for FreeBSD >= 8 platform]) ;; esac ;; *solaris*) AC_DEFINE_UNQUOTED([COROSYNC_SOLARIS], [1], [Compiling for Solaris platform]) AC_DEFINE_UNQUOTED([TS_CLASS], [1], [Prevent being scheduled RR]) AC_DEFINE_UNQUOTED([_SEM_SEMUN_UNDEFINED], [1], [The semun structure is undefined]) CP=rsync OS_CFLAGS="" OS_CPPFLAGS="-D_REENTRANT" OS_LDFLAGS="" OS_DYFLAGS="-Wl,-z,lazyload" DARWIN_OPTS="" SOLARIS_OPTS=" " ;; *) AC_MSG_ERROR([Unsupported OS? hmmmm]) ;; esac AC_SUBST(CP) # *FLAGS handling goes here ENV_CFLAGS="$CFLAGS" ENV_CPPFLAGS="$CPPFLAGS" ENV_LDFLAGS="$LDFLAGS" # debug build stuff if test "x${enable_debug}" = xyes; then AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code]) OPT_CFLAGS="-O0" PACKAGE_FEATURES="$PACKAGE_FEATURES debug" else OPT_CFLAGS="-O3" fi # gdb flags if test "x${GCC}" = xyes; then GDB_FLAGS="-ggdb3" else GDB_FLAGS="-g" fi # Look for libnss if test "x${enable_nss}" = xyes; then PKG_CHECK_MODULES([nss],[nss]) AC_DEFINE_UNQUOTED([HAVE_LIBNSS], 1, [have libnss]) PACKAGE_FEATURES="$PACKAGE_FEATURES nss" fi # Look for dbus-1 if test "x${enable_dbus}" = xyes; then PKG_CHECK_MODULES([DBUS],[dbus-1]) AC_DEFINE_UNQUOTED([HAVE_DBUS], 1, [have dbus]) PACKAGE_FEATURES="$PACKAGE_FEATURES dbus" fi if test "x${enable_testagents}" = xyes; then AC_DEFINE_UNQUOTED([HAVE_TESTAGENTS], 1, [have testagents]) PACKAGE_FEATURES="$PACKAGE_FEATURES testagents" fi if test "x${enable_rdma}" = xyes; then PKG_CHECK_MODULES([rdmacm],[rdmacm]) PKG_CHECK_MODULES([ibverbs],[ibverbs]) AC_DEFINE_UNQUOTED([HAVE_RDMA], 1, [have rdmacm]) PACKAGE_FEATURES="$PACKAGE_FEATURES rdma" fi if test "x${enable_monitoring}" = xyes; then AC_CHECK_LIB([statgrab], [sg_get_mem_stats], have_libstatgrab="yes", have_libstatgrab="no") if test "x${have_libstatgrab}" = xyes; then AC_DEFINE_UNQUOTED([HAVE_LIBSTATGRAB], 1, [have libstatgrab]) statgrab_LIBS="-lstatgrab" else if test "x${have_linux}" = xno; then AC_MSG_ERROR(monitoring requires libstatgrab on non-linux systems) fi fi AC_SUBST([statgrab_LIBS]) AC_DEFINE_UNQUOTED([HAVE_MONITORING], 1, [have resource monitoring]) PACKAGE_FEATURES="$PACKAGE_FEATURES monitoring" fi if test "x${enable_watchdog}" = xyes; then AC_CHECK_HEADER(linux/watchdog.h,,AC_MSG_ERROR(watchdog requires linux/watchdog.h)) AC_CHECK_HEADER(linux/reboot.h,,AC_MSG_ERROR(watchdog requires linux/reboot.h)) AC_DEFINE_UNQUOTED([HAVE_WATCHDOG], 1, [have watchdog]) PACKAGE_FEATURES="$PACKAGE_FEATURES watchdog" fi if test "x${enable_augeas}" = xyes; then PACKAGE_FEATURES="$PACKAGE_FEATURES augeas" fi if test "x${enable_systemd}" = xyes; then PACKAGE_FEATURES="$PACKAGE_FEATURES systemd" fi if test "x${enable_snmp}" = xyes; then SNMPCONFIG="" AC_CHECK_HEADERS(net-snmp/net-snmp-config.h) if test "x${ac_cv_header_net_snmp_net_snmp_config_h}" != "xyes"; then enable_snmp=no fi if test $enable_snmp != no; then AC_PATH_PROGS(SNMPCONFIG, net-snmp-config) if test "X${SNMPCONFIG}" = "X"; then AC_MSG_RESULT(You need the net_snmp development package to continue.) enable_snmp=no fi fi if test $enable_snmp != no; then AC_MSG_CHECKING(for special snmp libraries) SNMPLIBS=`$SNMPCONFIG --libs` AC_MSG_RESULT($SNMPLIBS) fi if test $enable_snmp != no; then savedLibs=$LIBS LIBS="$LIBS $SNMPLIBS" AC_CHECK_FUNCS(netsnmp_transport_open_client) if test $ac_cv_func_netsnmp_transport_open_client != yes; then AC_CHECK_FUNCS(netsnmp_tdomain_transport) if test $ac_cv_func_netsnmp_tdomain_transport != yes; then enable_snmp=no fi else AC_DEFINE_UNQUOTED([NETSNMPV54], $NETSNMP_NEW_SUPPORT, [have net-snmp5.4 over]) fi LIBS=$savedLibs fi AC_MSG_CHECKING(for snmp) AC_MSG_RESULT($enable_snmp) if test $enable_snmp = no; then enable_snmp=0 AC_MSG_ERROR(Unable to support SNMP) else enable_snmp=1 PACKAGE_FEATURES="$PACKAGE_FEATURES snmp" AC_DEFINE_UNQUOTED([ENABLE_SNMP], $enable_snmp, [Build in support for sending SNMP traps]) fi else enable_snmp=0 fi AC_SUBST([SNMPLIBS]) AC_SUBST([SNMP_LCRSO]) AM_CONDITIONAL(BUILD_SNMP, test "${enable_snmp}" = "1") # extra warnings EXTRA_WARNINGS="" WARNLIST=" all shadow missing-prototypes missing-declarations strict-prototypes declaration-after-statement pointer-arith write-strings cast-align bad-function-cast missing-format-attribute format=2 format-security format-nonliteral no-long-long unsigned-char gnu89-inline no-strict-aliasing " for j in $WARNLIST; do if cc_supports_flag -W$j; then EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j"; fi done if test "x${enable_coverage}" = xyes && \ cc_supports_flag -ftest-coverage && \ cc_supports_flag -fprofile-arcs ; then AC_MSG_NOTICE([Enabling Coverage (enable -O0 by default)]) OPT_CFLAGS="-O0" COVERAGE_CFLAGS="-ftest-coverage -fprofile-arcs" COVERAGE_LDFLAGS="-ftest-coverage -fprofile-arcs" COVERAGE_LCRSO_EXTRA_LDFLAGS="-rdynamic" PACKAGE_FEATURES="$PACKAGE_FEATURES coverage" else COVERAGE_CFLAGS="" COVERAGE_LDFLAGS="" COVERAGE_LCRSO_EXTRA_LDFLAGS="" fi if test "x${enable_small_memory_footprint}" = xyes ; then AC_DEFINE_UNQUOTED([HAVE_SMALL_MEMORY_FOOTPRINT], 1, [have small_memory_footprint]) PACKAGE_FEATURES="$PACKAGE_FEATURES small-memory-footprint" fi if test "x${enable_ansi}" = xyes && \ cc_supports_flag -std=iso9899:199409 ; then AC_MSG_NOTICE([Enabling ANSI Compatibility]) ANSI_CPPFLAGS="-ansi -D_GNU_SOURCE -DANSI_ONLY" PACKAGE_FEATURES="$PACKAGE_FEATURES ansi" else ANSI_CPPFLAGS="" fi if test "x${enable_fatal_warnings}" = xyes && \ cc_supports_flag -Werror ; then AC_MSG_NOTICE([Enabling Fatal Warnings (-Werror)]) WERROR_CFLAGS="-Werror" PACKAGE_FEATURES="$PACKAGE_FEATURES fatal-warnings" else WERROR_CFLAGS="" fi # don't add addtional cflags if test "x${enable_user_flags}" = xyes; then OPT_CFLAGS="" GDB_FLAGS="" EXTRA_WARNINGS="" fi # final build of *FLAGS CFLAGS="$ENV_CFLAGS $OPT_CFLAGS $GDB_FLAGS $OS_CFLAGS \ $COVERAGE_CFLAGS $EXTRA_WARNINGS $WERROR_CFLAGS $NSS_CFLAGS" CPPFLAGS="$ENV_CPPFLAGS $ANSI_CPPFLAGS $OS_CPPFLAGS" LDFLAGS="$ENV_LDFLAGS $COVERAGE_LDFLAGS $OS_LDFLAGS" # substitute what we need: AC_SUBST([INITDDIR]) AC_SUBST([LCRSODIR]) AC_SUBST([SOCKETDIR]) AC_SUBST([SOMAJOR]) AC_SUBST([SOMINOR]) AC_SUBST([SOMICRO]) AC_SUBST([SONAME]) AC_SUBST([COVERAGE_LCRSO_EXTRA_LDFLAGS]) AC_SUBST([OS_DYFLAGS]) AC_SUBST([OS_LDL]) AM_CONDITIONAL(INSTALL_TESTAGENTS, test -n "${enable_testagents}") AM_CONDITIONAL(INSTALL_MIB, test "${enable_snmp}" = "1") AM_CONDITIONAL(INSTALL_DBUSCONF, test "${enable_dbus}" = "1") AM_CONDITIONAL(AUGTOOL, test -n "${AUGTOOL}") AC_SUBST([NSS_LDFLAGS]) AM_CONDITIONAL(BUILD_DARWIN, test -n "${DARWIN_OPTS}") AM_CONDITIONAL(BUILD_SOLARIS, test -n "${SOLARIS_OPTS}") AC_SUBST([DARWIN_OPTS]) AC_SUBST([SOLARIS_OPTS]) AM_CONDITIONAL(BUILD_HTML_DOCS, test -n "${GROFF}") AC_SUBST([LINT_FLAGS]) AC_DEFINE_UNQUOTED([LCRSODIR], "$(eval echo ${LCRSODIR})", [LCRSO directory]) AC_DEFINE_UNQUOTED([SOCKETDIR], "$(eval echo ${SOCKETDIR})", [Socket directory]) AC_DEFINE_UNQUOTED([LOCALSTATEDIR], "$(eval echo ${localstatedir})", [localstate directory]) COROSYSCONFDIR=${sysconfdir}/corosync AC_SUBST([COROSYSCONFDIR]) AC_DEFINE_UNQUOTED([COROSYSCONFDIR], "$(eval echo ${COROSYSCONFDIR})", [corosync config directory]) AC_DEFINE_UNQUOTED([PACKAGE_FEATURES], "${PACKAGE_FEATURES}", [corosync built-in features]) AC_OUTPUT AC_MSG_RESULT([]) AC_MSG_RESULT([$PACKAGE configuration:]) AC_MSG_RESULT([ Version = ${VERSION}]) AC_MSG_RESULT([ Prefix = ${prefix}]) AC_MSG_RESULT([ Executables = ${sbindir}]) AC_MSG_RESULT([ Man pages = ${mandir}]) AC_MSG_RESULT([ Doc dir = ${docdir}]) AC_MSG_RESULT([ Libraries = ${libdir}]) AC_MSG_RESULT([ Header files = ${includedir}]) AC_MSG_RESULT([ Arch-independent files = ${datadir}]) AC_MSG_RESULT([ State information = ${localstatedir}]) AC_MSG_RESULT([ System configuration = ${sysconfdir}]) AC_MSG_RESULT([ System init.d directory = ${INITDDIR}]) AC_MSG_RESULT([ corosync config dir = ${COROSYSCONFDIR}]) AC_MSG_RESULT([ LCRSO = ${LCRSODIR}]) AC_MSG_RESULT([ SOCKETDIR = ${SOCKETDIR}]) AC_MSG_RESULT([ Features =${PACKAGE_FEATURES}]) AC_MSG_RESULT([]) AC_MSG_RESULT([$PACKAGE build info:]) AC_MSG_RESULT([ Library SONAME = ${SONAME}]) LIB_MSG_RESULT(m4_shift(local_soname_list))dnl AC_MSG_RESULT([ Default optimization = ${OPT_CFLAGS}]) AC_MSG_RESULT([ Default debug options = ${GDB_CFLAGS}]) AC_MSG_RESULT([ Extra compiler warnings = ${EXTRA_WARNING}]) AC_MSG_RESULT([ Env. defined CFLAG = ${ENV_CFLAGS}]) AC_MSG_RESULT([ Env. defined CPPFLAGS = ${ENV_CPPFLAGS}]) AC_MSG_RESULT([ Env. defined LDFLAGS = ${ENV_LDFLAGS}]) AC_MSG_RESULT([ OS defined CFLAGS = ${OS_CFLAGS}]) AC_MSG_RESULT([ OS defined CPPFLAGS = ${OS_CPPFLAGS}]) AC_MSG_RESULT([ OS defined LDFLAGS = ${OS_LDFLAGS}]) AC_MSG_RESULT([ OS defined LDL = ${OS_LDL}]) AC_MSG_RESULT([ OS defined DYFLAGS = ${OS_DYFLAGS}]) AC_MSG_RESULT([ ANSI defined CPPFLAGS = ${ANSI_CPPFLAGS}]) AC_MSG_RESULT([ Coverage CFLAGS = ${COVERAGE_CFLAGS}]) AC_MSG_RESULT([ Coverage LDFLAGS = ${COVERAGE_LDFLAGS}]) AC_MSG_RESULT([ Fatal War. CFLAGS = ${WERROR_CFLAGS}]) AC_MSG_RESULT([ Final CFLAGS = ${CFLAGS}]) AC_MSG_RESULT([ Final CPPFLAGS = ${CPPFLAGS}]) AC_MSG_RESULT([ Final LDFLAGS = ${LDFLAGS}]) diff --git a/cts/agents/common_test_agent.c b/cts/agents/common_test_agent.c index 03bd677f..f268aca6 100644 --- a/cts/agents/common_test_agent.c +++ b/cts/agents/common_test_agent.c @@ -1,307 +1,307 @@ /* * Copyright (c) 2010 Red Hat, Inc. * * All rights reserved. * * Author: Angus Salkeld (asalkeld@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common_test_agent.h" int32_t parse_debug = 0; static char big_and_buf_rx[HOW_BIG_AND_BUF]; ta_do_command_fn do_command; static qb_loop_t *poll_handle; static pre_exit_fn pre_exit = NULL; qb_loop_t *ta_poll_handle_get(void) { return poll_handle; } static void shut_me_down(void) { if (pre_exit) { pre_exit(); } qb_loop_stop(poll_handle); } static void ta_handle_command (int sock, char* msg) { int num_args; char *saveptr = NULL; char *str = strdup (msg); char *str_len; char *str_arg; char *args[5]; int i = 0; int a = 0; char* func = NULL; if (parse_debug) syslog (LOG_DEBUG,"%s (MSG:%s)\n", __func__, msg); str_len = strtok_r (str, ":", &saveptr); assert (str_len); num_args = atoi (str_len) * 2; for (i = 0; i < num_args / 2; i++) { str_len = strtok_r (NULL, ":", &saveptr); str_arg = strtok_r (NULL, ":", &saveptr); if (func == NULL) { /* first "arg" is the function */ if (parse_debug) syslog (LOG_DEBUG, "(LEN:%s, FUNC:%s)", str_len, str_arg); func = str_arg; a = 0; } else { args[a] = str_arg; a++; if (parse_debug) syslog (LOG_DEBUG, "(LEN:%s, ARG:%s)", str_len, str_arg); } } do_command (sock, func, args, a+1); free (str); } static int server_process_data_fn ( int fd, int revents, void *data) { char *saveptr; char *msg; char *cmd; int32_t nbytes; if (revents & POLLHUP) { shut_me_down(); return -1; } if ((nbytes = recv (fd, big_and_buf_rx, sizeof (big_and_buf_rx), 0)) <= 0) { /* got error or connection closed by client */ if (nbytes == 0) { /* connection closed */ syslog (LOG_WARNING, "socket %d hung up: exiting...\n", fd); } else { syslog (LOG_ERR,"recv() failed: %s", strerror(errno)); } shut_me_down(); return -1; } else { big_and_buf_rx[nbytes] = '\0'; msg = strtok_r (big_and_buf_rx, ";", &saveptr); assert (msg); while (msg) { cmd = strdup (msg); ta_handle_command (fd, cmd); free (cmd); msg = strtok_r (NULL, ";", &saveptr); } } return 0; } static int server_accept_fn ( int fd, int revents, void *data) { socklen_t addrlen; struct sockaddr_in in_addr; int new_fd; int res; if (revents & POLLHUP) { shut_me_down(); return -1; } addrlen = sizeof (struct sockaddr_in); retry_accept: new_fd = accept (fd, (struct sockaddr *)&in_addr, &addrlen); if (new_fd == -1 && errno == EINTR) { goto retry_accept; } if (new_fd == -1) { syslog (LOG_ERR, "Could not accept connection: %s\n", strerror (errno)); return (0); /* This is an error, but -1 would indicate disconnect from poll loop */ } res = fcntl (new_fd, F_SETFL, O_NONBLOCK); if (res == -1) { syslog (LOG_ERR, "Could not set non-blocking operation on connection: %s\n", strerror (errno)); close (new_fd); return (0); /* This is an error, but -1 would indicate disconnect from poll loop */ } qb_loop_poll_add (poll_handle, QB_LOOP_MED, new_fd, POLLIN|POLLNVAL, NULL, server_process_data_fn); return 0; } static int create_server_sockect (int server_port) { int listener; int yes = 1; int rv; struct addrinfo hints, *ai, *p; char server_port_str[16]; char addr_str[INET_ADDRSTRLEN]; - void *ptr; + void *ptr = NULL; /* get a socket and bind it */ sprintf(server_port_str, "%d", server_port); memset (&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if ((rv = getaddrinfo (NULL, server_port_str, &hints, &ai)) != 0) { syslog (LOG_ERR, "%s", gai_strerror (rv)); exit (1); } for (p = ai; p != NULL; p = p->ai_next) { listener = socket (p->ai_family, p->ai_socktype, p->ai_protocol); if (listener < 0) { continue; } /* lose the pesky "address already in use" error message */ if (setsockopt (listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) { syslog (LOG_ERR, "setsockopt() failed: %s", strerror (errno)); } switch (p->ai_family) { case AF_INET: ptr = &((struct sockaddr_in *) p->ai_addr)->sin_addr; break; case AF_INET6: ptr = &((struct sockaddr_in6 *) p->ai_addr)->sin6_addr; break; } if (inet_ntop(p->ai_family, ptr, addr_str, INET_ADDRSTRLEN) == NULL) { syslog (LOG_ERR, "inet_ntop() failed: %s", strerror (errno)); } if (bind (listener, p->ai_addr, p->ai_addrlen) < 0) { syslog (LOG_ERR, "bind(%s) failed: %s\n", addr_str, strerror (errno)); close (listener); continue; } break; } if (p == NULL) { syslog (LOG_ERR, "failed to bind"); exit (2); } freeaddrinfo (ai); if (listen (listener, 10) == -1) { syslog (LOG_ERR, "listen() failed: %s", strerror(errno)); exit (3); } return listener; } static int32_t sig_exit_handler (int num, void *data) { shut_me_down(); return 0; } int test_agent_run(int server_port, ta_do_command_fn func, pre_exit_fn exit_fn) { int listener; do_command = func; pre_exit = exit_fn; poll_handle = qb_loop_create (); if (exit_fn) { qb_loop_signal_add(poll_handle, QB_LOOP_HIGH, SIGINT, NULL, sig_exit_handler, NULL); qb_loop_signal_add(poll_handle, QB_LOOP_HIGH, SIGQUIT, NULL, sig_exit_handler, NULL); qb_loop_signal_add(poll_handle, QB_LOOP_HIGH, SIGTERM, NULL, sig_exit_handler, NULL); } listener = create_server_sockect (server_port); qb_loop_poll_add (poll_handle, QB_LOOP_MED, listener, POLLIN|POLLNVAL, NULL, server_accept_fn); qb_loop_run (poll_handle); return 0; } diff --git a/exec/crypto.c b/exec/crypto.c index 901797a1..14fb8074 100644 --- a/exec/crypto.c +++ b/exec/crypto.c @@ -1,1342 +1,1340 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.com */ #include #include #include #include #include #include #include #include #if defined(COROSYNC_BSD) #include #endif #include #include #include #include "crypto.h" #define CONST64(n) n ## ULL typedef uint32_t ulong32; typedef uint64_t ulong64; #if __BYTE_ORDER == __LITTLE_ENDIAN #define ENDIAN_LITTLE #elif __BYTE_ORDER == __BIG_ENDIAN #define ENDIAN_BIG #else #error "cannot detect byte order" #endif #if defined(COROSYNC_LINUX) #if __WORDSIZE == 64 #define ENDIAN_64BITWORD #endif #if __WORDSIZE == 32 #define ENDIAN_32BITWORD #endif #else /* XXX need to find a better default */ #define ENDIAN_32BITWORD #endif /* ---- HELPER MACROS ---- */ #ifdef ENDIAN_NEUTRAL #define STORE32L(x, y) \ { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD32L(x, y) \ { x = ((unsigned long)((y)[3] & 255)<<24) | \ ((unsigned long)((y)[2] & 255)<<16) | \ ((unsigned long)((y)[1] & 255)<<8) | \ ((unsigned long)((y)[0] & 255)); } #define STORE64L(x, y) \ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD64L(x, y) \ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } #define STORE32H(x, y) \ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } #define LOAD32H(x, y) \ { x = ((unsigned long)((y)[0] & 255)<<24) | \ ((unsigned long)((y)[1] & 255)<<16) | \ ((unsigned long)((y)[2] & 255)<<8) | \ ((unsigned long)((y)[3] & 255)); } #define STORE64H(x, y) \ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } #define LOAD64H(x, y) \ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } #endif /* ENDIAN_NEUTRAL */ #ifdef ENDIAN_LITTLE #define STORE32H(x, y) \ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } #define LOAD32H(x, y) \ { x = ((unsigned long)((y)[0] & 255)<<24) | \ ((unsigned long)((y)[1] & 255)<<16) | \ ((unsigned long)((y)[2] & 255)<<8) | \ ((unsigned long)((y)[3] & 255)); } #define STORE64H(x, y) \ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } #define LOAD64H(x, y) \ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } #ifdef ENDIAN_32BITWORD #define STORE32L(x, y) \ { unsigned long __t = (x); memcpy(y, &__t, 4); } #define LOAD32L(x, y) \ memcpy(&(x), y, 4); #define STORE64L(x, y) \ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD64L(x, y) \ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } #else /* 64-bit words then */ #define STORE32L(x, y) \ { unsigned long __t = (x); memcpy(y, &__t, 4); } #define LOAD32L(x, y) \ { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } #define STORE64L(x, y) \ { ulong64 __t = (x); memcpy(y, &__t, 8); } #define LOAD64L(x, y) \ { memcpy(&(x), y, 8); } #endif /* ENDIAN_64BITWORD */ #endif /* ENDIAN_LITTLE */ #ifdef ENDIAN_BIG #define STORE32L(x, y) \ { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD32L(x, y) \ { x = ((unsigned long)((y)[3] & 255)<<24) | \ ((unsigned long)((y)[2] & 255)<<16) | \ ((unsigned long)((y)[1] & 255)<<8) | \ ((unsigned long)((y)[0] & 255)); } #define STORE64L(x, y) \ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD64L(x, y) \ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } #ifdef ENDIAN_32BITWORD #define STORE32H(x, y) \ { unsigned long __t = (x); memcpy(y, &__t, 4); } #define LOAD32H(x, y) \ memcpy(&(x), y, 4); #define STORE64H(x, y) \ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } #define LOAD64H(x, y) \ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \ (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } #else /* 64-bit words then */ #define STORE32H(x, y) \ { unsigned long __t = (x); memcpy(y, &__t, 4); } #define LOAD32H(x, y) \ { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } #define STORE64H(x, y) \ { ulong64 __t = (x); memcpy(y, &__t, 8); } #define LOAD64H(x, y) \ { memcpy(&(x), y, 8); } #endif /* ENDIAN_64BITWORD */ #endif /* ENDIAN_BIG */ #define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \ ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) ) #if defined(__GNUC__) && defined(__i386__) && !defined(INTEL_CC) static inline unsigned long ROL(unsigned long word, int i) { __asm__("roll %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); return word; } static inline unsigned long ROR(unsigned long word, int i) { __asm__("rorl %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); return word; } #else /* rotates the hard way */ #define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) #define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) #endif #define ROL64(x, y) \ ( (((x)<<((ulong64)(y)&63)) | \ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) #define ROR64(x, y) \ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) #undef MAX #undef MIN #define MAX(x, y) ( ((x)>(y))?(x):(y) ) #define MIN(x, y) ( ((x)<(y))?(x):(y) ) /* extract a byte portably */ #define byte(x, n) (((x) >> (8 * (n))) & 255) #define CONST64(n) n ## ULL /* a simple macro for making hash "process" functions */ #define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ int func_name (hash_state * md, const unsigned char *buf, unsigned long len) \ { \ unsigned long n; \ if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ return CRYPT_INVALID_ARG; \ } \ while (len > 0) { \ if (md-> state_var .curlen == 0 && len >= block_size) { \ compress_name (md, (unsigned char *)buf); \ md-> state_var .length += block_size * 8; \ buf += block_size; \ len -= block_size; \ } else { \ n = MIN(len, (block_size - md-> state_var .curlen)); \ memcpy(md-> state_var .buf + md-> state_var.curlen, buf, (size_t)n); \ md-> state_var .curlen += n; \ buf += n; \ len -= n; \ if (md-> state_var .curlen == block_size) { \ compress_name (md, md-> state_var .buf); \ md-> state_var .length += 8*block_size; \ md-> state_var .curlen = 0; \ } \ } \ } \ return CRYPT_OK; \ } #define MAXBLOCKSIZE 128 /* * The mycrypt_macros.h file */ /* ---- HELPER MACROS ---- */ #ifdef ENDIAN_NEUTRAL #define STORE32L(x, y) \ { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD32L(x, y) \ { x = ((unsigned long)((y)[3] & 255)<<24) | \ ((unsigned long)((y)[2] & 255)<<16) | \ ((unsigned long)((y)[1] & 255)<<8) | \ ((unsigned long)((y)[0] & 255)); } #define STORE64L(x, y) \ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD64L(x, y) \ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } #define STORE32H(x, y) \ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } #define LOAD32H(x, y) \ { x = ((unsigned long)((y)[0] & 255)<<24) | \ ((unsigned long)((y)[1] & 255)<<16) | \ ((unsigned long)((y)[2] & 255)<<8) | \ ((unsigned long)((y)[3] & 255)); } #define STORE64H(x, y) \ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } #define LOAD64H(x, y) \ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } #endif /* ENDIAN_NEUTRAL */ #ifdef ENDIAN_LITTLE #define STORE32H(x, y) \ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } #define LOAD32H(x, y) \ { x = ((unsigned long)((y)[0] & 255)<<24) | \ ((unsigned long)((y)[1] & 255)<<16) | \ ((unsigned long)((y)[2] & 255)<<8) | \ ((unsigned long)((y)[3] & 255)); } #define STORE64H(x, y) \ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } #define LOAD64H(x, y) \ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } #ifdef ENDIAN_32BITWORD #define STORE32L(x, y) \ { unsigned long __t = (x); memcpy(y, &__t, 4); } #define LOAD32L(x, y) \ memcpy(&(x), y, 4); #define STORE64L(x, y) \ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD64L(x, y) \ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } #else /* 64-bit words then */ #define STORE32L(x, y) \ { unsigned long __t = (x); memcpy(y, &__t, 4); } #define LOAD32L(x, y) \ { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } #define STORE64L(x, y) \ { ulong64 __t = (x); memcpy(y, &__t, 8); } #define LOAD64L(x, y) \ { memcpy(&(x), y, 8); } #endif /* ENDIAN_64BITWORD */ #endif /* ENDIAN_LITTLE */ #ifdef ENDIAN_BIG #define STORE32L(x, y) \ { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD32L(x, y) \ { x = ((unsigned long)((y)[3] & 255)<<24) | \ ((unsigned long)((y)[2] & 255)<<16) | \ ((unsigned long)((y)[1] & 255)<<8) | \ ((unsigned long)((y)[0] & 255)); } #define STORE64L(x, y) \ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } #define LOAD64L(x, y) \ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } #ifdef ENDIAN_32BITWORD #define STORE32H(x, y) \ { unsigned long __t = (x); memcpy(y, &__t, 4); } #define LOAD32H(x, y) \ memcpy(&(x), y, 4); #define STORE64H(x, y) \ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } #define LOAD64H(x, y) \ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \ (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } #else /* 64-bit words then */ #define STORE32H(x, y) \ { unsigned long __t = (x); memcpy(y, &__t, 4); } #define LOAD32H(x, y) \ { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } #define STORE64H(x, y) \ { ulong64 __t = (x); memcpy(y, &__t, 8); } #define LOAD64H(x, y) \ { memcpy(&(x), y, 8); } #endif /* ENDIAN_64BITWORD */ #endif /* ENDIAN_BIG */ #define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \ ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) ) #define ROL64(x, y) \ ( (((x)<<((ulong64)(y)&63)) | \ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) #define ROR64(x, y) \ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) #undef MAX #undef MIN #define MAX(x, y) ( ((x)>(y))?(x):(y) ) #define MIN(x, y) ( ((x)<(y))?(x):(y) ) /* extract a byte portably */ #define byte(x, n) (((x) >> (8 * (n))) & 255) /* $Id: s128multab.h 213 2003-12-16 04:27:12Z ggr $ */ /* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */ /* Multiplication table for Turing using 0xD02B4367 */ static const ulong32 Multab[256] = { 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, 0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478, 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746, 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, 0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A, 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB, 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, 0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04, 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2, 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, 0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D, 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC, 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, 0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80, 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE, 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, 0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F, 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE, 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, 0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41, 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC, 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, 0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703, 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2, 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, 0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5, 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB, 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, 0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787, 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656, 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, 0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9, 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748, 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, 0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7, 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476, 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, 0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A, 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34, 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, 0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523, 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2, 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, 0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D, 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0, 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, 0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F, 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E, 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, 0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F, 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71, 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, 0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D, 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC, 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, 0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433, 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5, 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, 0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A, 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB, 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, 0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7, 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789, 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658, }; /* $Id: s128sbox.h 213 2003-12-16 04:27:12Z ggr $ */ /* Sbox for SOBER-128 */ /* * This is really the combination of two SBoxes; the least significant * 24 bits comes from: * 8->32 Sbox generated by Millan et. al. at Queensland University of * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter, * "On the Design of 8*32 S-boxes". Unpublished report, by the * Information Systems Research Centre, * Queensland University of Technology, 1999. * * The most significant 8 bits are the Skipjack "F table", which can be * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf . * In this optimised table, though, the intent is to XOR the word from * the table selected by the high byte with the input word. Thus, the * high byte is actually the Skipjack F-table entry XORED with its * table index. */ static const ulong32 Sbox[256] = { 0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4, 0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae, 0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c, 0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35, 0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e, 0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b, 0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f, 0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1, 0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd, 0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3, 0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f, 0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36, 0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf, 0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816, 0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d, 0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af, 0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6, 0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418, 0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0, 0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd, 0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088, 0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759, 0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895, 0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66, 0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc, 0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1, 0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911, 0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e, 0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515, 0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133, 0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226, 0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084, 0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb, 0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184, 0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420, 0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02, 0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655, 0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c, 0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418, 0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473, 0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a, 0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0, 0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21, 0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36, 0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5, 0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6, 0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0, 0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795, 0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0, 0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78, 0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da, 0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a, 0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118, 0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed, 0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd, 0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b, 0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921, 0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e, 0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5, 0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8, 0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376, 0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a, 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8, 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40, }; /* Implementation of SOBER-128 by Tom St Denis. * Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. */ const struct _prng_descriptor sober128_desc = { "sober128", 64, &sober128_start, &sober128_add_entropy, &sober128_ready, &sober128_read, }; const struct _prng_descriptor *prng_descriptor[] = { &sober128_desc }; /* don't change these... */ #define N 17 #define FOLD N /* how many iterations of folding to do */ #define INITKONST 0x6996c53a /* value of KONST to use during key loading */ #define KEYP 15 /* where to insert key words */ #define FOLDP 4 /* where to insert non-linear feedback */ #define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF)) static ulong32 BYTE2WORD(const unsigned char *b) { ulong32 t; LOAD32L(t, b); return t; } #define WORD2BYTE(w, b) STORE32L(b, w) static void XORWORD(ulong32 w, unsigned char *b) { ulong32 t; LOAD32L(t, b); t ^= w; STORE32L(t, b); } /* give correct offset for the current position of the register, * where logically R[0] is at position "zero". */ #define OFF(zero, i) (((zero)+(i)) % N) /* step the LFSR */ /* After stepping, "zero" moves right one place */ #define STEP(R,z) \ R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; static void cycle(ulong32 *R) { ulong32 t; int i; STEP(R,0); t = R[0]; for (i = 1; i < N; ++i) { R[i-1] = R[i]; } R[N-1] = t; } /* Return a non-linear function of some parts of the register. */ #define NLFUNC(c,z) \ { \ t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \ t ^= Sbox[(t >> 24) & 0xFF]; \ t = ROR(t, 8); \ t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \ t ^= Sbox[(t >> 24) & 0xFF]; \ t = t + c->R[OFF(z,13)]; \ } static ulong32 nltap(struct sober128_prng *c) { ulong32 t; NLFUNC(c, 0); return t; } /* initialise to known state */ int sober128_start(prng_state *prng) { int i; struct sober128_prng *c; c = &(prng->sober128); /* Register initialised to Fibonacci numbers */ c->R[0] = 1; c->R[1] = 1; for (i = 2; i < N; ++i) { c->R[i] = c->R[i-1] + c->R[i-2]; } c->konst = INITKONST; /* next add_entropy will be the key */ c->flag = 1; c->set = 0; return CRYPT_OK; } /* Save the current register state */ static void s128_savestate(struct sober128_prng *c) { int i; for (i = 0; i < N; ++i) { c->initR[i] = c->R[i]; } } /* initialise to previously saved register state */ static void s128_reloadstate(struct sober128_prng *c) { int i; for (i = 0; i < N; ++i) { c->R[i] = c->initR[i]; } } /* Initialise "konst" */ static void s128_genkonst(struct sober128_prng *c) { ulong32 newkonst; do { cycle(c->R); newkonst = nltap(c); } while ((newkonst & 0xFF000000) == 0); c->konst = newkonst; } /* Load key material into the register */ #define ADDKEY(k) \ c->R[KEYP] += (k); #define XORNL(nl) \ c->R[FOLDP] ^= (nl); /* nonlinear diffusion of register for key */ #define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t; static void s128_diffuse(struct sober128_prng *c) { ulong32 t; /* relies on FOLD == N == 17! */ DROUND(0); DROUND(1); DROUND(2); DROUND(3); DROUND(4); DROUND(5); DROUND(6); DROUND(7); DROUND(8); DROUND(9); DROUND(10); DROUND(11); DROUND(12); DROUND(13); DROUND(14); DROUND(15); DROUND(16); } int sober128_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng) { struct sober128_prng *c; ulong32 i, k; c = &(prng->sober128); if (c->flag == 1) { /* this is the first call to the add_entropy so this input is the key */ /* len must be multiple of 4 bytes */ assert ((len & 3) == 0); for (i = 0; i < len; i += 4) { k = BYTE2WORD(&buf[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(len); /* now diffuse */ s128_diffuse(c); s128_genkonst(c); s128_savestate(c); c->nbuf = 0; c->flag = 0; c->set = 1; } else { /* ok we are adding an IV then... */ s128_reloadstate(c); /* len must be multiple of 4 bytes */ assert ((len & 3) == 0); for (i = 0; i < len; i += 4) { k = BYTE2WORD(&buf[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(len); /* now diffuse */ s128_diffuse(c); c->nbuf = 0; } return CRYPT_OK; } int sober128_ready(prng_state *prng) { return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR; } /* XOR pseudo-random bytes into buffer */ #define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, buf+(z*4)); unsigned long sober128_read(unsigned char *buf, unsigned long nbytes, prng_state *prng) { struct sober128_prng *c; ulong32 t, tlen; c = &(prng->sober128); t = 0; tlen = nbytes; /* handle any previously buffered bytes */ while (c->nbuf != 0 && nbytes != 0) { *buf++ ^= c->sbuf & 0xFF; c->sbuf >>= 8; c->nbuf -= 8; --nbytes; } #ifndef SMALL_CODE /* do lots at a time, if there's enough to do */ while (nbytes >= N*4) { SROUND(0); SROUND(1); SROUND(2); SROUND(3); SROUND(4); SROUND(5); SROUND(6); SROUND(7); SROUND(8); SROUND(9); SROUND(10); SROUND(11); SROUND(12); SROUND(13); SROUND(14); SROUND(15); SROUND(16); buf += 4*N; nbytes -= 4*N; } #endif /* do small or odd size buffers the slow way */ while (4 <= nbytes) { cycle(c->R); t = nltap(c); XORWORD(t, buf); buf += 4; nbytes -= 4; } /* handle any trailing bytes */ if (nbytes != 0) { cycle(c->R); c->sbuf = nltap(c); c->nbuf = 32; while (c->nbuf != 0 && nbytes != 0) { *buf++ ^= c->sbuf & 0xFF; c->sbuf >>= 8; c->nbuf -= 8; --nbytes; } } return tlen; } /* SHA1 code by Tom St Denis */ const struct _hash_descriptor sha1_desc = { "sha1", 2, 20, 64, /* DER identifier */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 }, 15, &sha1_init, &sha1_process, &sha1_done, }; #define F0(x,y,z) (z ^ (x & (y ^ z))) #define F1(x,y,z) (x ^ y ^ z) #define F2(x,y,z) ((x & y) | (z & (x | y))) #define F3(x,y,z) (x ^ y ^ z) static void sha1_compress(hash_state *md, const unsigned char *buf) { ulong32 a,b,c,d,e,W[80],i; /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD32H(W[i], buf + (4*i)); } /* copy state */ a = md->sha1.state[0]; b = md->sha1.state[1]; c = md->sha1.state[2]; d = md->sha1.state[3]; e = md->sha1.state[4]; /* expand it */ for (i = 16; i < 80; i++) { W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); } /* compress */ /* round one */ #define FF0(a,b,c,d,e,i) e = (ROL(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROL(b, 30); #define FF1(a,b,c,d,e,i) e = (ROL(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROL(b, 30); #define FF2(a,b,c,d,e,i) e = (ROL(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROL(b, 30); #define FF3(a,b,c,d,e,i) e = (ROL(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROL(b, 30); for (i = 0; i < 20; ) { FF0(a,b,c,d,e,i++); FF0(e,a,b,c,d,i++); FF0(d,e,a,b,c,i++); FF0(c,d,e,a,b,i++); FF0(b,c,d,e,a,i++); } /* round two */ for (; i < 40; ) { FF1(a,b,c,d,e,i++); FF1(e,a,b,c,d,i++); FF1(d,e,a,b,c,i++); FF1(c,d,e,a,b,i++); FF1(b,c,d,e,a,i++); } /* round three */ for (; i < 60; ) { FF2(a,b,c,d,e,i++); FF2(e,a,b,c,d,i++); FF2(d,e,a,b,c,i++); FF2(c,d,e,a,b,i++); FF2(b,c,d,e,a,i++); } /* round four */ for (; i < 80; ) { FF3(a,b,c,d,e,i++); FF3(e,a,b,c,d,i++); FF3(d,e,a,b,c,i++); FF3(c,d,e,a,b,i++); FF3(b,c,d,e,a,i++); } #undef FF0 #undef FF1 #undef FF2 #undef FF3 /* store */ md->sha1.state[0] = md->sha1.state[0] + a; md->sha1.state[1] = md->sha1.state[1] + b; md->sha1.state[2] = md->sha1.state[2] + c; md->sha1.state[3] = md->sha1.state[3] + d; md->sha1.state[4] = md->sha1.state[4] + e; } void sha1_init(hash_state * md) { md->sha1.state[0] = 0x67452301UL; md->sha1.state[1] = 0xefcdab89UL; md->sha1.state[2] = 0x98badcfeUL; md->sha1.state[3] = 0x10325476UL; md->sha1.state[4] = 0xc3d2e1f0UL; md->sha1.curlen = 0; md->sha1.length = 0; } HASH_PROCESS(sha1_process, sha1_compress, sha1, 64) int sha1_done(hash_state * md, unsigned char *hash) { int i; /* * Assert there isn't an invalid argument */ assert (md->sha1.curlen < sizeof (md->sha1.buf)); /* increase the length of the message */ md->sha1.length += md->sha1.curlen * 8; /* append the '1' bit */ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->sha1.curlen > 56) { while (md->sha1.curlen < 64) { md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; } sha1_compress(md, md->sha1.buf); md->sha1.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->sha1.curlen < 56) { md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->sha1.length, md->sha1.buf+56); sha1_compress(md, md->sha1.buf); /* copy output */ for (i = 0; i < 5; i++) { STORE32H(md->sha1.state[i], hash+(4*i)); } return CRYPT_OK; } /* Submited by Dobes Vandermeer (dobes@smartt.com) */ /* (1) append zeros to the end of K to create a B byte string (e.g., if K is of length 20 bytes and B=64, then K will be appended with 44 zero bytes 0x00) (2) XOR (bitwise exclusive-OR) the B byte string computed in step (1) with ipad (ipad = the byte 0x36 repeated B times) (3) append the stream of data 'text' to the B byte string resulting from step (2) (4) apply H to the stream generated in step (3) (5) XOR (bitwise exclusive-OR) the B byte string computed in step (1) with opad (opad = the byte 0x5C repeated B times.) (6) append the H result from step (4) to the B byte string resulting from step (5) (7) apply H to the stream generated in step (6) and output the result */ int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) { unsigned char buf[128]; - unsigned long hashsize; unsigned long i; int err; hmac->hash = hash; - hashsize = hash_descriptor[hash]->hashsize; /* valid key length? */ assert (keylen > 0); assert (keylen <= hash_descriptor[hash]->blocksize); memcpy(hmac->key, key, (size_t)keylen); if(keylen < hash_descriptor[hash]->blocksize) { memset((hmac->key) + keylen, 0, (size_t)(hash_descriptor[hash]->blocksize - keylen)); } // Create the initial vector for step (3) for(i=0; i < hash_descriptor[hash]->blocksize; i++) { buf[i] = hmac->key[i] ^ 0x36; } // Pre-pend that to the hash data hash_descriptor[hash]->init(&hmac->md); err = hash_descriptor[hash]->process(&hmac->md, buf, hash_descriptor[hash]->blocksize); return err; } int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len) { return hash_descriptor[hmac->hash]->process(&hmac->md, buf, len); } /* Submited by Dobes Vandermeer (dobes@smartt.com) */ /* (1) append zeros to the end of K to create a B byte string (e.g., if K is of length 20 bytes and B=64, then K will be appended with 44 zero bytes 0x00) (2) XOR (bitwise exclusive-OR) the B byte string computed in step (1) with ipad (ipad = the byte 0x36 repeated B times) (3) append the stream of data 'text' to the B byte string resulting from step (2) (4) apply H to the stream generated in step (3) (5) XOR (bitwise exclusive-OR) the B byte string computed in step (1) with opad (opad = the byte 0x5C repeated B times.) (6) append the H result from step (4) to the B byte string resulting from step (5) (7) apply H to the stream generated in step (6) and output the result */ int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen) { unsigned char buf[128]; unsigned char isha[256]; unsigned long hashsize, i; int hash, err; /* test hash */ hash = hmac->hash; /* get the hash message digest size */ hashsize = hash_descriptor[hash]->hashsize; // Get the hash of the first HMAC vector plus the data if ((err = hash_descriptor[hash]->done(&hmac->md, isha)) != CRYPT_OK) { goto __ERR; } // Create the second HMAC vector vector for step (3) for(i=0; i < hash_descriptor[hash]->blocksize; i++) { buf[i] = hmac->key[i] ^ 0x5C; } // Now calculate the "outer" hash for step (5), (6), and (7) hash_descriptor[hash]->init(&hmac->md); if ((err = hash_descriptor[hash]->process(&hmac->md, buf, hash_descriptor[hash]->blocksize)) != CRYPT_OK) { goto __ERR; } if ((err = hash_descriptor[hash]->process(&hmac->md, isha, hashsize)) != CRYPT_OK) { goto __ERR; } if ((err = hash_descriptor[hash]->done(&hmac->md, buf)) != CRYPT_OK) { goto __ERR; } // copy to output for (i = 0; i < hashsize && i < *outlen; i++) { hashOut[i] = buf[i]; } *outlen = i; err = CRYPT_OK; __ERR: return err; } const struct _hash_descriptor *hash_descriptor[] = { &sha1_desc }; /* portable way to get secure random bits to feed a PRNG */ /* on *NIX read /dev/random */ static unsigned long rng_nix(unsigned char *buf, unsigned long len, void (*callback)(void)) { int fd; unsigned long rb = 0; fd = open ("/dev/urandom", O_RDONLY); if (fd >= 0) { rb = (unsigned long)read (fd, buf, len); close (fd); } return (rb); } /* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */ #if defined(XCLOCKS_PER_SEC) #define ANSI_RNG static unsigned long rng_ansic(unsigned char *buf, unsigned long len, void (*callback)(void)) { clock_t t1; int l, acc, bits, a, b; if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) { return 0; } l = len; bits = 8; acc = a = b = 0; while (len--) { if (callback != NULL) callback(); while (bits--) { do { t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1; t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1; } while (a == b); acc = (acc << 1) | a; } *buf++ = acc; acc = 0; bits = 8; } acc = bits = a = b = 0; return l; } #endif unsigned long rng_get_bytes(unsigned char *buf, unsigned long len, void (*callback)(void)) { unsigned long x; x = rng_nix(buf, len, callback); if (x != 0) { return x; } #ifdef ANSI_RNG x = rng_ansic(buf, len, callback); if (x != 0) { return x; } #endif return 0; } int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)) { unsigned char buf[258]; int err; if (bits < 64 || bits > 1024) { return CRYPT_INVALID_PRNGSIZE; } if ((err = prng_descriptor[wprng]->start(prng)) != CRYPT_OK) { return err; } bits = ((bits/8)+((bits&7)!=0?1:0)) * 2; if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) { return CRYPT_ERROR_READPRNG; } if ((err = prng_descriptor[wprng]->add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) { return err; } if ((err = prng_descriptor[wprng]->ready(prng)) != CRYPT_OK) { return err; } return CRYPT_OK; } diff --git a/exec/main.c b/exec/main.c index 62ca494f..bcc0da35 100644 --- a/exec/main.c +++ b/exec/main.c @@ -1,1519 +1,1516 @@ /* * Copyright (c) 2002-2006 MontaVista Software, Inc. * Copyright (c) 2006-2009 Red Hat, Inc. * * All rights reserved. * * Author: Steven Dake (sdake@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** * \mainpage Corosync * * This is the doxygen generated developer documentation for the Corosync * project. For more information about Corosync, please see the project * web site, corosync.org. * * \section license License * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "quorum.h" #include "totemsrp.h" #include "mainconfig.h" #include "totemconfig.h" #include "main.h" #include "sync.h" #include "syncv2.h" #include "timer.h" #include "util.h" #include "apidef.h" #include "service.h" #include "schedwrk.h" #include "evil.h" #ifdef HAVE_SMALL_MEMORY_FOOTPRINT #define IPC_LOGSYS_SIZE 1024*64 #else #define IPC_LOGSYS_SIZE 8192*128 #endif LOGSYS_DECLARE_SYSTEM ("corosync", LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_THREADED | LOGSYS_MODE_FORK, 0, NULL, LOG_INFO, LOG_DAEMON, LOG_INFO, NULL, IPC_LOGSYS_SIZE); LOGSYS_DECLARE_SUBSYS ("MAIN"); #define SERVER_BACKLOG 5 static int sched_priority = 0; static unsigned int service_count = 32; static struct totem_logging_configuration totem_logging_configuration; static int num_config_modules; static struct config_iface_ver0 *config_modules[MAX_DYNAMIC_SERVICES]; static struct objdb_iface_ver0 *objdb = NULL; static struct corosync_api_v1 *api = NULL; static enum cs_sync_mode minimum_sync_mode; static int sync_in_process = 1; static qb_loop_t *corosync_poll_handle; struct sched_param global_sched_param; static hdb_handle_t object_memb_handle; static corosync_timer_handle_t corosync_stats_timer_handle; static const char *corosync_lock_file = LOCALSTATEDIR"/run/corosync.pid"; qb_loop_t *cs_poll_handle_get (void) { return (corosync_poll_handle); } int cs_poll_dispatch_add (qb_loop_t * handle, int fd, int events, void *data, int (*dispatch_fn) (int fd, int revents, void *data)) { return qb_loop_poll_add(handle, QB_LOOP_MED, fd, events, data, dispatch_fn); } int cs_poll_dispatch_delete(qb_loop_t * handle, int fd) { return qb_loop_poll_del(handle, fd); } void corosync_state_dump (void) { int i; for (i = 0; i < SERVICE_HANDLER_MAXIMUM_COUNT; i++) { if (ais_service[i] && ais_service[i]->exec_dump_fn) { ais_service[i]->exec_dump_fn (); } } } static void unlink_all_completed (void) { api->timer_delete (corosync_stats_timer_handle); qb_loop_stop (corosync_poll_handle); } void corosync_shutdown_request (void) { corosync_service_unlink_all (api, unlink_all_completed); } static int32_t sig_diag_handler (int num, void *data) { corosync_state_dump (); logsys_log_rec_store (LOCALSTATEDIR "/lib/corosync/fdata"); return 0; } static int32_t sig_exit_handler (int num, void *data) { corosync_service_unlink_all (api, unlink_all_completed); return 0; } static void sigsegv_handler (int num) { (void)signal (SIGSEGV, SIG_DFL); logsys_atexit(); logsys_log_rec_store (LOCALSTATEDIR "/lib/corosync/fdata"); raise (SIGSEGV); } static void sigabrt_handler (int num) { (void)signal (SIGABRT, SIG_DFL); logsys_atexit(); logsys_log_rec_store (LOCALSTATEDIR "/lib/corosync/fdata"); raise (SIGABRT); } #define LOCALHOST_IP inet_addr("127.0.0.1") static hdb_handle_t corosync_group_handle; static struct totempg_group corosync_group = { .group = "a", .group_len = 1 }; static void serialize_lock (void) { } static void serialize_unlock (void) { } static void corosync_sync_completed (void) { log_printf (LOGSYS_LEVEL_NOTICE, "Completed service synchronization, ready to provide service.\n"); sync_in_process = 0; cs_ipcs_sync_state_changed(sync_in_process); } static int corosync_sync_callbacks_retrieve (int sync_id, struct sync_callbacks *callbacks) { unsigned int ais_service_index; int res; for (ais_service_index = 0; ais_service_index < SERVICE_HANDLER_MAXIMUM_COUNT; ais_service_index++) { if (ais_service[ais_service_index] != NULL && (ais_service[ais_service_index]->sync_mode == CS_SYNC_V1 || ais_service[ais_service_index]->sync_mode == CS_SYNC_V1_APIV2)) { if (ais_service_index == sync_id) { break; } } } /* * Try to load backwards compat sync engines */ if (ais_service_index == SERVICE_HANDLER_MAXIMUM_COUNT) { res = evil_callbacks_load (sync_id, callbacks); return (res); } callbacks->name = ais_service[ais_service_index]->name; callbacks->sync_init_api.sync_init_v1 = ais_service[ais_service_index]->sync_init; callbacks->api_version = 1; if (ais_service[ais_service_index]->sync_mode == CS_SYNC_V1_APIV2) { callbacks->api_version = 2; } callbacks->sync_process = ais_service[ais_service_index]->sync_process; callbacks->sync_activate = ais_service[ais_service_index]->sync_activate; callbacks->sync_abort = ais_service[ais_service_index]->sync_abort; return (0); } static int corosync_sync_v2_callbacks_retrieve ( int service_id, struct sync_callbacks *callbacks) { int res; if (minimum_sync_mode == CS_SYNC_V2 && service_id == CLM_SERVICE && ais_service[CLM_SERVICE] == NULL) { res = evil_callbacks_load (service_id, callbacks); return (res); } if (minimum_sync_mode == CS_SYNC_V2 && service_id == EVT_SERVICE && ais_service[EVT_SERVICE] == NULL) { res = evil_callbacks_load (service_id, callbacks); return (res); } if (ais_service[service_id] == NULL) { return (-1); } if (minimum_sync_mode == CS_SYNC_V1 && ais_service[service_id]->sync_mode != CS_SYNC_V2) { return (-1); } callbacks->name = ais_service[service_id]->name; callbacks->api_version = 1; if (ais_service[service_id]->sync_mode == CS_SYNC_V1_APIV2) { callbacks->api_version = 2; } callbacks->sync_init_api.sync_init_v1 = ais_service[service_id]->sync_init; callbacks->sync_process = ais_service[service_id]->sync_process; callbacks->sync_activate = ais_service[service_id]->sync_activate; callbacks->sync_abort = ais_service[service_id]->sync_abort; return (0); } static struct memb_ring_id corosync_ring_id; static void member_object_joined (unsigned int nodeid) { hdb_handle_t object_find_handle; hdb_handle_t object_node_handle; char * nodeint_str; char nodeid_str[64]; unsigned int key_incr_dummy; snprintf (nodeid_str, 64, "%d", nodeid); objdb->object_find_create ( object_memb_handle, nodeid_str, strlen (nodeid_str), &object_find_handle); if (objdb->object_find_next (object_find_handle, &object_node_handle) == 0) { objdb->object_key_increment (object_node_handle, "join_count", strlen("join_count"), &key_incr_dummy); objdb->object_key_replace (object_node_handle, "status", strlen("status"), "joined", strlen("joined")); } else { nodeint_str = (char*)api->totem_ifaces_print (nodeid); objdb->object_create (object_memb_handle, &object_node_handle, nodeid_str, strlen (nodeid_str)); objdb->object_key_create_typed (object_node_handle, "ip", nodeint_str, strlen(nodeint_str), OBJDB_VALUETYPE_STRING); key_incr_dummy = 1; objdb->object_key_create_typed (object_node_handle, "join_count", &key_incr_dummy, sizeof (key_incr_dummy), OBJDB_VALUETYPE_UINT32); objdb->object_key_create_typed (object_node_handle, "status", "joined", strlen("joined"), OBJDB_VALUETYPE_STRING); } } static void member_object_left (unsigned int nodeid) { hdb_handle_t object_find_handle; hdb_handle_t object_node_handle; char nodeid_str[64]; snprintf (nodeid_str, 64, "%u", nodeid); objdb->object_find_create ( object_memb_handle, nodeid_str, strlen (nodeid_str), &object_find_handle); if (objdb->object_find_next (object_find_handle, &object_node_handle) == 0) { objdb->object_key_replace (object_node_handle, "status", strlen("status"), "left", strlen("left")); } } static void confchg_fn ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id) { int i; int abort_activate = 0; if (sync_in_process == 1) { abort_activate = 1; } sync_in_process = 1; cs_ipcs_sync_state_changed(sync_in_process); memcpy (&corosync_ring_id, ring_id, sizeof (struct memb_ring_id)); for (i = 0; i < left_list_entries; i++) { member_object_left (left_list[i]); } for (i = 0; i < joined_list_entries; i++) { member_object_joined (joined_list[i]); } /* * Call configuration change for all services */ for (i = 0; i < service_count; i++) { if (ais_service[i] && ais_service[i]->confchg_fn) { ais_service[i]->confchg_fn (configuration_type, member_list, member_list_entries, left_list, left_list_entries, joined_list, joined_list_entries, ring_id); } } if (abort_activate) { sync_v2_abort (); } if (minimum_sync_mode == CS_SYNC_V2 && configuration_type == TOTEM_CONFIGURATION_TRANSITIONAL) { sync_v2_save_transitional (member_list, member_list_entries, ring_id); } if (minimum_sync_mode == CS_SYNC_V2 && configuration_type == TOTEM_CONFIGURATION_REGULAR) { sync_v2_start (member_list, member_list_entries, ring_id); } } static void priv_drop (void) { return; /* TODO: we are still not dropping privs */ } static void corosync_tty_detach (void) { FILE *r; /* * Disconnect from TTY if this is not a debug run */ switch (fork ()) { case -1: corosync_exit_error (AIS_DONE_FORK); break; case 0: /* * child which is disconnected, run this process */ break; default: exit (0); break; } /* Create new session */ (void)setsid(); /* * Map stdin/out/err to /dev/null. */ r = freopen("/dev/null", "r", stdin); if (r == NULL) { corosync_exit_error (AIS_DONE_STD_TO_NULL_REDIR); } r = freopen("/dev/null", "a", stderr); if (r == NULL) { corosync_exit_error (AIS_DONE_STD_TO_NULL_REDIR); } r = freopen("/dev/null", "a", stdout); if (r == NULL) { corosync_exit_error (AIS_DONE_STD_TO_NULL_REDIR); } } static void corosync_mlockall (void) { #if !defined(COROSYNC_BSD) || defined(COROSYNC_FREEBSD_GE_8) int res; #endif struct rlimit rlimit; rlimit.rlim_cur = RLIM_INFINITY; rlimit.rlim_max = RLIM_INFINITY; #ifndef COROSYNC_SOLARIS setrlimit (RLIMIT_MEMLOCK, &rlimit); #else setrlimit (RLIMIT_VMEM, &rlimit); #endif #if defined(COROSYNC_BSD) && !defined(COROSYNC_FREEBSD_GE_8) /* under FreeBSD < 8 a process with locked page cannot call dlopen * code disabled until FreeBSD bug i386/93396 was solved */ log_printf (LOGSYS_LEVEL_WARNING, "Could not lock memory of service to avoid page faults\n"); #else res = mlockall (MCL_CURRENT | MCL_FUTURE); if (res == -1) { LOGSYS_PERROR (errno, LOGSYS_LEVEL_WARNING, "Could not lock memory of service to avoid page faults"); }; #endif } static void corosync_totem_stats_updater (void *data) { totempg_stats_t * stats; uint32_t mtt_rx_token; uint32_t total_mtt_rx_token; uint32_t avg_backlog_calc; uint32_t total_backlog_calc; uint32_t avg_token_holdtime; uint32_t total_token_holdtime; int t, prev; int32_t token_count; uint32_t firewall_enabled_or_nic_failure; stats = api->totem_get_stats(); objdb->object_key_replace (stats->hdr.handle, "msg_reserved", strlen("msg_reserved"), &stats->msg_reserved, sizeof (stats->msg_reserved)); objdb->object_key_replace (stats->hdr.handle, "msg_queue_avail", strlen("msg_queue_avail"), &stats->msg_queue_avail, sizeof (stats->msg_queue_avail)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "orf_token_tx", strlen("orf_token_tx"), &stats->mrp->srp->orf_token_tx, sizeof (stats->mrp->srp->orf_token_tx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "orf_token_rx", strlen("orf_token_rx"), &stats->mrp->srp->orf_token_rx, sizeof (stats->mrp->srp->orf_token_rx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "memb_merge_detect_tx", strlen("memb_merge_detect_tx"), &stats->mrp->srp->memb_merge_detect_tx, sizeof (stats->mrp->srp->memb_merge_detect_tx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "memb_merge_detect_rx", strlen("memb_merge_detect_rx"), &stats->mrp->srp->memb_merge_detect_rx, sizeof (stats->mrp->srp->memb_merge_detect_rx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "memb_join_tx", strlen("memb_join_tx"), &stats->mrp->srp->memb_join_tx, sizeof (stats->mrp->srp->memb_join_tx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "memb_join_rx", strlen("memb_join_rx"), &stats->mrp->srp->memb_join_rx, sizeof (stats->mrp->srp->memb_join_rx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "mcast_tx", strlen("mcast_tx"), &stats->mrp->srp->mcast_tx, sizeof (stats->mrp->srp->mcast_tx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "mcast_retx", strlen("mcast_retx"), &stats->mrp->srp->mcast_retx, sizeof (stats->mrp->srp->mcast_retx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "mcast_rx", strlen("mcast_rx"), &stats->mrp->srp->mcast_rx, sizeof (stats->mrp->srp->mcast_rx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "memb_commit_token_tx", strlen("memb_commit_token_tx"), &stats->mrp->srp->memb_commit_token_tx, sizeof (stats->mrp->srp->memb_commit_token_tx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "memb_commit_token_rx", strlen("memb_commit_token_rx"), &stats->mrp->srp->memb_commit_token_rx, sizeof (stats->mrp->srp->memb_commit_token_rx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "token_hold_cancel_tx", strlen("token_hold_cancel_tx"), &stats->mrp->srp->token_hold_cancel_tx, sizeof (stats->mrp->srp->token_hold_cancel_tx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "token_hold_cancel_rx", strlen("token_hold_cancel_rx"), &stats->mrp->srp->token_hold_cancel_rx, sizeof (stats->mrp->srp->token_hold_cancel_rx)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "operational_entered", strlen("operational_entered"), &stats->mrp->srp->operational_entered, sizeof (stats->mrp->srp->operational_entered)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "operational_token_lost", strlen("operational_token_lost"), &stats->mrp->srp->operational_token_lost, sizeof (stats->mrp->srp->operational_token_lost)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "gather_entered", strlen("gather_entered"), &stats->mrp->srp->gather_entered, sizeof (stats->mrp->srp->gather_entered)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "gather_token_lost", strlen("gather_token_lost"), &stats->mrp->srp->gather_token_lost, sizeof (stats->mrp->srp->gather_token_lost)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "commit_entered", strlen("commit_entered"), &stats->mrp->srp->commit_entered, sizeof (stats->mrp->srp->commit_entered)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "commit_token_lost", strlen("commit_token_lost"), &stats->mrp->srp->commit_token_lost, sizeof (stats->mrp->srp->commit_token_lost)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "recovery_entered", strlen("recovery_entered"), &stats->mrp->srp->recovery_entered, sizeof (stats->mrp->srp->recovery_entered)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "recovery_token_lost", strlen("recovery_token_lost"), &stats->mrp->srp->recovery_token_lost, sizeof (stats->mrp->srp->recovery_token_lost)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "consensus_timeouts", strlen("consensus_timeouts"), &stats->mrp->srp->consensus_timeouts, sizeof (stats->mrp->srp->consensus_timeouts)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "rx_msg_dropped", strlen("rx_msg_dropped"), &stats->mrp->srp->rx_msg_dropped, sizeof (stats->mrp->srp->rx_msg_dropped)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "continuous_gather", strlen("continuous_gather"), &stats->mrp->srp->continuous_gather, sizeof (stats->mrp->srp->continuous_gather)); firewall_enabled_or_nic_failure = (stats->mrp->srp->continuous_gather > MAX_NO_CONT_GATHER ? 1 : 0); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "firewall_enabled_or_nic_failure", strlen("firewall_enabled_or_nic_failure"), &firewall_enabled_or_nic_failure, sizeof (firewall_enabled_or_nic_failure)); total_mtt_rx_token = 0; total_token_holdtime = 0; total_backlog_calc = 0; token_count = 0; t = stats->mrp->srp->latest_token; while (1) { if (t == 0) prev = TOTEM_TOKEN_STATS_MAX - 1; else prev = t - 1; if (prev == stats->mrp->srp->earliest_token) break; /* if tx == 0, then dropped token (not ours) */ if (stats->mrp->srp->token[t].tx != 0 || (stats->mrp->srp->token[t].rx - stats->mrp->srp->token[prev].rx) > 0 ) { total_mtt_rx_token += (stats->mrp->srp->token[t].rx - stats->mrp->srp->token[prev].rx); total_token_holdtime += (stats->mrp->srp->token[t].tx - stats->mrp->srp->token[t].rx); total_backlog_calc += stats->mrp->srp->token[t].backlog_calc; token_count++; } t = prev; } if (token_count) { mtt_rx_token = (total_mtt_rx_token / token_count); avg_backlog_calc = (total_backlog_calc / token_count); avg_token_holdtime = (total_token_holdtime / token_count); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "mtt_rx_token", strlen("mtt_rx_token"), &mtt_rx_token, sizeof (mtt_rx_token)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "avg_token_workload", strlen("avg_token_workload"), &avg_token_holdtime, sizeof (avg_token_holdtime)); objdb->object_key_replace (stats->mrp->srp->hdr.handle, "avg_backlog_calc", strlen("avg_backlog_calc"), &avg_backlog_calc, sizeof (avg_backlog_calc)); } cs_ipcs_stats_update(); api->timer_add_duration (1500 * MILLI_2_NANO_SECONDS, NULL, corosync_totem_stats_updater, &corosync_stats_timer_handle); } static void corosync_totem_stats_init (void) { totempg_stats_t * stats; hdb_handle_t object_find_handle; hdb_handle_t object_runtime_handle; hdb_handle_t object_totem_handle; uint32_t zero_32 = 0; uint64_t zero_64 = 0; stats = api->totem_get_stats(); objdb->object_find_create ( OBJECT_PARENT_HANDLE, "runtime", strlen ("runtime"), &object_find_handle); if (objdb->object_find_next (object_find_handle, &object_runtime_handle) == 0) { objdb->object_create (object_runtime_handle, &object_totem_handle, "totem", strlen ("totem")); objdb->object_create (object_totem_handle, &stats->hdr.handle, "pg", strlen ("pg")); objdb->object_create (stats->hdr.handle, &stats->mrp->hdr.handle, "mrp", strlen ("mrp")); objdb->object_create (stats->mrp->hdr.handle, &stats->mrp->srp->hdr.handle, "srp", strlen ("srp")); objdb->object_key_create_typed (stats->hdr.handle, "msg_reserved", &stats->msg_reserved, sizeof (stats->msg_reserved), OBJDB_VALUETYPE_UINT32); objdb->object_key_create_typed (stats->hdr.handle, "msg_queue_avail", &stats->msg_queue_avail, sizeof (stats->msg_queue_avail), OBJDB_VALUETYPE_UINT32); /* Members object */ objdb->object_create (stats->mrp->srp->hdr.handle, &object_memb_handle, "members", strlen ("members")); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "orf_token_tx", &stats->mrp->srp->orf_token_tx, sizeof (stats->mrp->srp->orf_token_tx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "orf_token_rx", &stats->mrp->srp->orf_token_rx, sizeof (stats->mrp->srp->orf_token_rx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "memb_merge_detect_tx", &stats->mrp->srp->memb_merge_detect_tx, sizeof (stats->mrp->srp->memb_merge_detect_tx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "memb_merge_detect_rx", &stats->mrp->srp->memb_merge_detect_rx, sizeof (stats->mrp->srp->memb_merge_detect_rx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "memb_join_tx", &stats->mrp->srp->memb_join_tx, sizeof (stats->mrp->srp->memb_join_tx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "memb_join_rx", &stats->mrp->srp->memb_join_rx, sizeof (stats->mrp->srp->memb_join_rx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "mcast_tx", &stats->mrp->srp->mcast_tx, sizeof (stats->mrp->srp->mcast_tx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "mcast_retx", &stats->mrp->srp->mcast_retx, sizeof (stats->mrp->srp->mcast_retx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "mcast_rx", &stats->mrp->srp->mcast_rx, sizeof (stats->mrp->srp->mcast_rx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "memb_commit_token_tx", &stats->mrp->srp->memb_commit_token_tx, sizeof (stats->mrp->srp->memb_commit_token_tx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "memb_commit_token_rx", &stats->mrp->srp->memb_commit_token_rx, sizeof (stats->mrp->srp->memb_commit_token_rx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "token_hold_cancel_tx", &stats->mrp->srp->token_hold_cancel_tx, sizeof (stats->mrp->srp->token_hold_cancel_tx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "token_hold_cancel_rx", &stats->mrp->srp->token_hold_cancel_rx, sizeof (stats->mrp->srp->token_hold_cancel_rx), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "operational_entered", &stats->mrp->srp->operational_entered, sizeof (stats->mrp->srp->operational_entered), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "operational_token_lost", &stats->mrp->srp->operational_token_lost, sizeof (stats->mrp->srp->operational_token_lost), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "gather_entered", &stats->mrp->srp->gather_entered, sizeof (stats->mrp->srp->gather_entered), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "gather_token_lost", &stats->mrp->srp->gather_token_lost, sizeof (stats->mrp->srp->gather_token_lost), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "commit_entered", &stats->mrp->srp->commit_entered, sizeof (stats->mrp->srp->commit_entered), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "commit_token_lost", &stats->mrp->srp->commit_token_lost, sizeof (stats->mrp->srp->commit_token_lost), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "recovery_entered", &stats->mrp->srp->recovery_entered, sizeof (stats->mrp->srp->recovery_entered), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "recovery_token_lost", &stats->mrp->srp->recovery_token_lost, sizeof (stats->mrp->srp->recovery_token_lost), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "consensus_timeouts", &stats->mrp->srp->consensus_timeouts, sizeof (stats->mrp->srp->consensus_timeouts), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "mtt_rx_token", &zero_32, sizeof (zero_32), OBJDB_VALUETYPE_UINT32); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "avg_token_workload", &zero_32, sizeof (zero_32), OBJDB_VALUETYPE_UINT32); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "avg_backlog_calc", &zero_32, sizeof (zero_32), OBJDB_VALUETYPE_UINT32); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "rx_msg_dropped", &zero_64, sizeof (zero_64), OBJDB_VALUETYPE_UINT64); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "continuous_gather", &zero_32, sizeof (zero_32), OBJDB_VALUETYPE_UINT32); objdb->object_key_create_typed (stats->mrp->srp->hdr.handle, "firewall_enabled_or_nic_failure", &zero_32, sizeof (zero_32), OBJDB_VALUETYPE_UINT32); } /* start stats timer */ api->timer_add_duration (1500 * MILLI_2_NANO_SECONDS, NULL, corosync_totem_stats_updater, &corosync_stats_timer_handle); } static void deliver_fn ( unsigned int nodeid, const void *msg, unsigned int msg_len, int endian_conversion_required) { const struct qb_ipc_request_header *header; int32_t service; int32_t fn_id; uint32_t id; - uint32_t size; uint32_t key_incr_dummy; header = msg; if (endian_conversion_required) { id = swab32 (header->id); - size = swab32 (header->size); } else { id = header->id; - size = header->size; } /* * Call the proper executive handler */ service = id >> 16; fn_id = id & 0xffff; if (ais_service[service] == NULL && service == EVT_SERVICE) { evil_deliver_fn (nodeid, service, fn_id, msg, endian_conversion_required); } if (!ais_service[service]) { return; } if (fn_id >= ais_service[service]->exec_engine_count) { log_printf(LOGSYS_LEVEL_WARNING, "discarded unknown message %d for service %d (max id %d)", fn_id, service, ais_service[service]->exec_engine_count); return; } objdb->object_key_increment (service_stats_handle[service][fn_id], "rx", strlen("rx"), &key_incr_dummy); if (endian_conversion_required) { assert(ais_service[service]->exec_engine[fn_id].exec_endian_convert_fn != NULL); ais_service[service]->exec_engine[fn_id].exec_endian_convert_fn ((void *)msg); } ais_service[service]->exec_engine[fn_id].exec_handler_fn (msg, nodeid); } void main_get_config_modules(struct config_iface_ver0 ***modules, int *num) { *modules = config_modules; *num = num_config_modules; } int main_mcast ( const struct iovec *iovec, unsigned int iov_len, unsigned int guarantee) { const struct qb_ipc_request_header *req = iovec->iov_base; int32_t service; int32_t fn_id; uint32_t key_incr_dummy; service = req->id >> 16; fn_id = req->id & 0xffff; if (ais_service[service]) { objdb->object_key_increment (service_stats_handle[service][fn_id], "tx", strlen("tx"), &key_incr_dummy); } return (totempg_groups_mcast_joined (corosync_group_handle, iovec, iov_len, guarantee)); } static qb_loop_timer_handle recheck_the_q_level_timer; void corosync_recheck_the_q_level(void *data) { totempg_check_q_level(corosync_group_handle); if (cs_ipcs_q_level_get() == TOTEM_Q_LEVEL_CRITICAL) { qb_loop_timer_add(cs_poll_handle_get(), QB_LOOP_MED, 1*QB_TIME_NS_IN_MSEC, NULL, corosync_recheck_the_q_level, &recheck_the_q_level_timer); } } struct sending_allowed_private_data_struct { int reserved_msgs; }; int corosync_sending_allowed ( unsigned int service, unsigned int id, const void *msg, void *sending_allowed_private_data) { struct sending_allowed_private_data_struct *pd = (struct sending_allowed_private_data_struct *)sending_allowed_private_data; struct iovec reserve_iovec; struct qb_ipc_request_header *header = (struct qb_ipc_request_header *)msg; int sending_allowed; reserve_iovec.iov_base = (char *)header; reserve_iovec.iov_len = header->size; pd->reserved_msgs = totempg_groups_joined_reserve ( corosync_group_handle, &reserve_iovec, 1); if (pd->reserved_msgs == -1) { return -EINVAL; } sending_allowed = QB_FALSE; if (corosync_quorum_is_quorate() == 1 || ais_service[service]->allow_inquorate == CS_LIB_ALLOW_INQUORATE) { // we are quorate // now check flow control if (ais_service[service]->lib_engine[id].flow_control == CS_LIB_FLOW_CONTROL_NOT_REQUIRED) { sending_allowed = QB_TRUE; } else if (pd->reserved_msgs && sync_in_process == 0) { sending_allowed = QB_TRUE; } else if (pd->reserved_msgs == 0) { return -ENOBUFS; } else /* (sync_in_process) */ { return -EINPROGRESS; } } else { return -EHOSTUNREACH; } return (sending_allowed); } void corosync_sending_allowed_release (void *sending_allowed_private_data) { struct sending_allowed_private_data_struct *pd = (struct sending_allowed_private_data_struct *)sending_allowed_private_data; if (pd->reserved_msgs == -1) { return; } totempg_groups_joined_release (pd->reserved_msgs); } int message_source_is_local (const mar_message_source_t *source) { int ret = 0; assert (source != NULL); if (source->nodeid == totempg_my_nodeid_get ()) { ret = 1; } return ret; } void message_source_set ( mar_message_source_t *source, void *conn) { assert ((source != NULL) && (conn != NULL)); memset (source, 0, sizeof (mar_message_source_t)); source->nodeid = totempg_my_nodeid_get (); source->conn = conn; } static void corosync_setscheduler (void) { #if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX) && defined(HAVE_SCHED_SETSCHEDULER) int res; sched_priority = sched_get_priority_max (SCHED_RR); if (sched_priority != -1) { global_sched_param.sched_priority = sched_priority; res = sched_setscheduler (0, SCHED_RR, &global_sched_param); if (res == -1) { LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "Could not set SCHED_RR at priority %d", global_sched_param.sched_priority); global_sched_param.sched_priority = 0; logsys_thread_priority_set (SCHED_OTHER, NULL, 1); } else { /* * Turn on SCHED_RR in logsys system */ res = logsys_thread_priority_set (SCHED_RR, &global_sched_param, 10); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "Could not set logsys thread priority." " Can't continue because of priority inversions."); corosync_exit_error (AIS_DONE_LOGSETUP); } } } else { LOGSYS_PERROR (errno, LOGSYS_LEVEL_WARNING, "Could not get maximum scheduler priority"); sched_priority = 0; } #else log_printf(LOGSYS_LEVEL_WARNING, "The Platform is missing process priority setting features. Leaving at default."); #endif } static void fplay_key_change_notify_fn ( object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_len, const void *key_value_pt, size_t key_value_len, void *priv_data_pt) { if (key_len == strlen ("dump_flight_data") && memcmp ("dump_flight_data", key_name_pt, key_len) == 0) { logsys_log_rec_store (LOCALSTATEDIR "/lib/corosync/fdata"); } if (key_len == strlen ("dump_state") && memcmp ("dump_state", key_name_pt, key_len) == 0) { corosync_state_dump (); } } static void corosync_fplay_control_init (void) { hdb_handle_t object_find_handle; hdb_handle_t object_runtime_handle; hdb_handle_t object_blackbox_handle; objdb->object_find_create (OBJECT_PARENT_HANDLE, "runtime", strlen ("runtime"), &object_find_handle); if (objdb->object_find_next (object_find_handle, &object_runtime_handle) != 0) { return; } objdb->object_create (object_runtime_handle, &object_blackbox_handle, "blackbox", strlen ("blackbox")); objdb->object_key_create_typed (object_blackbox_handle, "dump_flight_data", "no", strlen("no"), OBJDB_VALUETYPE_STRING); objdb->object_key_create_typed (object_blackbox_handle, "dump_state", "no", strlen("no"), OBJDB_VALUETYPE_STRING); objdb->object_track_start (object_blackbox_handle, OBJECT_TRACK_DEPTH_RECURSIVE, fplay_key_change_notify_fn, NULL, NULL, NULL, NULL); } static void main_service_ready (void) { int res; /* * This must occur after totempg is initialized because "this_ip" must be set */ res = corosync_service_defaults_link_and_init (api); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "Could not initialize default services\n"); corosync_exit_error (AIS_DONE_INIT_SERVICES); } evil_init (api); cs_ipcs_init(); corosync_totem_stats_init (); corosync_fplay_control_init (); if (minimum_sync_mode == CS_SYNC_V2) { log_printf (LOGSYS_LEVEL_NOTICE, "Compatibility mode set to none. Using V2 of the synchronization engine.\n"); sync_v2_init ( corosync_sync_v2_callbacks_retrieve, corosync_sync_completed); } else if (minimum_sync_mode == CS_SYNC_V1) { log_printf (LOGSYS_LEVEL_NOTICE, "Compatibility mode set to whitetank. Using V1 and V2 of the synchronization engine.\n"); sync_register ( corosync_sync_callbacks_retrieve, sync_v2_memb_list_determine, sync_v2_memb_list_abort, sync_v2_start); sync_v2_init ( corosync_sync_v2_callbacks_retrieve, corosync_sync_completed); } } static enum e_ais_done corosync_flock (const char *lockfile, pid_t pid) { struct flock lock; enum e_ais_done err; char pid_s[17]; int fd_flag; int lf; err = AIS_DONE_EXIT; lf = open (lockfile, O_WRONLY | O_CREAT, 0640); if (lf == -1) { log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't create lock file.\n"); return (AIS_DONE_AQUIRE_LOCK); } retry_fcntl: lock.l_type = F_WRLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; if (fcntl (lf, F_SETLK, &lock) == -1) { switch (errno) { case EINTR: goto retry_fcntl; break; case EAGAIN: case EACCES: log_printf (LOGSYS_LEVEL_ERROR, "Another Corosync instance is already running.\n"); err = AIS_DONE_ALREADY_RUNNING; goto error_close; break; default: log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't aquire lock. Error was %s\n", strerror(errno)); err = AIS_DONE_AQUIRE_LOCK; goto error_close; break; } } if (ftruncate (lf, 0) == -1) { log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't truncate lock file. Error was %s\n", strerror (errno)); err = AIS_DONE_AQUIRE_LOCK; goto error_close_unlink; } memset (pid_s, 0, sizeof (pid_s)); snprintf (pid_s, sizeof (pid_s) - 1, "%u\n", pid); retry_write: if (write (lf, pid_s, strlen (pid_s)) != strlen (pid_s)) { if (errno == EINTR) { goto retry_write; } else { log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't write pid to lock file. " "Error was %s\n", strerror (errno)); err = AIS_DONE_AQUIRE_LOCK; goto error_close_unlink; } } if ((fd_flag = fcntl (lf, F_GETFD, 0)) == -1) { log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't get close-on-exec flag from lock file. " "Error was %s\n", strerror (errno)); err = AIS_DONE_AQUIRE_LOCK; goto error_close_unlink; } fd_flag |= FD_CLOEXEC; if (fcntl (lf, F_SETFD, fd_flag) == -1) { log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't set close-on-exec flag to lock file. " "Error was %s\n", strerror (errno)); err = AIS_DONE_AQUIRE_LOCK; goto error_close_unlink; } return (err); error_close_unlink: unlink (lockfile); error_close: close (lf); return (err); } int main (int argc, char **argv, char **envp) { const char *error_string; struct totem_config totem_config; hdb_handle_t objdb_handle; hdb_handle_t config_handle; unsigned int config_version = 0; void *objdb_p; struct config_iface_ver0 *config; void *config_p; const char *config_iface_init; char *config_iface; char *iface; char *strtok_save_pt; int res, ch; int background, setprio; struct stat stat_out; char corosync_lib_dir[PATH_MAX]; hdb_handle_t object_runtime_handle; enum e_ais_done flock_err; /* default configuration */ background = 1; setprio = 1; while ((ch = getopt (argc, argv, "fpv")) != EOF) { switch (ch) { case 'f': background = 0; logsys_config_mode_set (NULL, LOGSYS_MODE_OUTPUT_STDERR|LOGSYS_MODE_THREADED|LOGSYS_MODE_FORK); break; case 'p': setprio = 0; break; case 'v': printf ("Corosync Cluster Engine, version '%s'\n", VERSION); printf ("Copyright (c) 2006-2009 Red Hat, Inc.\n"); return EXIT_SUCCESS; break; default: fprintf(stderr, \ "usage:\n"\ " -f : Start application in foreground.\n"\ " -p : Do not set process priority. \n"\ " -v : Display version and SVN revision of Corosync and exit.\n"); return EXIT_FAILURE; } } /* * Set round robin realtime scheduling with priority 99 * Lock all memory to avoid page faults which may interrupt * application healthchecking */ if (setprio) { corosync_setscheduler (); } corosync_mlockall (); log_printf (LOGSYS_LEVEL_NOTICE, "Corosync Cluster Engine ('%s'): started and ready to provide service.\n", VERSION); log_printf (LOGSYS_LEVEL_INFO, "Corosync built-in features:" PACKAGE_FEATURES "\n"); corosync_poll_handle = qb_loop_create (); qb_loop_signal_add(corosync_poll_handle, QB_LOOP_LOW, SIGUSR2, NULL, sig_diag_handler, NULL); qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH, SIGINT, NULL, sig_exit_handler, NULL); qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH, SIGQUIT, NULL, sig_exit_handler, NULL); qb_loop_signal_add(corosync_poll_handle, QB_LOOP_HIGH, SIGTERM, NULL, sig_exit_handler, NULL); (void)signal (SIGSEGV, sigsegv_handler); (void)signal (SIGABRT, sigabrt_handler); #if MSG_NOSIGNAL != 0 (void)signal (SIGPIPE, SIG_IGN); #endif /* * Load the object database interface */ res = lcr_ifact_reference ( &objdb_handle, "objdb", 0, &objdb_p, 0); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't open configuration object database component.\n"); corosync_exit_error (AIS_DONE_OBJDB); } objdb = (struct objdb_iface_ver0 *)objdb_p; objdb->objdb_init (); /* * Initialize the corosync_api_v1 definition */ apidef_init (objdb); api = apidef_get (); num_config_modules = 0; /* * Bootstrap in the default configuration parser or use * the corosync default built in parser if the configuration parser * isn't overridden */ config_iface_init = getenv("COROSYNC_DEFAULT_CONFIG_IFACE"); if (!config_iface_init) { config_iface_init = "corosync_parser"; } /* Make a copy so we can deface it with strtok */ if ((config_iface = strdup(config_iface_init)) == NULL) { log_printf (LOGSYS_LEVEL_ERROR, "exhausted virtual memory"); corosync_exit_error (AIS_DONE_OBJDB); } iface = strtok_r(config_iface, ":", &strtok_save_pt); while (iface) { res = lcr_ifact_reference ( &config_handle, iface, config_version, &config_p, 0); config = (struct config_iface_ver0 *)config_p; if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't open configuration component '%s'\n", iface); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } res = config->config_readconfig(objdb, &error_string); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } log_printf (LOGSYS_LEVEL_NOTICE, "%s", error_string); config_modules[num_config_modules++] = config; iface = strtok_r(NULL, ":", &strtok_save_pt); } free(config_iface); res = corosync_main_config_read (objdb, &error_string); if (res == -1) { /* * if we are here, we _must_ flush the logsys queue * and try to inform that we couldn't read the config. * this is a desperate attempt before certain death * and there is no guarantee that we can print to stderr * nor that logsys is sending the messages where we expect. */ log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string); fprintf(stderr, "%s", error_string); syslog (LOGSYS_LEVEL_ERROR, "%s", error_string); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } /* * Make sure required directory is present */ sprintf (corosync_lib_dir, "%s/lib/corosync", LOCALSTATEDIR); res = stat (corosync_lib_dir, &stat_out); if ((res == -1) || (res == 0 && !S_ISDIR(stat_out.st_mode))) { log_printf (LOGSYS_LEVEL_ERROR, "Required directory not present %s. Please create it.\n", corosync_lib_dir); corosync_exit_error (AIS_DONE_DIR_NOT_PRESENT); } res = totem_config_read (objdb, &totem_config, &error_string); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } res = totem_config_keyread (objdb, &totem_config, &error_string); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } res = totem_config_validate (&totem_config, &error_string); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } totem_config.totem_logging_configuration = totem_logging_configuration; totem_config.totem_logging_configuration.log_subsys_id = _logsys_subsys_create ("TOTEM"); if (totem_config.totem_logging_configuration.log_subsys_id < 0) { log_printf (LOGSYS_LEVEL_ERROR, "Unable to initialize TOTEM logging subsystem\n"); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } totem_config.totem_logging_configuration.log_level_security = LOGSYS_LEVEL_WARNING; totem_config.totem_logging_configuration.log_level_error = LOGSYS_LEVEL_ERROR; totem_config.totem_logging_configuration.log_level_warning = LOGSYS_LEVEL_WARNING; totem_config.totem_logging_configuration.log_level_notice = LOGSYS_LEVEL_NOTICE; totem_config.totem_logging_configuration.log_level_debug = LOGSYS_LEVEL_DEBUG; totem_config.totem_logging_configuration.log_printf = _logsys_log_printf; res = corosync_main_config_compatibility_read (objdb, &minimum_sync_mode, &error_string); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } res = corosync_main_config_compatibility_read (objdb, &minimum_sync_mode, &error_string); if (res == -1) { log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string); corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } /* create the main runtime object */ objdb->object_create (OBJECT_PARENT_HANDLE, &object_runtime_handle, "runtime", strlen ("runtime")); /* * Now we are fully initialized. */ if (background) { corosync_tty_detach (); } logsys_fork_completed(); if ((flock_err = corosync_flock (corosync_lock_file, getpid ())) != AIS_DONE_EXIT) { corosync_exit_error (flock_err); } /* * if totempg_initialize doesn't have root priveleges, it cannot * bind to a specific interface. This only matters if * there is more then one interface in a system, so * in this case, only a warning is printed */ /* * Join multicast group and setup delivery * and configuration change functions */ totempg_initialize ( corosync_poll_handle, &totem_config); totempg_service_ready_register ( main_service_ready); totempg_groups_initialize ( &corosync_group_handle, deliver_fn, confchg_fn); totempg_groups_join ( corosync_group_handle, &corosync_group, 1); /* * Drop root privleges to user 'ais' * TODO: Don't really need full root capabilities; * needed capabilities are: * CAP_NET_RAW (bindtodevice) * CAP_SYS_NICE (setscheduler) * CAP_IPC_LOCK (mlockall) */ priv_drop (); schedwrk_init ( serialize_lock, serialize_unlock); /* * Start main processing loop */ qb_loop_run (corosync_poll_handle); /* * Exit was requested */ totempg_finalize (); /* * Remove pid lock file */ unlink (corosync_lock_file); corosync_exit_error (AIS_DONE_EXIT); return EXIT_SUCCESS; } diff --git a/exec/objdb.c b/exec/objdb.c index 99e20ec7..999db61f 100644 --- a/exec/objdb.c +++ b/exec/objdb.c @@ -1,1841 +1,1847 @@ /* * Copyright (c) 2006 MontaVista Software, Inc. * Copyright (c) 2007-2010 Red Hat, Inc. * * All rights reserved. * * Author: Steven Dake (sdake@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" struct object_key { void *key_name; size_t key_len; void *value; size_t value_len; objdb_value_types_t value_type; struct list_head list; }; struct object_tracker { hdb_handle_t object_handle; void * data_pt; object_track_depth_t depth; object_key_change_notify_fn_t key_change_notify_fn; object_create_notify_fn_t object_create_notify_fn; object_destroy_notify_fn_t object_destroy_notify_fn; object_reload_notify_fn_t object_reload_notify_fn; struct list_head tracker_list; struct list_head object_list; }; struct object_instance { void *object_name; size_t object_name_len; hdb_handle_t object_handle; hdb_handle_t parent_handle; struct list_head key_head; struct list_head child_head; struct list_head child_list; struct list_head *find_child_list; struct list_head *iter_key_list; struct list_head *iter_list; void *priv; struct object_valid *object_valid_list; int object_valid_list_entries; struct object_key_valid *object_key_valid_list; int object_key_valid_list_entries; struct list_head track_head; }; struct object_find_instance { void *object_name; size_t object_len; hdb_handle_t *handles_array; size_t handles_array_size; size_t handles_array_pos; }; struct objdb_iface_ver0 objdb_iface; struct list_head objdb_trackers_head; DECLARE_HDB_DATABASE (object_instance_database,NULL); DECLARE_HDB_DATABASE (object_find_instance_database,NULL); static int objdb_init (void) { hdb_handle_t handle; struct object_instance *instance; - unsigned int res; + int res; res = hdb_handle_create (&object_instance_database, sizeof (struct object_instance), &handle); if (res != 0) { goto error_exit; } res = hdb_handle_get (&object_instance_database, handle, (void *)&instance); if (res != 0) { goto error_destroy; } instance->find_child_list = &instance->child_head; instance->object_name = (char *)"parent"; instance->object_name_len = strlen ("parent"); instance->object_handle = handle; instance->parent_handle = OBJECT_PARENT_HANDLE; instance->priv = NULL; instance->object_valid_list = NULL; instance->object_valid_list_entries = 0; list_init (&instance->key_head); list_init (&instance->child_head); list_init (&instance->child_list); list_init (&instance->track_head); list_init (&objdb_trackers_head); hdb_handle_put (&object_instance_database, handle); return (0); error_destroy: hdb_handle_destroy (&object_instance_database, handle); error_exit: return (-1); } static int _object_notify_deleted_children(struct object_instance *parent_pt) { struct list_head *list; struct list_head *notify_list; int res; struct object_instance *obj_pt = NULL; struct object_tracker * tracker_pt; for (list = parent_pt->child_head.next; list != &parent_pt->child_head; list = list->next) { obj_pt = list_entry(list, struct object_instance, child_list); res = _object_notify_deleted_children(obj_pt); if (res) return res; for (notify_list = obj_pt->track_head.next; notify_list != &obj_pt->track_head; notify_list = notify_list->next) { tracker_pt = list_entry (notify_list, struct object_tracker, object_list); if ((tracker_pt != NULL) && (tracker_pt->object_destroy_notify_fn != NULL)) tracker_pt->object_destroy_notify_fn(parent_pt->object_handle, obj_pt->object_name, obj_pt->object_name_len, tracker_pt->data_pt); } } return 0; } static void object_created_notification( hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len) { struct list_head * list; struct object_instance * obj_pt; struct object_tracker * tracker_pt; hdb_handle_t obj_handle = object_handle; - unsigned int res; do { - res = hdb_handle_get (&object_instance_database, - obj_handle, (void *)&obj_pt); + if (hdb_handle_get (&object_instance_database, + obj_handle, (void *)&obj_pt) != 0) { + return; + } for (list = obj_pt->track_head.next; list != &obj_pt->track_head; list = list->next) { tracker_pt = list_entry (list, struct object_tracker, object_list); if (((obj_handle == parent_object_handle) || (tracker_pt->depth == OBJECT_TRACK_DEPTH_RECURSIVE)) && (tracker_pt->object_create_notify_fn != NULL)) { tracker_pt->object_create_notify_fn(parent_object_handle, object_handle, name_pt, name_len, tracker_pt->data_pt); } } hdb_handle_put (&object_instance_database, obj_handle); obj_handle = obj_pt->parent_handle; } while (obj_handle != OBJECT_PARENT_HANDLE); } static void object_pre_deletion_notification(hdb_handle_t object_handle, hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len) { struct list_head * list; struct object_instance * obj_pt; struct object_tracker * tracker_pt; hdb_handle_t obj_handle = object_handle; - unsigned int res; do { - res = hdb_handle_get (&object_instance_database, - obj_handle, (void *)&obj_pt); + if (hdb_handle_get (&object_instance_database, + obj_handle, (void *)&obj_pt) != 0) { + return; + } for (list = obj_pt->track_head.next; list != &obj_pt->track_head; list = list->next) { tracker_pt = list_entry (list, struct object_tracker, object_list); if (((obj_handle == parent_object_handle) || (tracker_pt->depth == OBJECT_TRACK_DEPTH_RECURSIVE)) && (tracker_pt->object_destroy_notify_fn != NULL)) { tracker_pt->object_destroy_notify_fn( parent_object_handle, name_pt, name_len, tracker_pt->data_pt); } } /* notify child object listeners */ if (obj_handle == object_handle) _object_notify_deleted_children(obj_pt); obj_handle = obj_pt->parent_handle; hdb_handle_put (&object_instance_database, obj_pt->object_handle); } while (obj_handle != OBJECT_PARENT_HANDLE); } static void object_key_changed_notification(hdb_handle_t object_handle, const void *name_pt, size_t name_len, const void *value_pt, size_t value_len, object_change_type_t type) { struct list_head * list; struct object_instance * obj_pt; struct object_instance * owner_pt = NULL; struct object_tracker * tracker_pt; hdb_handle_t obj_handle = object_handle; - unsigned int res; do { - res = hdb_handle_get (&object_instance_database, - obj_handle, (void *)&obj_pt); + if (hdb_handle_get (&object_instance_database, + obj_handle, (void *)&obj_pt) != 0) { + return; + } if (owner_pt == NULL) owner_pt = obj_pt; for (list = obj_pt->track_head.next; list != &obj_pt->track_head; list = list->next) { tracker_pt = list_entry (list, struct object_tracker, object_list); if (((obj_handle == object_handle) || (tracker_pt->depth == OBJECT_TRACK_DEPTH_RECURSIVE)) && (tracker_pt->key_change_notify_fn != NULL)) tracker_pt->key_change_notify_fn(type, obj_pt->parent_handle, object_handle, owner_pt->object_name, owner_pt->object_name_len, name_pt, name_len, value_pt, value_len, tracker_pt->data_pt); } obj_handle = obj_pt->parent_handle; hdb_handle_put (&object_instance_database, obj_pt->object_handle); } while (obj_handle != OBJECT_PARENT_HANDLE); } static void object_reload_notification(int startstop, int flush) { struct list_head * list, *tmp; struct list_head tmplist; struct object_instance * obj_pt; struct object_tracker * tracker_pt; struct object_tracker * tmptracker_pt; - unsigned int res; - res = hdb_handle_get (&object_instance_database, - OBJECT_PARENT_HANDLE, (void *)&obj_pt); + if (hdb_handle_get (&object_instance_database, + OBJECT_PARENT_HANDLE, (void *)&obj_pt) != 0) { + return; + } /* * Make a copy of the list * so that items can be added & removed in the callbacks */ list_init(&tmplist); for (list = obj_pt->track_head.next; list != &obj_pt->track_head; list = list->next) { tracker_pt = list_entry (list, struct object_tracker, object_list); if (tracker_pt->object_reload_notify_fn != NULL) { tmptracker_pt = malloc(sizeof(*tracker_pt)); if (tmptracker_pt) { list_add(&tmptracker_pt->object_list, &tmplist); tmptracker_pt->object_reload_notify_fn = tracker_pt->object_reload_notify_fn; tmptracker_pt->data_pt = tracker_pt->data_pt; } } } for (list = tmplist.next, tmp = list->next; list != &tmplist; list = tmp, tmp = list->next) { tracker_pt = list_entry (list, struct object_tracker, object_list); tracker_pt->object_reload_notify_fn(startstop, flush, tracker_pt->data_pt); free(tracker_pt); } hdb_handle_put (&object_instance_database, OBJECT_PARENT_HANDLE); } /* * object db create/destroy/set */ static int object_create ( hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len) { struct object_instance *object_instance; struct object_instance *parent_instance; - unsigned int res; + int res; int found = 0; int i; res = hdb_handle_get (&object_instance_database, parent_object_handle, (void *)&parent_instance); if (res != 0) { goto error_exit; } /* * Do validation check if validation is configured for the parent object */ if (parent_instance->object_valid_list_entries) { for (i = 0; i < parent_instance->object_valid_list_entries; i++) { if ((object_name_len == parent_instance->object_valid_list[i].object_len) && (memcmp (object_name, parent_instance->object_valid_list[i].object_name, object_name_len) == 0)) { found = 1; break; } } /* * Item not found in validation list */ if (found == 0) { goto error_object_put; } } res = hdb_handle_create (&object_instance_database, sizeof (struct object_instance), object_handle); if (res != 0) { goto error_object_put; } res = hdb_handle_get (&object_instance_database, *object_handle, (void *)&object_instance); if (res != 0) { goto error_destroy; } list_init (&object_instance->key_head); list_init (&object_instance->child_head); list_init (&object_instance->child_list); list_init (&object_instance->track_head); object_instance->object_name = malloc (object_name_len); if (object_instance->object_name == 0) { goto error_put_destroy; } memcpy (object_instance->object_name, object_name, object_name_len); object_instance->object_name_len = object_name_len; list_add_tail (&object_instance->child_list, &parent_instance->child_head); object_instance->object_handle = *object_handle; object_instance->find_child_list = &object_instance->child_head; object_instance->iter_key_list = &object_instance->key_head; object_instance->iter_list = &object_instance->child_head; object_instance->priv = NULL; object_instance->object_valid_list = NULL; object_instance->object_valid_list_entries = 0; object_instance->parent_handle = parent_object_handle; hdb_handle_put (&object_instance_database, *object_handle); hdb_handle_put (&object_instance_database, parent_object_handle); object_created_notification( object_instance->parent_handle, object_instance->object_handle, object_instance->object_name, object_instance->object_name_len); return (0); error_put_destroy: hdb_handle_put (&object_instance_database, *object_handle); error_destroy: hdb_handle_destroy (&object_instance_database, *object_handle); error_object_put: hdb_handle_put (&object_instance_database, parent_object_handle); error_exit: return (-1); } static int object_priv_set ( hdb_handle_t object_handle, void *priv) { int res; struct object_instance *object_instance; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&object_instance); if (res != 0) { goto error_exit; } object_instance->priv = priv; hdb_handle_put (&object_instance_database, object_handle); return (0); error_exit: return (-1); } static int object_key_create_typed( hdb_handle_t object_handle, const char *key_name, const void *value, size_t value_len, objdb_value_types_t value_type) { struct object_instance *instance; struct object_key *object_key; - unsigned int res; + int res; struct list_head *list; int found = 0; int i; size_t key_len = strlen(key_name); size_t expected_size; int test_size_by_type = CS_TRUE; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } switch (value_type) { case OBJDB_VALUETYPE_INT16: expected_size = sizeof (int16_t); break; case OBJDB_VALUETYPE_UINT16: expected_size = sizeof (uint16_t); break; case OBJDB_VALUETYPE_INT32: expected_size = sizeof (int32_t); break; case OBJDB_VALUETYPE_UINT32: expected_size = sizeof (uint32_t); break; case OBJDB_VALUETYPE_INT64: expected_size = sizeof (int64_t); break; case OBJDB_VALUETYPE_UINT64: expected_size = sizeof (uint64_t); break; case OBJDB_VALUETYPE_FLOAT: expected_size = sizeof (float); break; case OBJDB_VALUETYPE_DOUBLE: expected_size = sizeof (double); break; case OBJDB_VALUETYPE_ANY: default: test_size_by_type = CS_FALSE; break; } if (test_size_by_type) { if (expected_size != value_len) { //printf ("%s exp:%d != len:%d\n", key_name, expected_size, value_len); goto error_put; } } /* * Do validation check if validation is configured for the parent object */ if (instance->object_key_valid_list_entries) { for (i = 0; i < instance->object_key_valid_list_entries; i++) { if ((key_len == instance->object_key_valid_list[i].key_len) && (memcmp (key_name, instance->object_key_valid_list[i].key_name, key_len) == 0)) { found = 1; break; } } /* * Item not found in validation list */ if (found == 0) { goto error_put; } else { if (instance->object_key_valid_list[i].validate_callback) { res = instance->object_key_valid_list[i].validate_callback ( key_name, key_len, value, value_len); if (res != 0) { goto error_put; } } } } /* See if it already exists */ found = 0; for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { free(object_key->value); } else { object_key = malloc (sizeof (struct object_key)); if (object_key == 0) { goto error_put; } object_key->key_name = malloc (key_len + 1); if (object_key->key_name == 0) { goto error_put_object; } memcpy (object_key->key_name, key_name, key_len + 1); list_init (&object_key->list); list_add_tail (&object_key->list, &instance->key_head); } object_key->value = malloc (value_len); if (object_key->value == 0) { goto error_put_key; } memcpy (object_key->value, value, value_len); object_key->key_len = key_len; object_key->value_len = value_len; object_key->value_type = value_type; object_key_changed_notification(object_handle, key_name, key_len, value, value_len, OBJECT_KEY_CREATED); hdb_handle_put (&object_instance_database, object_handle); return (0); error_put_key: free (object_key->key_name); error_put_object: free (object_key); error_put: hdb_handle_put (&object_instance_database, object_handle); error_exit: return (-1); } static int object_key_create ( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *value, size_t value_len) { char *key_name_terminated = NULL; char *key_name_str = (char*)key_name; int ret; if (key_name_str[key_len-1] != '\0') { key_name_terminated = malloc (key_len + 1); memcpy (key_name_terminated, key_name, key_len); key_name_terminated[key_len] = '\0'; key_name_str = key_name_terminated; } ret = object_key_create_typed (object_handle, key_name_str, value, value_len, OBJDB_VALUETYPE_ANY); if (key_name_terminated) { free (key_name_terminated); } return ret; } static int _clear_object(struct object_instance *instance) { struct list_head *list; int res; struct object_instance *find_instance = NULL; struct object_key *object_key = NULL; struct object_tracker *tracker_pt = NULL; for (list = instance->key_head.next; list != &instance->key_head; ) { object_key = list_entry (list, struct object_key, list); list = list->next; list_del(&object_key->list); free(object_key->key_name); free(object_key->value); free(object_key); } for (list = instance->track_head.next; list != &instance->track_head;) { tracker_pt = list_entry (list, struct object_tracker, object_list); list = list->next; list_del(&tracker_pt->tracker_list); list_del(&tracker_pt->object_list); free(tracker_pt); } for (list = instance->child_head.next; list != &instance->child_head; ) { find_instance = list_entry (list, struct object_instance, child_list); res = _clear_object(find_instance); if (res) return res; list = list->next; list_del(&find_instance->child_list); free(find_instance->object_name); hdb_handle_destroy (&object_instance_database, find_instance->object_handle); } return 0; } static int object_destroy ( hdb_handle_t object_handle) { struct object_instance *instance; - unsigned int res; + int res; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { return (res); } object_pre_deletion_notification(object_handle, instance->parent_handle, instance->object_name, instance->object_name_len); /* Recursively clear sub-objects & keys */ res = _clear_object(instance); list_del(&instance->child_list); free(instance->object_name); hdb_handle_put (&object_instance_database, object_handle); hdb_handle_destroy (&object_instance_database, object_handle); return (res); } static int object_valid_set ( hdb_handle_t object_handle, struct object_valid *object_valid_list, size_t object_valid_list_entries) { struct object_instance *instance; - unsigned int res; + int res; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } instance->object_valid_list = object_valid_list; instance->object_valid_list_entries = object_valid_list_entries; hdb_handle_put (&object_instance_database, object_handle); return (0); error_exit: return (-1); } static int object_key_valid_set ( hdb_handle_t object_handle, struct object_key_valid *object_key_valid_list, size_t object_key_valid_list_entries) { struct object_instance *instance; - unsigned int res; + int res; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } instance->object_key_valid_list = object_key_valid_list; instance->object_key_valid_list_entries = object_key_valid_list_entries; hdb_handle_put (&object_instance_database, object_handle); return (0); error_exit: return (-1); } /* * object db reading */ static int object_find_create ( hdb_handle_t object_handle, const void *object_name, size_t object_len, hdb_handle_t *object_find_handle) { - unsigned int res; + int res; struct object_instance *iter_obj_inst; struct object_instance *object_instance; struct object_find_instance *object_find_instance; struct list_head *list; hdb_handle_t *handles_array, *handles_array_realloc; size_t ha_len; size_t ha_used; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&object_instance); if (res != 0) { goto error_exit; } res = hdb_handle_create (&object_find_instance_database, sizeof (struct object_find_instance), object_find_handle); if (res != 0) { goto error_put; } res = hdb_handle_get (&object_find_instance_database, *object_find_handle, (void *)&object_find_instance); if (res != 0) { goto error_destroy; } object_find_instance->object_name = (char *)object_name; object_find_instance->object_len = object_len; ha_len = ha_used = 0; handles_array = NULL; for (list = object_instance->child_head.next; list != &object_instance->child_head; list = list->next) { iter_obj_inst = list_entry (list, struct object_instance, child_list); if (object_find_instance->object_len == 0 || ((iter_obj_inst->object_name_len == object_find_instance->object_len) && (memcmp (iter_obj_inst->object_name, object_find_instance->object_name, object_find_instance->object_len) == 0))) { /* * Add handle to list */ if (ha_used + 1 > ha_len) { ha_len = ha_len * 2 + 1; if ((handles_array_realloc = realloc (handles_array, ha_len * sizeof (hdb_handle_t))) == NULL) { goto error_ha_free; } handles_array = handles_array_realloc; } handles_array[ha_used] = iter_obj_inst->object_handle; ha_used++; } } object_find_instance->handles_array_size = ha_used; object_find_instance->handles_array_pos = 0; object_find_instance->handles_array = handles_array; hdb_handle_put (&object_instance_database, object_handle); hdb_handle_put (&object_find_instance_database, *object_find_handle); return (0); error_ha_free: free(handles_array); error_destroy: hdb_handle_destroy (&object_instance_database, *object_find_handle); error_put: hdb_handle_put (&object_instance_database, object_handle); error_exit: return (-1); } static int object_find_next ( hdb_handle_t object_find_handle, hdb_handle_t *object_handle) { - unsigned int res; + int res; struct object_find_instance *object_find_instance; struct object_instance *object_instance = NULL; - unsigned int found = 0; + int found = 0; size_t pos; res = hdb_handle_get (&object_find_instance_database, object_find_handle, (void *)&object_find_instance); if (res != 0) { goto error_exit; } for (pos = object_find_instance->handles_array_pos; !found && pos < object_find_instance->handles_array_size; pos++) { *object_handle = object_find_instance->handles_array[pos]; res = hdb_handle_get (&object_instance_database, *object_handle, (void *)&object_instance); if (res != 0) { continue; } if (object_find_instance->object_len == 0 || ((object_instance->object_name_len == object_find_instance->object_len) && (memcmp (object_instance->object_name, object_find_instance->object_name, object_find_instance->object_len) == 0))) { found = 1; } hdb_handle_put (&object_instance_database, *object_handle); } object_find_instance->handles_array_pos = pos; hdb_handle_put (&object_find_instance_database, object_find_handle); if (found) { *object_handle = object_instance->object_handle; res = 0; + } else { + res = -1; } return (res); error_exit: return (-1); } static int object_find_destroy ( hdb_handle_t object_find_handle) { struct object_find_instance *object_find_instance; - unsigned int res; + int res; res = hdb_handle_get (&object_find_instance_database, object_find_handle, (void *)&object_find_instance); if (res != 0) { goto error_exit; } free(object_find_instance->handles_array); hdb_handle_put(&object_find_instance_database, object_find_handle); hdb_handle_destroy(&object_find_instance_database, object_find_handle); return (0); error_exit: return (-1); } static int object_key_get_typed ( hdb_handle_t object_handle, const char *key_name, void **value, size_t *value_len, objdb_value_types_t * type) { - unsigned int res = 0; + int res = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; size_t key_len = strlen(key_name); res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { *value = object_key->value; if (value_len) { *value_len = object_key->value_len; } *type = object_key->value_type; } else { res = -1; } hdb_handle_put (&object_instance_database, object_handle); return (res); error_exit: return (-1); } static int object_key_get ( hdb_handle_t object_handle, const void *key_name, size_t key_len, void **value, size_t *value_len) { objdb_value_types_t t; int ret; char *key_name_str = (char*)key_name; char *key_name_terminated = NULL; if (key_name_str[key_len-1] != '\0') { key_name_terminated = malloc (key_len + 1); memcpy (key_name_terminated, key_name, key_len); key_name_terminated[key_len] = '\0'; key_name_str = key_name_terminated; } ret = object_key_get_typed(object_handle, key_name_str, value, value_len, &t); if (key_name_terminated) { free (key_name_terminated); } return ret; } static int object_key_increment ( hdb_handle_t object_handle, const void *key_name, size_t key_len, unsigned int *value) { - unsigned int res = 0; + int res = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { switch (object_key->value_type) { case OBJDB_VALUETYPE_INT16: (*(int16_t *)object_key->value)++; break; case OBJDB_VALUETYPE_UINT16: (*(uint16_t *)object_key->value)++; break; case OBJDB_VALUETYPE_INT32: (*(int32_t *)object_key->value)++; break; case OBJDB_VALUETYPE_UINT32: (*(uint32_t *)object_key->value)++; break; case OBJDB_VALUETYPE_INT64: (*(int64_t *)object_key->value)++; break; case OBJDB_VALUETYPE_UINT64: (*(uint64_t *)object_key->value)++; break; case OBJDB_VALUETYPE_ANY: /* for backwards compatibilty */ if (object_key->value_len == sizeof(int)) { (*(int *)object_key->value)++; } else { res = -1; } break; default: res = -1; break; } if (res == 0) { /* nasty, not sure why we need to return this typed * instead of void* */ *value = *(int *)object_key->value; } } else { res = -1; } hdb_handle_put (&object_instance_database, object_handle); if (res == 0) { object_key_changed_notification (object_handle, key_name, key_len, object_key->value, object_key->value_len, OBJECT_KEY_REPLACED); } return (res); error_exit: return (-1); } static int object_key_decrement ( hdb_handle_t object_handle, const void *key_name, size_t key_len, unsigned int *value) { - unsigned int res = 0; + int res = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { switch (object_key->value_type) { case OBJDB_VALUETYPE_INT16: (*(int16_t *)object_key->value)--; break; case OBJDB_VALUETYPE_UINT16: (*(uint16_t *)object_key->value)--; break; case OBJDB_VALUETYPE_INT32: (*(int32_t *)object_key->value)--; break; case OBJDB_VALUETYPE_UINT32: (*(uint32_t *)object_key->value)--; break; case OBJDB_VALUETYPE_INT64: (*(int64_t *)object_key->value)--; break; case OBJDB_VALUETYPE_UINT64: (*(uint64_t *)object_key->value)--; break; case OBJDB_VALUETYPE_ANY: /* for backwards compatibilty */ if (object_key->value_len == sizeof(int)) { (*(int *)object_key->value)--; } else { res = -1; } break; default: res = -1; break; } if (res == 0) { /* nasty, not sure why we need to return this typed * instead of void* */ *value = *(int *)object_key->value; } } else { res = -1; } hdb_handle_put (&object_instance_database, object_handle); if (res == 0) { object_key_changed_notification (object_handle, key_name, key_len, object_key->value, object_key->value_len, OBJECT_KEY_REPLACED); } return (res); error_exit: return (-1); } static int object_key_delete ( hdb_handle_t object_handle, const void *key_name, size_t key_len) { - unsigned int res; + int res; int ret = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { list_del(&object_key->list); free(object_key->key_name); free(object_key->value); free(object_key); } else { ret = -1; errno = ENOENT; } hdb_handle_put (&object_instance_database, object_handle); if (ret == 0) { object_key_changed_notification(object_handle, key_name, key_len, NULL, 0, OBJECT_KEY_DELETED); } return (ret); error_exit: return (-1); } static int object_key_replace ( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *new_value, size_t new_value_len) { - unsigned int res; + int res; int ret = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; int value_changed = 0; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { int i; int found_validator = 0; /* * Do validation check if validation is configured for the parent object */ if (instance->object_key_valid_list_entries) { for (i = 0; i < instance->object_key_valid_list_entries; i++) { if ((key_len == instance->object_key_valid_list[i].key_len) && (memcmp (key_name, instance->object_key_valid_list[i].key_name, key_len) == 0)) { found_validator = 1; break; } } /* * Item not found in validation list */ if (found_validator == 0) { goto error_put; } else { if (instance->object_key_valid_list[i].validate_callback) { res = instance->object_key_valid_list[i].validate_callback ( key_name, key_len, new_value, new_value_len); if (res != 0) { goto error_put; } } } } if (new_value_len != object_key->value_len) { void *replacement_value; replacement_value = malloc(new_value_len); if (!replacement_value) goto error_exit; free(object_key->value); object_key->value = replacement_value; memset (object_key->value, 0, new_value_len); object_key->value_len = new_value_len; } if (memcmp (object_key->value, new_value, new_value_len) == 0) { value_changed = 0; } else { memcpy(object_key->value, new_value, new_value_len); object_key->value_len = new_value_len; value_changed = 1; } } else { ret = -1; errno = ENOENT; } hdb_handle_put (&object_instance_database, object_handle); if (ret == 0 && value_changed) { object_key_changed_notification (object_handle, key_name, key_len, new_value, new_value_len, OBJECT_KEY_REPLACED); } return (ret); error_put: hdb_handle_put (&object_instance_database, object_handle); error_exit: return (-1); } static int object_priv_get ( hdb_handle_t object_handle, void **priv) { int res; struct object_instance *object_instance; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&object_instance); if (res != 0) { goto error_exit; } *priv = object_instance->priv; hdb_handle_put (&object_instance_database, object_handle); return (0); error_exit: return (-1); } static int _dump_object(struct object_instance *instance, FILE *file, int depth) { struct list_head *list; int res; int i; struct object_instance *find_instance = NULL; struct object_key *object_key = NULL; char stringbuf1[1024]; char stringbuf2[1024]; memcpy(stringbuf1, instance->object_name, instance->object_name_len); stringbuf1[instance->object_name_len] = '\0'; for (i=0; iobject_handle != OBJECT_PARENT_HANDLE) fprintf(file, "%s {\n", stringbuf1); for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); memcpy(stringbuf1, object_key->key_name, object_key->key_len); stringbuf1[object_key->key_len] = '\0'; switch (object_key->value_type) { case OBJDB_VALUETYPE_INT16: snprintf (stringbuf2, sizeof(int), "%hd", *(unsigned int*)object_key->value); break; case OBJDB_VALUETYPE_UINT16: snprintf (stringbuf2, sizeof(int), "%hu", *(unsigned int*)object_key->value); break; case OBJDB_VALUETYPE_INT32: snprintf (stringbuf2, sizeof(int), "%d", *(int*)object_key->value); break; case OBJDB_VALUETYPE_UINT32: snprintf (stringbuf2, sizeof(int), "%u", *(unsigned int*)object_key->value); break; case OBJDB_VALUETYPE_INT64: snprintf (stringbuf2, sizeof(int), "%ld", *(long int*)object_key->value); break; case OBJDB_VALUETYPE_UINT64: snprintf (stringbuf2, sizeof(int), "%lu", *(unsigned long int*)object_key->value); break; default: case OBJDB_VALUETYPE_STRING: case OBJDB_VALUETYPE_ANY: memcpy(stringbuf2, object_key->value, object_key->value_len); stringbuf2[object_key->value_len] = '\0'; break; } for (i=0; ichild_head.next; list != &instance->child_head; list = list->next) { find_instance = list_entry (list, struct object_instance, child_list); res = _dump_object(find_instance, file, depth+1); if (res) return res; } for (i=0; iobject_handle != OBJECT_PARENT_HANDLE) fprintf(file, "}\n"); return 0; } static int object_key_iter_reset(hdb_handle_t object_handle) { - unsigned int res; + int res; struct object_instance *instance; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } instance->iter_key_list = &instance->key_head; hdb_handle_put (&object_instance_database, object_handle); return (0); error_exit: return (-1); } static int object_key_iter_typed (hdb_handle_t parent_object_handle, char **key_name, void **value, size_t *value_len, objdb_value_types_t *type) { - unsigned int res; + int res; struct object_instance *instance; struct object_key *find_key = NULL; struct list_head *list; unsigned int found = 0; res = hdb_handle_get (&object_instance_database, parent_object_handle, (void *)&instance); if (res != 0) { goto error_exit; } res = -ENOENT; list = instance->iter_key_list->next; if (list != &instance->key_head) { find_key = list_entry (list, struct object_key, list); found = 1; } instance->iter_key_list = list; if (found) { *key_name = find_key->key_name; *value = find_key->value; *type = find_key->value_type; if (value_len) *value_len = find_key->value_len; res = 0; } else { res = -1; } hdb_handle_put (&object_instance_database, parent_object_handle); return (res); error_exit: return (-1); } static int object_key_iter(hdb_handle_t parent_object_handle, void **key_name, size_t *key_len, void **value, size_t *value_len) { objdb_value_types_t t; int ret; char *str; ret = object_key_iter_typed (parent_object_handle, (char**)key_name, value, value_len, &t); if (!ret) { str = *key_name; *key_len = strlen(str); } return ret; } static int object_key_iter_from(hdb_handle_t parent_object_handle, hdb_handle_t start_pos, void **key_name, size_t *key_len, void **value, size_t *value_len) { unsigned int pos = 0; - unsigned int res; + int res; struct object_instance *instance; struct object_key *find_key = NULL; struct list_head *list; unsigned int found = 0; res = hdb_handle_get (&object_instance_database, parent_object_handle, (void *)&instance); if (res != 0) { goto error_exit; } res = -ENOENT; for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { find_key = list_entry (list, struct object_key, list); if (pos++ == start_pos) { found = 1; break; } } if (found) { *key_name = find_key->key_name; if (key_len) *key_len = find_key->key_len; *value = find_key->value; if (value_len) *value_len = find_key->value_len; res = 0; } else { res = -1; } hdb_handle_put (&object_instance_database, parent_object_handle); return (res); error_exit: return (-1); } static int object_parent_get(hdb_handle_t object_handle, hdb_handle_t *parent_handle) { struct object_instance *instance; - unsigned int res; + int res; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { return (res); } if (object_handle == OBJECT_PARENT_HANDLE) *parent_handle = 0; else *parent_handle = instance->parent_handle; hdb_handle_put (&object_instance_database, object_handle); return (0); } static int object_name_get(hdb_handle_t object_handle, char *object_name, size_t *object_name_len) { struct object_instance *instance; - unsigned int res; + int res; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { return (res); } memcpy(object_name, instance->object_name, instance->object_name_len); *object_name_len = instance->object_name_len; hdb_handle_put (&object_instance_database, object_handle); return (0); } static int object_track_start(hdb_handle_t object_handle, object_track_depth_t depth, object_key_change_notify_fn_t key_change_notify_fn, object_create_notify_fn_t object_create_notify_fn, object_destroy_notify_fn_t object_destroy_notify_fn, object_reload_notify_fn_t object_reload_notify_fn, void * priv_data_pt) { struct object_instance *instance; - unsigned int res; + int res; struct object_tracker * tracker_pt; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { return (res); } tracker_pt = malloc(sizeof(struct object_tracker)); tracker_pt->depth = depth; tracker_pt->object_handle = object_handle; tracker_pt->key_change_notify_fn = key_change_notify_fn; tracker_pt->object_create_notify_fn = object_create_notify_fn; tracker_pt->object_destroy_notify_fn = object_destroy_notify_fn; tracker_pt->object_reload_notify_fn = object_reload_notify_fn; tracker_pt->data_pt = priv_data_pt; list_init(&tracker_pt->object_list); list_init(&tracker_pt->tracker_list); list_add(&tracker_pt->object_list, &instance->track_head); list_add(&tracker_pt->tracker_list, &objdb_trackers_head); hdb_handle_put (&object_instance_database, object_handle); return (res); } static void object_track_stop(object_key_change_notify_fn_t key_change_notify_fn, object_create_notify_fn_t object_create_notify_fn, object_destroy_notify_fn_t object_destroy_notify_fn, object_reload_notify_fn_t object_reload_notify_fn, void * priv_data_pt) { struct object_instance *instance; struct object_tracker * tracker_pt = NULL; struct object_tracker * obj_tracker_pt = NULL; struct list_head *list, *tmp_list; struct list_head *obj_list, *tmp_obj_list; - unsigned int res; + int res; /* go through the global list and find all the trackers to stop */ for (list = objdb_trackers_head.next, tmp_list = list->next; list != &objdb_trackers_head; list = tmp_list, tmp_list = tmp_list->next) { tracker_pt = list_entry (list, struct object_tracker, tracker_list); if (tracker_pt && (tracker_pt->data_pt == priv_data_pt) && (tracker_pt->object_create_notify_fn == object_create_notify_fn) && (tracker_pt->object_destroy_notify_fn == object_destroy_notify_fn) && (tracker_pt->object_reload_notify_fn == object_reload_notify_fn) && (tracker_pt->key_change_notify_fn == key_change_notify_fn)) { /* get the object & take this tracker off of it's list. */ res = hdb_handle_get (&object_instance_database, tracker_pt->object_handle, (void *)&instance); if (res != 0) continue; for (obj_list = instance->track_head.next, tmp_obj_list = obj_list->next; obj_list != &instance->track_head; obj_list = tmp_obj_list, tmp_obj_list = tmp_obj_list->next) { obj_tracker_pt = list_entry (obj_list, struct object_tracker, object_list); if (obj_tracker_pt == tracker_pt) { /* this is the tracker we are after. */ list_del(obj_list); } } hdb_handle_put (&object_instance_database, tracker_pt->object_handle); /* remove the tracker off of the global list */ list_del(list); free(tracker_pt); } } } static int object_dump(hdb_handle_t object_handle, FILE *file) { struct object_instance *instance; - unsigned int res; + int res; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { return (res); } res = _dump_object(instance, file, -1); hdb_handle_put (&object_instance_database, object_handle); return (res); } static int object_write_config(const char **error_string) { struct config_iface_ver0 **modules; int num_modules; int i; int res; main_get_config_modules(&modules, &num_modules); for (i=0; iconfig_writeconfig) { res = modules[i]->config_writeconfig(&objdb_iface, error_string); if (res) { return res; } } } return 0; } static int object_reload_config(int flush, const char **error_string) { struct config_iface_ver0 **modules; int num_modules; int i; int res; main_get_config_modules(&modules, &num_modules); object_reload_notification(OBJDB_RELOAD_NOTIFY_START, flush); for (i=0; iconfig_reloadconfig) { res = modules[i]->config_reloadconfig(&objdb_iface, flush, error_string); if (res) { object_reload_notification(OBJDB_RELOAD_NOTIFY_FAILED, flush); return res; } } } object_reload_notification(OBJDB_RELOAD_NOTIFY_END, flush); return 0; } struct objdb_iface_ver0 objdb_iface = { .objdb_init = objdb_init, .object_create = object_create, .object_priv_set = object_priv_set, .object_key_create = object_key_create, .object_key_delete = object_key_delete, .object_key_replace = object_key_replace, .object_destroy = object_destroy, .object_valid_set = object_valid_set, .object_key_valid_set = object_key_valid_set, .object_find_create = object_find_create, .object_find_next = object_find_next, .object_find_destroy = object_find_destroy, .object_key_get = object_key_get, .object_key_iter_reset = object_key_iter_reset, .object_key_iter = object_key_iter, .object_key_iter_from = object_key_iter_from, .object_priv_get = object_priv_get, .object_parent_get = object_parent_get, .object_name_get = object_name_get, .object_track_start = object_track_start, .object_track_stop = object_track_stop, .object_dump = object_dump, .object_write_config = object_write_config, .object_reload_config = object_reload_config, .object_key_increment = object_key_increment, .object_key_decrement = object_key_decrement, .object_key_create_typed = object_key_create_typed, .object_key_get_typed = object_key_get_typed, .object_key_iter_typed = object_key_iter_typed, }; struct lcr_iface objdb_iface_ver0[1] = { { .name = "objdb", .version = 0, .versions_replace = 0, .versions_replace_count = 0, .dependencies = 0, .dependency_count = 0, .constructor = NULL, .destructor = NULL, .interfaces = NULL, } }; struct lcr_comp objdb_comp_ver0 = { .iface_count = 1, .ifaces = objdb_iface_ver0 }; #ifdef COROSYNC_SOLARIS void corosync_lcr_component_register (void); void corosync_lcr_component_register (void) { #else __attribute__ ((constructor)) static void corosync_lcr_component_register (void) { #endif lcr_interfaces_set (&objdb_iface_ver0[0], &objdb_iface); lcr_component_register (&objdb_comp_ver0); } diff --git a/lib/cfg.c b/lib/cfg.c index 3a662d45..5cd35c3f 100644 --- a/lib/cfg.c +++ b/lib/cfg.c @@ -1,788 +1,787 @@ /* * Copyright (c) 2002-2005 MontaVista Software, Inc. * Copyright (c) 2006-2009 Red Hat, Inc. * * All rights reserved. * * Author: Steven Dake (sdake@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" /* * Data structure for instance data */ struct cfg_inst { qb_ipcc_connection_t *c; corosync_cfg_callbacks_t callbacks; cs_name_t comp_name; int comp_registered; int finalize; }; /* * All instances in one database */ DECLARE_HDB_DATABASE (cfg_hdb,NULL); /* * Implementation */ cs_error_t corosync_cfg_initialize ( corosync_cfg_handle_t *cfg_handle, const corosync_cfg_callbacks_t *cfg_callbacks) { struct cfg_inst *cfg_inst; cs_error_t error = CS_OK; error = hdb_error_to_cs (hdb_handle_create (&cfg_hdb, sizeof (struct cfg_inst), cfg_handle)); if (error != CS_OK) { goto error_no_destroy; } error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, *cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { goto error_destroy; } cfg_inst->c = qb_ipcc_connect ("cfg", IPC_REQUEST_SIZE); if (cfg_inst->c == NULL) { error = qb_to_cs_error(-errno); goto error_put_destroy; } if (error != CS_OK) { goto error_put_destroy; } if (cfg_callbacks) { memcpy (&cfg_inst->callbacks, cfg_callbacks, sizeof (corosync_cfg_callbacks_t)); } (void)hdb_handle_put (&cfg_hdb, *cfg_handle); return (CS_OK); error_put_destroy: (void)hdb_handle_put (&cfg_hdb, *cfg_handle); error_destroy: (void)hdb_handle_destroy (&cfg_hdb, *cfg_handle); error_no_destroy: return (error); } cs_error_t corosync_cfg_fd_get ( corosync_cfg_handle_t cfg_handle, int32_t *selection_fd) { struct cfg_inst *cfg_inst; cs_error_t error; error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } error = qb_to_cs_error (qb_ipcc_fd_get (cfg_inst->c, selection_fd)); (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error); } cs_error_t corosync_cfg_dispatch ( corosync_cfg_handle_t cfg_handle, cs_dispatch_flags_t dispatch_flags) { int timeout = -1; cs_error_t error; int cont = 1; /* always continue do loop except when set to 0 */ struct cfg_inst *cfg_inst; struct res_lib_cfg_testshutdown *res_lib_cfg_testshutdown; corosync_cfg_callbacks_t callbacks; struct qb_ipc_response_header *dispatch_data; char dispatch_buf[IPC_DISPATCH_SIZE]; error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } /* * Timeout instantly for CS_DISPATCH_ALL */ if (dispatch_flags == CS_DISPATCH_ALL) { timeout = 0; } dispatch_data = (struct qb_ipc_response_header *)dispatch_buf; do { error = qb_to_cs_error (qb_ipcc_event_recv ( cfg_inst->c, dispatch_buf, IPC_DISPATCH_SIZE, timeout)); if (error == CS_ERR_BAD_HANDLE) { error = CS_OK; goto error_put; } if (error == CS_ERR_TRY_AGAIN) { error = CS_OK; if (dispatch_flags == CPG_DISPATCH_ALL) { break; /* exit do while cont is 1 loop */ } else { continue; /* next poll */ } } if (error != CS_OK) { goto error_put; } /* * Make copy of callbacks, message data, unlock instance, and call callback * A risk of this dispatch method is that the callback routines may * operate at the same time that cfgFinalize has been called in another thread. */ memcpy (&callbacks, &cfg_inst->callbacks, sizeof (corosync_cfg_callbacks_t)); /* * Dispatch incoming response */ switch (dispatch_data->id) { case MESSAGE_RES_CFG_TESTSHUTDOWN: if (callbacks.corosync_cfg_shutdown_callback == NULL) { break; } res_lib_cfg_testshutdown = (struct res_lib_cfg_testshutdown *)dispatch_data; callbacks.corosync_cfg_shutdown_callback(cfg_handle, res_lib_cfg_testshutdown->flags); break; default: error = CS_ERR_LIBRARY; goto error_nounlock; break; } /* * Determine if more messages should be processed */ if (dispatch_flags == CS_DISPATCH_ONE) { cont = 0; } } while (cont); error_put: (void)hdb_handle_put (&cfg_hdb, cfg_handle); error_nounlock: return (error); } cs_error_t corosync_cfg_finalize ( corosync_cfg_handle_t cfg_handle) { struct cfg_inst *cfg_inst; cs_error_t error; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } /* * Another thread has already started finalizing */ if (cfg_inst->finalize) { (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (CS_ERR_BAD_HANDLE); } cfg_inst->finalize = 1; qb_ipcc_disconnect (cfg_inst->c); (void)hdb_handle_destroy (&cfg_hdb, cfg_handle); (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error); } cs_error_t corosync_cfg_ring_status_get ( corosync_cfg_handle_t cfg_handle, char ***interface_names, char ***status, unsigned int *interface_count) { struct cfg_inst *cfg_inst; struct req_lib_cfg_ringstatusget req_lib_cfg_ringstatusget; struct res_lib_cfg_ringstatusget res_lib_cfg_ringstatusget; unsigned int i, j; cs_error_t error; struct iovec iov; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_ringstatusget.header.size = sizeof (struct req_lib_cfg_ringstatusget); req_lib_cfg_ringstatusget.header.id = MESSAGE_REQ_CFG_RINGSTATUSGET; iov.iov_base = (void *)&req_lib_cfg_ringstatusget, iov.iov_len = sizeof (struct req_lib_cfg_ringstatusget), error = qb_to_cs_error (qb_ipcc_sendv_recv(cfg_inst->c, &iov, 1, &res_lib_cfg_ringstatusget, sizeof (struct res_lib_cfg_ringstatusget), -1)); *interface_count = res_lib_cfg_ringstatusget.interface_count; *interface_names = malloc (sizeof (char *) * *interface_count); if (*interface_names == NULL) { return (CS_ERR_NO_MEMORY); } memset (*interface_names, 0, sizeof (char *) * *interface_count); *status = malloc (sizeof (char *) * *interface_count); if (*status == NULL) { error = CS_ERR_NO_MEMORY; goto error_free_interface_names_array; } memset (*status, 0, sizeof (char *) * *interface_count); for (i = 0; i < res_lib_cfg_ringstatusget.interface_count; i++) { (*(interface_names))[i] = strdup (res_lib_cfg_ringstatusget.interface_name[i]); if ((*(interface_names))[i] == NULL) { error = CS_ERR_NO_MEMORY; goto error_free_interface_names; } } for (i = 0; i < res_lib_cfg_ringstatusget.interface_count; i++) { (*(status))[i] = strdup (res_lib_cfg_ringstatusget.interface_status[i]); if ((*(status))[i] == NULL) { error = CS_ERR_NO_MEMORY; goto error_free_status; } } goto no_error; error_free_status: for (j = 0; j < i; j++) { free ((*(status))[j]); } i = *interface_count; error_free_interface_names: for (j = 0; j < i; j++) { free ((*(interface_names))[j]); } free (*status); error_free_interface_names_array: free (*interface_names); no_error: (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error); } cs_error_t corosync_cfg_ring_reenable ( corosync_cfg_handle_t cfg_handle) { struct cfg_inst *cfg_inst; struct req_lib_cfg_ringreenable req_lib_cfg_ringreenable; struct res_lib_cfg_ringreenable res_lib_cfg_ringreenable; cs_error_t error; struct iovec iov; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_ringreenable.header.size = sizeof (struct req_lib_cfg_ringreenable); req_lib_cfg_ringreenable.header.id = MESSAGE_REQ_CFG_RINGREENABLE; iov.iov_base = (void *)&req_lib_cfg_ringreenable, iov.iov_len = sizeof (struct req_lib_cfg_ringreenable); error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_ringreenable, sizeof (struct res_lib_cfg_ringreenable), -1)); (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error); } cs_error_t corosync_cfg_service_load ( corosync_cfg_handle_t cfg_handle, const char *service_name, unsigned int service_ver) { struct cfg_inst *cfg_inst; struct req_lib_cfg_serviceload req_lib_cfg_serviceload; struct res_lib_cfg_serviceload res_lib_cfg_serviceload; cs_error_t error; struct iovec iov; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_serviceload.header.size = sizeof (struct req_lib_cfg_serviceload); req_lib_cfg_serviceload.header.id = MESSAGE_REQ_CFG_SERVICELOAD; memset (&req_lib_cfg_serviceload.service_name, 0, sizeof (req_lib_cfg_serviceload.service_name)); strncpy (req_lib_cfg_serviceload.service_name, service_name, sizeof (req_lib_cfg_serviceload.service_name) - 1); req_lib_cfg_serviceload.service_ver = service_ver; iov.iov_base = (void *)&req_lib_cfg_serviceload; iov.iov_len = sizeof (req_lib_cfg_serviceload); error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_serviceload, sizeof (struct res_lib_cfg_serviceload), -1)); (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error); } cs_error_t corosync_cfg_service_unload ( corosync_cfg_handle_t cfg_handle, const char *service_name, unsigned int service_ver) { struct cfg_inst *cfg_inst; struct req_lib_cfg_serviceunload req_lib_cfg_serviceunload; struct res_lib_cfg_serviceunload res_lib_cfg_serviceunload; cs_error_t error; struct iovec iov; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_serviceunload.header.size = sizeof (struct req_lib_cfg_serviceunload); req_lib_cfg_serviceunload.header.id = MESSAGE_REQ_CFG_SERVICEUNLOAD; memset (&req_lib_cfg_serviceunload.service_name, 0, sizeof (req_lib_cfg_serviceunload.service_name)); strncpy (req_lib_cfg_serviceunload.service_name, service_name, sizeof (req_lib_cfg_serviceunload.service_name) - 1); req_lib_cfg_serviceunload.service_ver = service_ver; iov.iov_base = (void *)&req_lib_cfg_serviceunload; iov.iov_len = sizeof (req_lib_cfg_serviceunload); error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_serviceunload, sizeof (struct res_lib_cfg_serviceunload), -1)); (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error); } cs_error_t corosync_cfg_state_track ( corosync_cfg_handle_t cfg_handle, uint8_t track_flags, const corosync_cfg_state_notification_t *notification_buffer) { struct cfg_inst *cfg_inst; struct req_lib_cfg_statetrack req_lib_cfg_statetrack; struct res_lib_cfg_statetrack res_lib_cfg_statetrack; cs_error_t error; struct iovec iov; req_lib_cfg_statetrack.header.size = sizeof (struct req_lib_cfg_statetrack); req_lib_cfg_statetrack.header.id = MESSAGE_REQ_CFG_STATETRACKSTART; req_lib_cfg_statetrack.track_flags = track_flags; req_lib_cfg_statetrack.notification_buffer_address = (corosync_cfg_state_notification_t *)notification_buffer; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } iov.iov_base = (void *)&req_lib_cfg_statetrack, iov.iov_len = sizeof (struct req_lib_cfg_statetrack), error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_statetrack, sizeof (struct res_lib_cfg_statetrack), -1)); (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error == CS_OK ? res_lib_cfg_statetrack.header.error : error); } cs_error_t corosync_cfg_state_track_stop ( corosync_cfg_handle_t cfg_handle) { struct cfg_inst *cfg_inst; struct req_lib_cfg_statetrackstop req_lib_cfg_statetrackstop; struct res_lib_cfg_statetrackstop res_lib_cfg_statetrackstop; cs_error_t error; struct iovec iov; error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_statetrackstop.header.size = sizeof (struct req_lib_cfg_statetrackstop); req_lib_cfg_statetrackstop.header.id = MESSAGE_REQ_CFG_STATETRACKSTOP; iov.iov_base = (void *)&req_lib_cfg_statetrackstop, iov.iov_len = sizeof (struct req_lib_cfg_statetrackstop), error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_statetrackstop, sizeof (struct res_lib_cfg_statetrackstop), -1)); (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error == CS_OK ? res_lib_cfg_statetrackstop.header.error : error); } cs_error_t corosync_cfg_kill_node ( corosync_cfg_handle_t cfg_handle, unsigned int nodeid, const char *reason) { struct cfg_inst *cfg_inst; struct req_lib_cfg_killnode req_lib_cfg_killnode; struct res_lib_cfg_killnode res_lib_cfg_killnode; cs_error_t error; struct iovec iov; if (strlen(reason) >= CS_MAX_NAME_LENGTH) return CS_ERR_NAME_TOO_LONG; error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_killnode.header.id = MESSAGE_REQ_CFG_KILLNODE; req_lib_cfg_killnode.header.size = sizeof (struct req_lib_cfg_killnode); req_lib_cfg_killnode.nodeid = nodeid; strcpy((char *)req_lib_cfg_killnode.reason.value, reason); req_lib_cfg_killnode.reason.length = strlen(reason)+1; iov.iov_base = (void *)&req_lib_cfg_killnode; iov.iov_len = sizeof (struct req_lib_cfg_killnode); error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_killnode, sizeof (struct res_lib_cfg_killnode), -1)); error = res_lib_cfg_killnode.header.error; (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error == CS_OK ? res_lib_cfg_killnode.header.error : error); } cs_error_t corosync_cfg_try_shutdown ( corosync_cfg_handle_t cfg_handle, corosync_cfg_shutdown_flags_t flags) { struct cfg_inst *cfg_inst; struct req_lib_cfg_tryshutdown req_lib_cfg_tryshutdown; struct res_lib_cfg_tryshutdown res_lib_cfg_tryshutdown; cs_error_t error; struct iovec iov; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_tryshutdown.header.id = MESSAGE_REQ_CFG_TRYSHUTDOWN; req_lib_cfg_tryshutdown.header.size = sizeof (struct req_lib_cfg_tryshutdown); req_lib_cfg_tryshutdown.flags = flags; iov.iov_base = (void *)&req_lib_cfg_tryshutdown; iov.iov_len = sizeof (req_lib_cfg_tryshutdown); error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_tryshutdown, sizeof (struct res_lib_cfg_tryshutdown), -1)); (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error == CS_OK ? res_lib_cfg_tryshutdown.header.error : error); } cs_error_t corosync_cfg_replyto_shutdown ( corosync_cfg_handle_t cfg_handle, corosync_cfg_shutdown_reply_flags_t response) { struct cfg_inst *cfg_inst; struct req_lib_cfg_replytoshutdown req_lib_cfg_replytoshutdown; struct res_lib_cfg_replytoshutdown res_lib_cfg_replytoshutdown; struct iovec iov; cs_error_t error; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_replytoshutdown.header.id = MESSAGE_REQ_CFG_REPLYTOSHUTDOWN; req_lib_cfg_replytoshutdown.header.size = sizeof (struct req_lib_cfg_replytoshutdown); req_lib_cfg_replytoshutdown.response = response; iov.iov_base = (void *)&req_lib_cfg_replytoshutdown; iov.iov_len = sizeof (struct req_lib_cfg_replytoshutdown); error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_replytoshutdown, sizeof (struct res_lib_cfg_replytoshutdown), -1)); return (error); } cs_error_t corosync_cfg_get_node_addrs ( corosync_cfg_handle_t cfg_handle, int nodeid, size_t max_addrs, int *num_addrs, corosync_cfg_node_address_t *addrs) { cs_error_t error; struct req_lib_cfg_get_node_addrs req_lib_cfg_get_node_addrs; struct res_lib_cfg_get_node_addrs *res_lib_cfg_get_node_addrs; struct cfg_inst *cfg_inst; int addrlen = 0; int i; struct iovec iov; - void *return_address; const char *addr_buf; char response_buf[IPC_RESPONSE_SIZE]; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_get_node_addrs.header.size = sizeof (req_lib_cfg_get_node_addrs); req_lib_cfg_get_node_addrs.header.id = MESSAGE_REQ_CFG_GET_NODE_ADDRS; req_lib_cfg_get_node_addrs.nodeid = nodeid; iov.iov_base = (char *)&req_lib_cfg_get_node_addrs; iov.iov_len = sizeof (req_lib_cfg_get_node_addrs); error = qb_to_cs_error (qb_ipcc_sendv_recv ( cfg_inst->c, &iov, 1, response_buf, IPC_RESPONSE_SIZE, -1)); res_lib_cfg_get_node_addrs = (struct res_lib_cfg_get_node_addrs *)response_buf; if (error != CS_OK) { goto error_put; } if (res_lib_cfg_get_node_addrs->family == AF_INET) addrlen = sizeof(struct sockaddr_in); if (res_lib_cfg_get_node_addrs->family == AF_INET6) addrlen = sizeof(struct sockaddr_in6); for (i = 0, addr_buf = (char *)res_lib_cfg_get_node_addrs->addrs; i < max_addrs && inum_addrs; i++, addr_buf += TOTEMIP_ADDRLEN) { struct sockaddr_in *in; struct sockaddr_in6 *in6; addrs[i].address_length = addrlen; if (res_lib_cfg_get_node_addrs->family == AF_INET) { in = (struct sockaddr_in *)addrs[i].address; in->sin_family = AF_INET; memcpy(&in->sin_addr, addr_buf, sizeof(struct in_addr)); } if (res_lib_cfg_get_node_addrs->family == AF_INET6) { in6 = (struct sockaddr_in6 *)addrs[i].address; in6->sin6_family = AF_INET6; memcpy(&in6->sin6_addr, addr_buf, sizeof(struct in6_addr)); } } *num_addrs = res_lib_cfg_get_node_addrs->num_addrs; errno = error = res_lib_cfg_get_node_addrs->header.error; error_put: hdb_handle_put (&cfg_hdb, cfg_handle); return (error); } cs_error_t corosync_cfg_local_get ( corosync_cfg_handle_t handle, unsigned int *local_nodeid) { cs_error_t error; struct cfg_inst *cfg_inst; struct iovec iov; struct req_lib_cfg_local_get req_lib_cfg_local_get; struct res_lib_cfg_local_get res_lib_cfg_local_get; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_local_get.header.size = sizeof (struct qb_ipc_request_header); req_lib_cfg_local_get.header.id = MESSAGE_REQ_CFG_LOCAL_GET; iov.iov_base = (void *)&req_lib_cfg_local_get; iov.iov_len = sizeof (struct req_lib_cfg_local_get); error = qb_to_cs_error (qb_ipcc_sendv_recv ( cfg_inst->c, &iov, 1, &res_lib_cfg_local_get, sizeof (struct res_lib_cfg_local_get), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_cfg_local_get.header.error; *local_nodeid = res_lib_cfg_local_get.local_nodeid; error_exit: (void)hdb_handle_put (&cfg_hdb, handle); return (error); } cs_error_t corosync_cfg_crypto_set ( corosync_cfg_handle_t handle, unsigned int type) { struct cfg_inst *cfg_inst; struct req_lib_cfg_crypto_set req_lib_cfg_crypto_set; struct res_lib_cfg_crypto_set res_lib_cfg_crypto_set; struct iovec iov; cs_error_t error; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_crypto_set.header.id = MESSAGE_REQ_CFG_CRYPTO_SET; req_lib_cfg_crypto_set.header.size = sizeof (struct req_lib_cfg_crypto_set); req_lib_cfg_crypto_set.type = type; iov.iov_base = (void *)&req_lib_cfg_crypto_set; iov.iov_len = sizeof (struct req_lib_cfg_crypto_set); error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c, &iov, 1, &res_lib_cfg_crypto_set, sizeof (struct res_lib_cfg_crypto_set), -1)); if (error == CS_OK) error = res_lib_cfg_crypto_set.header.error; (void)hdb_handle_put (&cfg_hdb, handle); return (error); } diff --git a/lib/confdb.c b/lib/confdb.c index 51a8c340..831b5cc9 100644 --- a/lib/confdb.c +++ b/lib/confdb.c @@ -1,1811 +1,1814 @@ /* * Copyright (c) 2008-2010 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* * Provides access to data in the corosync object database */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "sa-confdb.h" /* Hold the information for iterators so that callers can do recursive tree traversals. each object_handle can have its own iterator */ struct iter_context { struct list_head list; hdb_handle_t parent_object_handle; hdb_handle_t find_handle; hdb_handle_t next_entry; }; struct confdb_inst { qb_ipcc_connection_t *c; int finalize; int standalone; confdb_callbacks_t callbacks; const void *context; struct list_head object_find_head; struct list_head object_iter_head; struct list_head key_iter_head; }; DECLARE_HDB_DATABASE(confdb_handle_t_db,NULL); static cs_error_t do_find_destroy(struct confdb_inst *confdb_inst, hdb_handle_t find_handle); /* Safely tidy one iterator context list */ static void free_context_list(struct confdb_inst *confdb_inst, struct list_head *list) { struct iter_context *context; struct list_head *iter, *tmp; for (iter = list->next, tmp = iter->next; iter != list; iter = tmp, tmp = iter->next) { context = list_entry (iter, struct iter_context, list); (void)do_find_destroy(confdb_inst, context->find_handle); free(context); } } static struct iter_context *find_iter_context(struct list_head *list, hdb_handle_t object_handle) { struct iter_context *context; struct list_head *iter; for (iter = list->next; iter != list; iter = iter->next) { context = list_entry (iter, struct iter_context, list); if (context->parent_object_handle == object_handle) return context; } return NULL; } /** * @defgroup confdb_corosync confdb * @ingroup corosync * * @{ */ cs_error_t confdb_initialize ( confdb_handle_t *handle, confdb_callbacks_t *callbacks) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_create (&confdb_handle_t_db, sizeof (struct confdb_inst), handle)); if (error != CS_OK) { goto error_no_destroy; } error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, *handle, (void *)&confdb_inst)); if (error != CS_OK) { goto error_destroy; } if (getenv("COROSYNC_DEFAULT_CONFIG_IFACE")) { error = confdb_sa_init(); confdb_inst->standalone = 1; } else { error = CS_OK; confdb_inst->c = qb_ipcc_connect ("confdb", IPC_REQUEST_SIZE); if (confdb_inst->c == NULL) { error = qb_to_cs_error(-errno); goto error_put_destroy; } } if (error != CS_OK) goto error_put_destroy; if (callbacks) { memcpy (&confdb_inst->callbacks, callbacks, sizeof (confdb_callbacks_t)); } list_init (&confdb_inst->object_find_head); list_init (&confdb_inst->object_iter_head); list_init (&confdb_inst->key_iter_head); (void)hdb_handle_put (&confdb_handle_t_db, *handle); return (CS_OK); error_put_destroy: (void)hdb_handle_put (&confdb_handle_t_db, *handle); error_destroy: (void)hdb_handle_destroy (&confdb_handle_t_db, *handle); error_no_destroy: return (error); } cs_error_t confdb_finalize ( confdb_handle_t handle) { struct confdb_inst *confdb_inst; cs_error_t error; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* * Another thread has already started finalizing */ if (confdb_inst->finalize) { (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_ERR_BAD_HANDLE); } confdb_inst->finalize = 1; /* Free saved context handles */ free_context_list(confdb_inst, &confdb_inst->object_find_head); free_context_list(confdb_inst, &confdb_inst->object_iter_head); free_context_list(confdb_inst, &confdb_inst->key_iter_head); if (!confdb_inst->standalone) { qb_ipcc_disconnect (confdb_inst->c); } (void)hdb_handle_destroy (&confdb_handle_t_db, handle); (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_fd_get ( confdb_handle_t handle, int *fd) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } error = qb_to_cs_error (qb_ipcc_fd_get (confdb_inst->c, fd)); (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_context_get ( confdb_handle_t handle, const void **context) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } *context = confdb_inst->context; (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_context_set ( confdb_handle_t handle, const void *context) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } confdb_inst->context = context; (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_dispatch ( confdb_handle_t handle, cs_dispatch_flags_t dispatch_types) { int timeout = -1; cs_error_t error; int cont = 1; /* always continue do loop except when set to 0 */ struct confdb_inst *confdb_inst; confdb_callbacks_t callbacks; struct res_lib_confdb_key_change_callback *res_key_changed_pt; struct res_lib_confdb_object_create_callback *res_object_created_pt; struct res_lib_confdb_object_destroy_callback *res_object_destroyed_pt; struct res_lib_confdb_reload_callback *res_reload_pt; struct qb_ipc_response_header *dispatch_data; char dispatch_buf[IPC_DISPATCH_SIZE]; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_put; } /* * Timeout instantly for CS_DISPATCH_ONE or CS_DISPATCH_ALL and * wait indefinitely for CS_DISPATCH_BLOCKING */ if (dispatch_types == CONFDB_DISPATCH_ALL) { timeout = 0; } dispatch_data = (struct qb_ipc_response_header *)dispatch_buf; do { error = qb_to_cs_error(qb_ipcc_event_recv ( confdb_inst->c, dispatch_buf, IPC_DISPATCH_SIZE, timeout)); if (error == CS_ERR_BAD_HANDLE) { error = CS_OK; goto error_put; } if (error == CS_ERR_TRY_AGAIN) { error = CS_OK; if (dispatch_types == CONFDB_DISPATCH_ALL) { break; /* exit do while cont is 1 loop */ } else { continue; /* next poll */ } } if (error != CS_OK) { goto error_put; } /* * Make copy of callbacks, message data, unlock instance, and call callback * A risk of this dispatch method is that the callback routines may * operate at the same time that confdbFinalize has been called. */ memcpy (&callbacks, &confdb_inst->callbacks, sizeof (confdb_callbacks_t)); /* * Dispatch incoming message */ switch (dispatch_data->id) { case MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK: if (callbacks.confdb_key_change_notify_fn == NULL) { break; } res_key_changed_pt = (struct res_lib_confdb_key_change_callback *)dispatch_data; callbacks.confdb_key_change_notify_fn(handle, res_key_changed_pt->change_type, res_key_changed_pt->object_handle, res_key_changed_pt->parent_object_handle, res_key_changed_pt->object_name.value, res_key_changed_pt->object_name.length, res_key_changed_pt->key_name.value, res_key_changed_pt->key_name.length, res_key_changed_pt->key_value.value, res_key_changed_pt->key_value.length); break; case MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK: if (callbacks.confdb_object_create_change_notify_fn == NULL) { break; } res_object_created_pt = (struct res_lib_confdb_object_create_callback *)dispatch_data; callbacks.confdb_object_create_change_notify_fn(handle, res_object_created_pt->object_handle, res_object_created_pt->parent_object_handle, res_object_created_pt->name.value, res_object_created_pt->name.length); break; case MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK: if (callbacks.confdb_object_delete_change_notify_fn == NULL) { break; } res_object_destroyed_pt = (struct res_lib_confdb_object_destroy_callback *)dispatch_data; callbacks.confdb_object_delete_change_notify_fn(handle, res_object_destroyed_pt->parent_object_handle, res_object_destroyed_pt->name.value, res_object_destroyed_pt->name.length); break; case MESSAGE_RES_CONFDB_RELOAD_CALLBACK: if (callbacks.confdb_reload_notify_fn == NULL) { break; } res_reload_pt = (struct res_lib_confdb_reload_callback *)dispatch_data; callbacks.confdb_reload_notify_fn(handle, res_reload_pt->type); break; default: error = CS_ERR_LIBRARY; goto error_noput; break; } /* * Determine if more messages should be processed */ if (dispatch_types == CS_DISPATCH_ONE) { cont = 0; } } while (cont); error_put: (void)hdb_handle_put (&confdb_handle_t_db, handle); error_noput: return (error); } cs_error_t confdb_object_create ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_create req_lib_confdb_object_create; struct res_lib_confdb_object_create res_lib_confdb_object_create; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_create(parent_object_handle, object_name, object_name_len, object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_create.header.size = sizeof (struct req_lib_confdb_object_create); req_lib_confdb_object_create.header.id = MESSAGE_REQ_CONFDB_OBJECT_CREATE; req_lib_confdb_object_create.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_object_create.object_name.value, object_name, object_name_len); req_lib_confdb_object_create.object_name.length = object_name_len; iov.iov_base = (char *)&req_lib_confdb_object_create; iov.iov_len = sizeof (struct req_lib_confdb_object_create); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_object_create, sizeof (struct res_lib_confdb_object_create), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_create.header.error; *object_handle = res_lib_confdb_object_create.object_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_destroy ( confdb_handle_t handle, hdb_handle_t object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_destroy req_lib_confdb_object_destroy; struct qb_ipc_response_header res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_destroy(object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_destroy.header.size = sizeof (struct req_lib_confdb_object_destroy); req_lib_confdb_object_destroy.header.id = MESSAGE_REQ_CONFDB_OBJECT_DESTROY; req_lib_confdb_object_destroy.object_handle = object_handle; iov.iov_base = (char *)&req_lib_confdb_object_destroy; iov.iov_len = sizeof (struct req_lib_confdb_object_destroy); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res, sizeof (struct qb_ipc_response_header), -1)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_parent_get ( confdb_handle_t handle, hdb_handle_t object_handle, hdb_handle_t *parent_object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_parent_get req_lib_confdb_object_parent_get; struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_parent_get(object_handle, parent_object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_parent_get.header.size = sizeof (struct req_lib_confdb_object_parent_get); req_lib_confdb_object_parent_get.header.id = MESSAGE_REQ_CONFDB_OBJECT_PARENT_GET; req_lib_confdb_object_parent_get.object_handle = object_handle; iov.iov_base = (char *)&req_lib_confdb_object_parent_get; iov.iov_len = sizeof (struct req_lib_confdb_object_parent_get); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_object_parent_get, sizeof (struct res_lib_confdb_object_parent_get), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_parent_get.header.error; *parent_object_handle = res_lib_confdb_object_parent_get.parent_object_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_name_get ( confdb_handle_t handle, hdb_handle_t object_handle, char *object_name, size_t *object_name_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_name_get request; struct res_lib_confdb_object_name_get response; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_name_get(object_handle, object_name, object_name_len)) error = CS_ERR_ACCESS; goto error_exit; } request.header.size = sizeof (struct req_lib_confdb_object_name_get); request.header.id = MESSAGE_REQ_CONFDB_OBJECT_NAME_GET; request.object_handle = object_handle; iov.iov_base = (char *)&request; iov.iov_len = sizeof (struct req_lib_confdb_object_name_get); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &response, sizeof (struct res_lib_confdb_object_name_get), -1)); if (error != CS_OK) { goto error_exit; } error = response.header.error; if (error == CS_OK) { *object_name_len = response.object_name.length; memcpy(object_name, response.object_name.value, *object_name_len); } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } static cs_error_t do_find_destroy( struct confdb_inst *confdb_inst, hdb_handle_t find_handle) { cs_error_t error; struct iovec iov; struct req_lib_confdb_object_find_destroy req_lib_confdb_object_find_destroy; struct qb_ipc_response_header res; if (!find_handle) return CS_OK; if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_find_destroy(find_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_find_destroy.header.size = sizeof (struct req_lib_confdb_object_find_destroy); req_lib_confdb_object_find_destroy.header.id = MESSAGE_REQ_CONFDB_OBJECT_FIND_DESTROY; req_lib_confdb_object_find_destroy.find_handle = find_handle; iov.iov_base = (char *)&req_lib_confdb_object_find_destroy; iov.iov_len = sizeof (struct req_lib_confdb_object_find_destroy); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res, sizeof (struct qb_ipc_response_header), -1)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: return (error); } cs_error_t confdb_object_find_destroy( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct iter_context *context; cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); error = do_find_destroy(confdb_inst, context->find_handle); if (error == CS_OK) { list_del(&context->list); free(context); } (void)hdb_handle_put (&confdb_handle_t_db, handle); return error; } cs_error_t confdb_object_iter_destroy( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct iter_context *context; cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_iter_head, parent_object_handle); error = do_find_destroy(confdb_inst, context->find_handle); if (error == CS_OK) { list_del(&context->list); free(context); } (void)hdb_handle_put (&confdb_handle_t_db, handle); return error; } cs_error_t confdb_key_create ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_create req_lib_confdb_key_create; struct qb_ipc_response_header res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_create(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_create.header.size = sizeof (struct req_lib_confdb_key_create); req_lib_confdb_key_create.header.id = MESSAGE_REQ_CONFDB_KEY_CREATE; req_lib_confdb_key_create.object_handle = parent_object_handle; memcpy(req_lib_confdb_key_create.key_name.value, key_name, key_name_len); req_lib_confdb_key_create.key_name.length = key_name_len; memcpy(req_lib_confdb_key_create.value.value, value, value_len); req_lib_confdb_key_create.value.length = value_len; iov.iov_base = (char *)&req_lib_confdb_key_create; iov.iov_len = sizeof (struct req_lib_confdb_key_create); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res, sizeof (res), -1)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_create_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *key_name, const void *value, size_t value_len, confdb_value_types_t type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_create_typed request; struct qb_ipc_response_header res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_create_typed(parent_object_handle, key_name, value, value_len, type)) error = CS_ERR_ACCESS; goto error_exit; } request.header.size = sizeof (struct req_lib_confdb_key_create_typed); request.header.id = MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED; request.object_handle = parent_object_handle; request.key_name.length = strlen(key_name)+1; memcpy(request.key_name.value, key_name, request.key_name.length); memcpy(request.value.value, value, value_len); request.value.length = value_len; request.type = type; iov.iov_base = (char *)&request; iov.iov_len = sizeof (struct req_lib_confdb_key_create_typed); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res, sizeof (res), -1)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_delete ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_delete req_lib_confdb_key_delete; struct qb_ipc_response_header res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_delete(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_delete.header.size = sizeof (struct req_lib_confdb_key_delete); req_lib_confdb_key_delete.header.id = MESSAGE_REQ_CONFDB_KEY_DELETE; req_lib_confdb_key_delete.object_handle = parent_object_handle; memcpy(req_lib_confdb_key_delete.key_name.value, key_name, key_name_len); req_lib_confdb_key_delete.key_name.length = key_name_len; memcpy(req_lib_confdb_key_delete.value.value, value, value_len); req_lib_confdb_key_delete.value.length = value_len; iov.iov_base = (char *)&req_lib_confdb_key_delete; iov.iov_len = sizeof (struct req_lib_confdb_key_delete); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res, sizeof (res), -1)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_get ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, void *value, size_t *value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_get res_lib_confdb_key_get; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_get(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_GET; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_key_get, sizeof (struct res_lib_confdb_key_get), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_get.header.error; if (error == CS_OK) { *value_len = res_lib_confdb_key_get.value.length; memcpy(value, res_lib_confdb_key_get.value.value, *value_len); } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_get_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *key_name, void *value, size_t *value_len, confdb_value_types_t *type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_get_typed response; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_get_typed(parent_object_handle, key_name, value, value_len, (int*)type)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_GET_TYPED; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; req_lib_confdb_key_get.key_name.length = strlen(key_name) + 1; memcpy(req_lib_confdb_key_get.key_name.value, key_name, req_lib_confdb_key_get.key_name.length); iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &response, sizeof (struct res_lib_confdb_key_get_typed), -1)); if (error != CS_OK) { goto error_exit; } error = response.header.error; if (error == CS_OK) { *value_len = response.value.length; *type = response.type; memcpy(value, response.value.value, *value_len); } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_increment ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_increment(parent_object_handle, key_name, key_name_len, value)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_INCREMENT; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_incdec.header.error; if (error == CS_OK) { *value = res_lib_confdb_key_incdec.value; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_decrement ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_decrement(parent_object_handle, key_name, key_name_len, value)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_DECREMENT; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_incdec.header.error; if (error == CS_OK) { *value = res_lib_confdb_key_incdec.value; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_replace ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *old_value, size_t old_value_len, const void *new_value, size_t new_value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_replace req_lib_confdb_key_replace; struct qb_ipc_response_header res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_replace(parent_object_handle, key_name, key_name_len, old_value, old_value_len, new_value, new_value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_replace.header.size = sizeof (struct req_lib_confdb_key_replace); req_lib_confdb_key_replace.header.id = MESSAGE_REQ_CONFDB_KEY_REPLACE; req_lib_confdb_key_replace.object_handle = parent_object_handle; memcpy(req_lib_confdb_key_replace.key_name.value, key_name, key_name_len); req_lib_confdb_key_replace.key_name.length = key_name_len; memcpy(req_lib_confdb_key_replace.old_value.value, old_value, old_value_len); req_lib_confdb_key_replace.old_value.length = old_value_len; memcpy(req_lib_confdb_key_replace.new_value.value, new_value, new_value_len); req_lib_confdb_key_replace.new_value.length = new_value_len; iov.iov_base = (char *)&req_lib_confdb_key_replace; iov.iov_len = sizeof (struct req_lib_confdb_key_replace); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res, sizeof (res), -1)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_iter_start ( confdb_handle_t handle, hdb_handle_t object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_iter_head, object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->parent_object_handle = object_handle; context->find_handle = 0; list_add(&context->list, &confdb_inst->object_iter_head); } /* Start a new find context */ if (context->find_handle) { (void)do_find_destroy(confdb_inst, context->find_handle); context->find_handle = 0; } (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_key_iter_start ( confdb_handle_t handle, hdb_handle_t object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->key_iter_head, object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->parent_object_handle = object_handle; list_add(&context->list, &confdb_inst->key_iter_head); } context->find_handle = 0; context->next_entry = 0; (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_object_find_start ( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->find_handle = 0; context->parent_object_handle = parent_object_handle; list_add(&context->list, &confdb_inst->object_find_head); } /* Start a new find context */ if (context->find_handle) { (void)do_find_destroy(confdb_inst, context->find_handle); context->find_handle = 0; } (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_object_find ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_object_find req_lib_confdb_object_find; struct res_lib_confdb_object_find res_lib_confdb_object_find; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_object_find_start first */ context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_find(parent_object_handle, &context->find_handle, object_handle, object_name, object_name_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_find.header.size = sizeof (struct req_lib_confdb_object_find); req_lib_confdb_object_find.header.id = MESSAGE_REQ_CONFDB_OBJECT_FIND; req_lib_confdb_object_find.parent_object_handle = parent_object_handle; req_lib_confdb_object_find.find_handle = context->find_handle; memcpy(req_lib_confdb_object_find.object_name.value, object_name, object_name_len); req_lib_confdb_object_find.object_name.length = object_name_len; iov.iov_base = (char *)&req_lib_confdb_object_find; iov.iov_len = sizeof (struct req_lib_confdb_object_find); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_object_find, sizeof (struct res_lib_confdb_object_find), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_find.header.error; *object_handle = res_lib_confdb_object_find.object_handle; context->find_handle = res_lib_confdb_object_find.find_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_iter ( confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, void *object_name, size_t *object_name_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_object_iter req_lib_confdb_object_iter; struct res_lib_confdb_object_iter res_lib_confdb_object_iter; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_object_iter_start first */ context = find_iter_context(&confdb_inst->object_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; *object_name_len = 0; if (confdb_sa_object_iter(parent_object_handle, &context->find_handle, object_handle, NULL, 0, object_name, object_name_len)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_object_iter.header.size = sizeof (struct req_lib_confdb_object_iter); req_lib_confdb_object_iter.header.id = MESSAGE_REQ_CONFDB_OBJECT_ITER; req_lib_confdb_object_iter.parent_object_handle = parent_object_handle; req_lib_confdb_object_iter.find_handle = context->find_handle; iov.iov_base = (char *)&req_lib_confdb_object_iter; iov.iov_len = sizeof (struct req_lib_confdb_object_iter); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_object_iter, sizeof (struct res_lib_confdb_object_iter), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_iter.header.error; if (error == CS_OK) { *object_name_len = res_lib_confdb_object_iter.object_name.length; memcpy(object_name, res_lib_confdb_object_iter.object_name.value, *object_name_len); *object_handle = res_lib_confdb_object_iter.object_handle; context->find_handle = res_lib_confdb_object_iter.find_handle; } sa_exit: error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_iter ( confdb_handle_t handle, hdb_handle_t parent_object_handle, void *key_name, size_t *key_name_len, void *value, size_t *value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_key_iter req_lib_confdb_key_iter; struct res_lib_confdb_key_iter res_lib_confdb_key_iter; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_key_iter_start first */ context = find_iter_context(&confdb_inst->key_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_iter(parent_object_handle, context->next_entry, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_key_iter.header.size = sizeof (struct req_lib_confdb_key_iter); req_lib_confdb_key_iter.header.id = MESSAGE_REQ_CONFDB_KEY_ITER; req_lib_confdb_key_iter.parent_object_handle = parent_object_handle; req_lib_confdb_key_iter.next_entry= context->next_entry; iov.iov_base = (char *)&req_lib_confdb_key_iter; iov.iov_len = sizeof (struct req_lib_confdb_key_iter); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_key_iter, sizeof (struct res_lib_confdb_key_iter), -1)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_iter.header.error; if (error == CS_OK) { char* key_name_str = (char*)key_name; *key_name_len = res_lib_confdb_key_iter.key_name.length; memcpy(key_name, res_lib_confdb_key_iter.key_name.value, *key_name_len); key_name_str[res_lib_confdb_key_iter.key_name.length] = '\0'; *value_len = res_lib_confdb_key_iter.value.length; memcpy(value, res_lib_confdb_key_iter.value.value, *value_len); } sa_exit: context->next_entry++; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_iter_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, char *key_name, void *value, size_t *value_len, confdb_value_types_t *type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_key_iter req_lib_confdb_key_iter; struct res_lib_confdb_key_iter_typed response; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_key_iter_start first */ context = find_iter_context(&confdb_inst->key_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_iter_typed(parent_object_handle, context->next_entry, key_name, value, value_len, (int*)type)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_key_iter.header.size = sizeof (struct req_lib_confdb_key_iter); req_lib_confdb_key_iter.header.id = MESSAGE_REQ_CONFDB_KEY_ITER_TYPED; req_lib_confdb_key_iter.parent_object_handle = parent_object_handle; req_lib_confdb_key_iter.next_entry= context->next_entry; iov.iov_base = (char *)&req_lib_confdb_key_iter; iov.iov_len = sizeof (struct req_lib_confdb_key_iter); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &response, sizeof (struct res_lib_confdb_key_iter_typed), -1)); if (error != CS_OK) { goto error_exit; } error = response.header.error; if (error == CS_OK) { memcpy(key_name, response.key_name.value, response.key_name.length); key_name[response.key_name.length] = '\0'; *value_len = response.value.length; memcpy(value, response.value.value, *value_len); *type = response.type; } sa_exit: context->next_entry++; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_write ( confdb_handle_t handle, char *error_text, size_t errbuf_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct qb_ipc_request_header req; struct res_lib_confdb_write res_lib_confdb_write; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { /* FIXME: set error_text */ return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_write(error_text, errbuf_len)) error = CS_ERR_ACCESS; goto error_exit; } req.size = sizeof (struct qb_ipc_request_header); req.id = MESSAGE_REQ_CONFDB_WRITE; iov.iov_base = (char *)&req; iov.iov_len = sizeof (struct qb_ipc_request_header); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_write, sizeof (struct res_lib_confdb_write), -1)); if (error != CS_OK) { /* FIXME: set error_text */ goto error_exit; } error = res_lib_confdb_write.header.error; if (res_lib_confdb_write.error.length) { memcpy(error_text, res_lib_confdb_write.error.value, QB_MIN(res_lib_confdb_write.error.length,errbuf_len)); error_text[errbuf_len-1] = '\0'; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_reload ( confdb_handle_t handle, int flush, char *error_text, size_t errbuf_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct res_lib_confdb_reload res_lib_confdb_reload; struct req_lib_confdb_reload req_lib_confdb_reload; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { /* FIXME: set error_text */ return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_reload(flush, error_text, errbuf_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_reload.header.size = sizeof (req_lib_confdb_reload); req_lib_confdb_reload.header.id = MESSAGE_REQ_CONFDB_RELOAD; req_lib_confdb_reload.flush = flush; iov.iov_base = (char *)&req_lib_confdb_reload; iov.iov_len = sizeof (req_lib_confdb_reload); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res_lib_confdb_reload, sizeof (struct res_lib_confdb_reload), -1)); if (error != CS_OK) { /* FIXME: set error_text */ goto error_exit; } error = res_lib_confdb_reload.header.error; if(res_lib_confdb_reload.error.length) { memcpy(error_text, res_lib_confdb_reload.error.value, QB_MIN(res_lib_confdb_reload.error.length,errbuf_len)); error_text[errbuf_len-1] = '\0'; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_track_changes ( confdb_handle_t handle, hdb_handle_t object_handle, unsigned int flags) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_track_start req; struct qb_ipc_response_header res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_exit; } req.header.size = sizeof (struct req_lib_confdb_object_track_start); req.header.id = MESSAGE_REQ_CONFDB_TRACK_START; req.object_handle = object_handle; req.flags = flags; iov.iov_base = (char *)&req; iov.iov_len = sizeof (struct req_lib_confdb_object_track_start); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res, sizeof (struct qb_ipc_response_header), -1)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_stop_track_changes (confdb_handle_t handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct qb_ipc_request_header req; struct qb_ipc_response_header res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_exit; } req.size = sizeof (struct qb_ipc_request_header); req.id = MESSAGE_REQ_CONFDB_TRACK_STOP; iov.iov_base = (char *)&req; iov.iov_len = sizeof (struct qb_ipc_request_header); error = qb_to_cs_error (qb_ipcc_sendv_recv ( confdb_inst->c, &iov, 1, &res, sizeof (struct qb_ipc_response_header), -1)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } +/** + * @} + */ diff --git a/services/confdb.c b/services/confdb.c index f70f2efd..65a48abb 100644 --- a/services/confdb.c +++ b/services/confdb.c @@ -1,1090 +1,1094 @@ /* * Copyright (c) 2008-2010 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include -#include +#include #include + +#include #include #include #include #include #include #include #include #include LOGSYS_DECLARE_SUBSYS ("CONFDB"); static hdb_handle_t * m2h (mar_uint64_t *m) { /* FIXME enable the following when/if we use gnulib: (it's a compile-time assertion; i.e., zero run-time cost) verify (sizeof (*m) == sizeof (hdb_handle_t)); */ return (void *) m; } static struct corosync_api_v1 *api; static int notify_pipe[2]; struct confdb_ipc_message_holder { void *conn; size_t mlen; struct list_head list; char msg[]; }; DECLARE_LIST_INIT(confdb_ipc_message_holder_list_head); pthread_mutex_t confdb_ipc_message_holder_list_mutex = PTHREAD_MUTEX_INITIALIZER; static int confdb_exec_init_fn ( struct corosync_api_v1 *corosync_api); static int confdb_exec_exit_fn(void); static int fd_set_nonblocking(int fd); static int objdb_notify_dispatch(int fd, int revents, void *data); + + static int confdb_lib_init_fn (void *conn); static int confdb_lib_exit_fn (void *conn); static void message_handler_req_lib_confdb_object_create (void *conn, const void *message); static void message_handler_req_lib_confdb_object_destroy (void *conn, const void *message); static void message_handler_req_lib_confdb_object_find_destroy (void *conn, const void *message); static void message_handler_req_lib_confdb_key_create (void *conn, const void *message); static void message_handler_req_lib_confdb_key_create_typed (void *conn, const void *message); static void message_handler_req_lib_confdb_key_get (void *conn, const void *message); static void message_handler_req_lib_confdb_key_get_typed (void *conn, const void *message); static void message_handler_req_lib_confdb_key_replace (void *conn, const void *message); static void message_handler_req_lib_confdb_key_delete (void *conn, const void *message); static void message_handler_req_lib_confdb_key_iter (void *conn, const void *message); static void message_handler_req_lib_confdb_key_iter_typed (void *conn, const void *message); static void message_handler_req_lib_confdb_key_increment (void *conn, const void *message); static void message_handler_req_lib_confdb_key_decrement (void *conn, const void *message); static void message_handler_req_lib_confdb_object_iter (void *conn, const void *message); static void message_handler_req_lib_confdb_object_find (void *conn, const void *message); static void message_handler_req_lib_confdb_object_parent_get (void *conn, const void *message); static void message_handler_req_lib_confdb_object_name_get (void *conn, const void *message); static void message_handler_req_lib_confdb_write (void *conn, const void *message); static void message_handler_req_lib_confdb_reload (void *conn, const void *message); static void message_handler_req_lib_confdb_track_start (void *conn, const void *message); static void message_handler_req_lib_confdb_track_stop (void *conn, const void *message); static void confdb_notify_lib_of_key_change( object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_name_len, const void *key_value_pt, size_t key_value_len, void *priv_data_pt); static void confdb_notify_lib_of_new_object( hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len, void *priv_data_pt); static void confdb_notify_lib_of_destroyed_object( hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len, void *priv_data_pt); static void confdb_notify_lib_of_reload( objdb_reload_notify_type_t notify_type, int flush, void *priv_data_pt); /* * Library Handler Definition */ static struct corosync_lib_handler confdb_lib_engine[] = { { /* 0 */ .lib_handler_fn = message_handler_req_lib_confdb_object_create, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 1 */ .lib_handler_fn = message_handler_req_lib_confdb_object_destroy, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 2 */ .lib_handler_fn = message_handler_req_lib_confdb_object_find, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 3 */ .lib_handler_fn = message_handler_req_lib_confdb_key_create, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 4 */ .lib_handler_fn = message_handler_req_lib_confdb_key_get, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 5 */ .lib_handler_fn = message_handler_req_lib_confdb_key_replace, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 6 */ .lib_handler_fn = message_handler_req_lib_confdb_key_delete, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 7 */ .lib_handler_fn = message_handler_req_lib_confdb_object_iter, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 8 */ .lib_handler_fn = message_handler_req_lib_confdb_object_parent_get, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 9 */ .lib_handler_fn = message_handler_req_lib_confdb_key_iter, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 10 */ .lib_handler_fn = message_handler_req_lib_confdb_track_start, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 11 */ .lib_handler_fn = message_handler_req_lib_confdb_track_stop, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 12 */ .lib_handler_fn = message_handler_req_lib_confdb_write, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 13 */ .lib_handler_fn = message_handler_req_lib_confdb_reload, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 14 */ .lib_handler_fn = message_handler_req_lib_confdb_object_find_destroy, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 15 */ .lib_handler_fn = message_handler_req_lib_confdb_key_increment, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 16 */ .lib_handler_fn = message_handler_req_lib_confdb_key_decrement, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 17 */ .lib_handler_fn = message_handler_req_lib_confdb_key_create_typed, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 18 */ .lib_handler_fn = message_handler_req_lib_confdb_key_get_typed, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 19 */ .lib_handler_fn = message_handler_req_lib_confdb_key_iter_typed, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 20 */ .lib_handler_fn = message_handler_req_lib_confdb_object_name_get, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, }; struct corosync_service_engine confdb_service_engine = { .name = "corosync cluster config database access v1.01", .id = CONFDB_SERVICE, .priority = 1, .private_data_size = 0, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED, .allow_inquorate = CS_LIB_ALLOW_INQUORATE, .lib_init_fn = confdb_lib_init_fn, .lib_exit_fn = confdb_lib_exit_fn, .lib_engine = confdb_lib_engine, .lib_engine_count = sizeof (confdb_lib_engine) / sizeof (struct corosync_lib_handler), .exec_init_fn = confdb_exec_init_fn, .exec_exit_fn = confdb_exec_exit_fn, }; /* * Dynamic loader definition */ static struct corosync_service_engine *confdb_get_service_engine_ver0 (void); static struct corosync_service_engine_iface_ver0 confdb_service_engine_iface = { .corosync_get_service_engine_ver0 = confdb_get_service_engine_ver0 }; static struct lcr_iface corosync_confdb_ver0[1] = { { .name = "corosync_confdb", .version = 0, .versions_replace = 0, .versions_replace_count = 0, .dependencies = 0, .dependency_count = 0, .constructor = NULL, .destructor = NULL, .interfaces = NULL } }; static struct lcr_comp confdb_comp_ver0 = { .iface_count = 1, .ifaces = corosync_confdb_ver0 }; static struct corosync_service_engine *confdb_get_service_engine_ver0 (void) { return (&confdb_service_engine); } #ifdef COROSYNC_SOLARIS void corosync_lcr_component_register (void); void corosync_lcr_component_register (void) { #else __attribute__ ((constructor)) static void corosync_lcr_component_register (void) { #endif lcr_interfaces_set (&corosync_confdb_ver0[0], &confdb_service_engine_iface); lcr_component_register (&confdb_comp_ver0); } static int confdb_exec_exit_fn(void) { api->poll_dispatch_delete(api->poll_handle_get(), notify_pipe[0]); close(notify_pipe[0]); close(notify_pipe[1]); return 0; } static int confdb_exec_init_fn ( struct corosync_api_v1 *corosync_api) { int i; #ifdef COROSYNC_SOLARIS logsys_subsys_init(); #endif api = corosync_api; if (pipe(notify_pipe) != 0) { return -1; } for (i = 0; i < 2; i++) { if (fd_set_nonblocking (notify_pipe[i]) == -1) { return -1; } } return api->poll_dispatch_add(api->poll_handle_get(), notify_pipe[0], POLLIN, NULL, objdb_notify_dispatch); } static int confdb_lib_init_fn (void *conn) { log_printf(LOGSYS_LEVEL_DEBUG, "lib_init_fn: conn=%p\n", conn); return (0); } static int confdb_lib_exit_fn (void *conn) { log_printf(LOGSYS_LEVEL_DEBUG, "exit_fn for conn=%p\n", conn); /* cleanup the object trackers for this client. */ api->object_track_stop(confdb_notify_lib_of_key_change, confdb_notify_lib_of_new_object, confdb_notify_lib_of_destroyed_object, confdb_notify_lib_of_reload, conn); return (0); } static int fd_set_nonblocking(int fd) { int flags; int res; flags = fcntl (fd, F_GETFL); if (flags == -1) { return -1; } flags |= O_NONBLOCK; res = fcntl (fd, F_SETFL, flags); return res; } static void message_handler_req_lib_confdb_object_create (void *conn, const void *message) { const struct req_lib_confdb_object_create *req_lib_confdb_object_create = message; struct res_lib_confdb_object_create res_lib_confdb_object_create; hdb_handle_t object_handle; int ret = CS_OK; if (api->object_create(req_lib_confdb_object_create->parent_object_handle, &object_handle, req_lib_confdb_object_create->object_name.value, req_lib_confdb_object_create->object_name.length)) ret = CS_ERR_ACCESS; res_lib_confdb_object_create.object_handle = object_handle; res_lib_confdb_object_create.header.size = sizeof(res_lib_confdb_object_create); res_lib_confdb_object_create.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE; res_lib_confdb_object_create.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_create, sizeof(res_lib_confdb_object_create)); } static void message_handler_req_lib_confdb_object_destroy (void *conn, const void *message) { const struct req_lib_confdb_object_destroy *req_lib_confdb_object_destroy = message; struct qb_ipc_response_header res; int ret = CS_OK; if (api->object_destroy(req_lib_confdb_object_destroy->object_handle)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_object_find_destroy (void *conn, const void *message) { const struct req_lib_confdb_object_find_destroy *req_lib_confdb_object_find_destroy = message; struct qb_ipc_response_header res; int ret = CS_OK; if (api->object_find_destroy(req_lib_confdb_object_find_destroy->find_handle)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_create (void *conn, const void *message) { const struct req_lib_confdb_key_create *req_lib_confdb_key_create = message; struct qb_ipc_response_header res; int ret = CS_OK; if (api->object_key_create(req_lib_confdb_key_create->object_handle, req_lib_confdb_key_create->key_name.value, req_lib_confdb_key_create->key_name.length, req_lib_confdb_key_create->value.value, req_lib_confdb_key_create->value.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_CREATE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_create_typed (void *conn, const void *message) { const struct req_lib_confdb_key_create_typed *req_lib_confdb_key_create = message; struct qb_ipc_response_header res; int ret = CS_OK; if (api->object_key_create_typed(req_lib_confdb_key_create->object_handle, (char*)req_lib_confdb_key_create->key_name.value, req_lib_confdb_key_create->value.value, req_lib_confdb_key_create->value.length, req_lib_confdb_key_create->type)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_CREATE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_get (void *conn, const void *message) { const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; struct res_lib_confdb_key_get res_lib_confdb_key_get; size_t value_len; void *value; int ret = CS_OK; if (api->object_key_get(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &value, &value_len)) ret = CS_ERR_ACCESS; else { memcpy(res_lib_confdb_key_get.value.value, value, value_len); res_lib_confdb_key_get.value.length = value_len; } res_lib_confdb_key_get.header.size = sizeof(res_lib_confdb_key_get); res_lib_confdb_key_get.header.id = MESSAGE_RES_CONFDB_KEY_GET; res_lib_confdb_key_get.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get)); } static void message_handler_req_lib_confdb_key_get_typed (void *conn, const void *message) { const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; struct res_lib_confdb_key_get_typed res_lib_confdb_key_get; size_t value_len; void *value; int ret = CS_OK; objdb_value_types_t type; char * key_name = (char*)req_lib_confdb_key_get->key_name.value; key_name[req_lib_confdb_key_get->key_name.length] = '\0'; if (api->object_key_get_typed(req_lib_confdb_key_get->parent_object_handle, key_name, &value, &value_len, &type)) ret = CS_ERR_ACCESS; else { memcpy(res_lib_confdb_key_get.value.value, value, value_len); res_lib_confdb_key_get.value.length = value_len; res_lib_confdb_key_get.type = type; } res_lib_confdb_key_get.header.size = sizeof(res_lib_confdb_key_get); res_lib_confdb_key_get.header.id = MESSAGE_RES_CONFDB_KEY_GET_TYPED; res_lib_confdb_key_get.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get)); } static void message_handler_req_lib_confdb_key_increment (void *conn, const void *message) { const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; int ret = CS_OK; if (api->object_key_increment(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &res_lib_confdb_key_incdec.value)) ret = CS_ERR_ACCESS; res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec); res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_INCREMENT; res_lib_confdb_key_incdec.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec)); } static void message_handler_req_lib_confdb_key_decrement (void *conn, const void *message) { const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; int ret = CS_OK; if (api->object_key_decrement(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &res_lib_confdb_key_incdec.value)) ret = CS_ERR_ACCESS; res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec); res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_DECREMENT; res_lib_confdb_key_incdec.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec)); } static void message_handler_req_lib_confdb_key_replace (void *conn, const void *message) { const struct req_lib_confdb_key_replace *req_lib_confdb_key_replace = message; struct qb_ipc_response_header res; int ret = CS_OK; if (api->object_key_replace(req_lib_confdb_key_replace->object_handle, req_lib_confdb_key_replace->key_name.value, req_lib_confdb_key_replace->key_name.length, req_lib_confdb_key_replace->new_value.value, req_lib_confdb_key_replace->new_value.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_REPLACE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_delete (void *conn, const void *message) { const struct req_lib_confdb_key_delete *req_lib_confdb_key_delete = message; struct qb_ipc_response_header res; int ret = CS_OK; if (api->object_key_delete(req_lib_confdb_key_delete->object_handle, req_lib_confdb_key_delete->key_name.value, req_lib_confdb_key_delete->key_name.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_DELETE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_object_parent_get (void *conn, const void *message) { const struct req_lib_confdb_object_parent_get *req_lib_confdb_object_parent_get = message; struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get; hdb_handle_t object_handle; int ret = CS_OK; if (api->object_parent_get(req_lib_confdb_object_parent_get->object_handle, &object_handle)) ret = CS_ERR_ACCESS; res_lib_confdb_object_parent_get.parent_object_handle = object_handle; res_lib_confdb_object_parent_get.header.size = sizeof(res_lib_confdb_object_parent_get); res_lib_confdb_object_parent_get.header.id = MESSAGE_RES_CONFDB_OBJECT_PARENT_GET; res_lib_confdb_object_parent_get.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_parent_get, sizeof(res_lib_confdb_object_parent_get)); } static void message_handler_req_lib_confdb_object_name_get (void *conn, const void *message) { const struct req_lib_confdb_object_name_get *request = message; struct res_lib_confdb_object_name_get response; int ret = CS_OK; char object_name[CS_MAX_NAME_LENGTH]; size_t object_name_len; if (api->object_name_get(request->object_handle, object_name, &object_name_len)) { ret = CS_ERR_ACCESS; } response.object_name.length = object_name_len; strncpy((char*)response.object_name.value, object_name, CS_MAX_NAME_LENGTH); response.object_name.value[CS_MAX_NAME_LENGTH-1] = '\0'; response.header.size = sizeof(response); response.header.id = MESSAGE_RES_CONFDB_OBJECT_NAME_GET; response.header.error = ret; api->ipc_response_send(conn, &response, sizeof(response)); } static void message_handler_req_lib_confdb_key_iter (void *conn, const void *message) { const struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = message; struct res_lib_confdb_key_iter res_lib_confdb_key_iter; void *key_name; size_t key_name_len; void *value; size_t value_len; int ret = CS_OK; if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle, req_lib_confdb_key_iter->next_entry, &key_name, &key_name_len, &value, &value_len)) ret = CS_ERR_ACCESS; else { memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len); memcpy(res_lib_confdb_key_iter.value.value, value, value_len); res_lib_confdb_key_iter.key_name.length = key_name_len; res_lib_confdb_key_iter.value.length = value_len; } res_lib_confdb_key_iter.header.size = sizeof(res_lib_confdb_key_iter); res_lib_confdb_key_iter.header.id = MESSAGE_RES_CONFDB_KEY_ITER; res_lib_confdb_key_iter.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter)); } static void message_handler_req_lib_confdb_key_iter_typed (void *conn, const void *message) { const struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = message; struct res_lib_confdb_key_iter_typed res_lib_confdb_key_iter; void *key_name; size_t key_name_len; void *value; size_t value_len; int ret = CS_OK; objdb_value_types_t my_type; if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle, req_lib_confdb_key_iter->next_entry, &key_name, &key_name_len, &value, &value_len)) ret = CS_ERR_ACCESS; else { memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len); memcpy(res_lib_confdb_key_iter.value.value, value, value_len); res_lib_confdb_key_iter.key_name.length = key_name_len; res_lib_confdb_key_iter.key_name.value[key_name_len] = '\0'; res_lib_confdb_key_iter.value.length = value_len; api->object_key_get_typed(req_lib_confdb_key_iter->parent_object_handle, (const char*)res_lib_confdb_key_iter.key_name.value, &value, &value_len, &my_type); res_lib_confdb_key_iter.type = my_type; } res_lib_confdb_key_iter.header.size = sizeof(res_lib_confdb_key_iter); res_lib_confdb_key_iter.header.id = MESSAGE_RES_CONFDB_KEY_ITER_TYPED; res_lib_confdb_key_iter.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter)); } static void message_handler_req_lib_confdb_object_iter (void *conn, const void *message) { const struct req_lib_confdb_object_iter *req_lib_confdb_object_iter = message; struct res_lib_confdb_object_iter res_lib_confdb_object_iter; size_t object_name_len; int ret = CS_OK; if (!req_lib_confdb_object_iter->find_handle) { if (api->object_find_create(req_lib_confdb_object_iter->parent_object_handle, NULL, 0, m2h(&res_lib_confdb_object_iter.find_handle)) == -1) { ret = CS_ERR_ACCESS; goto response_send; } } else res_lib_confdb_object_iter.find_handle = req_lib_confdb_object_iter->find_handle; if (api->object_find_next(res_lib_confdb_object_iter.find_handle, m2h(&res_lib_confdb_object_iter.object_handle))) { ret = CS_ERR_ACCESS; api->object_find_destroy(res_lib_confdb_object_iter.find_handle); } else { if (api->object_name_get(res_lib_confdb_object_iter.object_handle, (char *)res_lib_confdb_object_iter.object_name.value, &object_name_len) == -1) { ret = CS_ERR_ACCESS; goto response_send; } else { res_lib_confdb_object_iter.object_name.length = object_name_len; } } response_send: res_lib_confdb_object_iter.header.size = sizeof(res_lib_confdb_object_iter); res_lib_confdb_object_iter.header.id = MESSAGE_RES_CONFDB_OBJECT_ITER; res_lib_confdb_object_iter.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_iter, sizeof(res_lib_confdb_object_iter)); } static void message_handler_req_lib_confdb_object_find (void *conn, const void *message) { const struct req_lib_confdb_object_find *req_lib_confdb_object_find = message; struct res_lib_confdb_object_find res_lib_confdb_object_find; int ret = CS_OK; if (!req_lib_confdb_object_find->find_handle) { if (api->object_find_create(req_lib_confdb_object_find->parent_object_handle, req_lib_confdb_object_find->object_name.value, req_lib_confdb_object_find->object_name.length, m2h(&res_lib_confdb_object_find.find_handle)) == -1) { ret = CS_ERR_ACCESS; goto response_send; } } else res_lib_confdb_object_find.find_handle = req_lib_confdb_object_find->find_handle; if (api->object_find_next(res_lib_confdb_object_find.find_handle, m2h(&res_lib_confdb_object_find.object_handle))) { ret = CS_ERR_ACCESS; api->object_find_destroy(res_lib_confdb_object_find.find_handle); } response_send: res_lib_confdb_object_find.header.size = sizeof(res_lib_confdb_object_find); res_lib_confdb_object_find.header.id = MESSAGE_RES_CONFDB_OBJECT_FIND; res_lib_confdb_object_find.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_find, sizeof(res_lib_confdb_object_find)); } static void message_handler_req_lib_confdb_write (void *conn, const void *message) { struct res_lib_confdb_write res_lib_confdb_write; int ret = CS_OK; const char *error_string = NULL; if (api->object_write_config(&error_string)) ret = CS_ERR_ACCESS; res_lib_confdb_write.header.size = sizeof(res_lib_confdb_write); res_lib_confdb_write.header.id = MESSAGE_RES_CONFDB_WRITE; res_lib_confdb_write.header.error = ret; if (error_string) { strcpy((char *)res_lib_confdb_write.error.value, error_string); res_lib_confdb_write.error.length = strlen(error_string) + 1; } else res_lib_confdb_write.error.length = 0; api->ipc_response_send(conn, &res_lib_confdb_write, sizeof(res_lib_confdb_write)); } static void message_handler_req_lib_confdb_reload (void *conn, const void *message) { const struct req_lib_confdb_reload *req_lib_confdb_reload = message; struct res_lib_confdb_reload res_lib_confdb_reload; int ret = CS_OK; const char *error_string = NULL; if (api->object_reload_config(req_lib_confdb_reload->flush, &error_string)) ret = CS_ERR_ACCESS; res_lib_confdb_reload.header.size = sizeof(res_lib_confdb_reload); res_lib_confdb_reload.header.id = MESSAGE_RES_CONFDB_RELOAD; res_lib_confdb_reload.header.error = ret; if(error_string) { strcpy((char *)res_lib_confdb_reload.error.value, error_string); res_lib_confdb_reload.error.length = strlen(error_string) + 1; } else res_lib_confdb_reload.error.length = 0; api->ipc_response_send(conn, &res_lib_confdb_reload, sizeof(res_lib_confdb_reload)); } static int objdb_notify_dispatch(int fd, int revents, void *data) { struct confdb_ipc_message_holder *holder; ssize_t rc; char pipe_cmd; if (revents & POLLHUP) { return -1; } pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex); retry_read: rc = read(fd, &pipe_cmd, sizeof(pipe_cmd)); if (rc == sizeof(pipe_cmd)) { goto retry_read; /* Flush whole buffer */ } if (rc == -1) { if (errno == EINTR) { goto retry_read; } if (errno != EAGAIN && errno != EWOULDBLOCK) { goto unlock_exit; } } else { goto unlock_exit; /* rc != -1 && rc != 1 -> end of file */ } while (!list_empty (&confdb_ipc_message_holder_list_head)) { holder = list_entry (confdb_ipc_message_holder_list_head.next, struct confdb_ipc_message_holder, list); list_del (&holder->list); /* * All list operations are done now, so unlock list mutex to * prevent deadlock in IPC. */ pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex); api->ipc_dispatch_send(holder->conn, holder->msg, holder->mlen); api->ipc_refcnt_dec(holder->conn); free(holder); /* * Next operation is again list one, so lock list again. */ pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex); } unlock_exit: pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex); return 0; } static int32_t ipc_dispatch_send_from_poll_thread(void *conn, const void *msg, size_t mlen) { struct confdb_ipc_message_holder *holder; ssize_t written; size_t holder_size; char pipe_cmd; api->ipc_refcnt_inc(conn); holder_size = sizeof (*holder) + mlen; holder = malloc (holder_size); if (holder == NULL) { api->ipc_refcnt_dec(conn); return -1; } memset(holder, 0, holder_size); holder->conn = conn; holder->mlen = mlen; memcpy(holder->msg, msg, mlen); list_init(&holder->list); pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex); list_add_tail (&holder->list, &confdb_ipc_message_holder_list_head); pipe_cmd = 'M'; /* Message */ retry_write: written = write(notify_pipe[1], &pipe_cmd, sizeof(pipe_cmd)); if (written == -1) { if (errno == EINTR) { goto retry_write; } if (errno != EAGAIN && errno != EWOULDBLOCK) { /* * Different error then EINTR or BLOCK -> exit with error */ goto refcnt_del_unlock_exit; } } else if (written != sizeof (pipe_cmd)) { goto refcnt_del_unlock_exit; } pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex); return 0; refcnt_del_unlock_exit: list_del (&holder->list); free(holder); api->ipc_refcnt_dec(conn); pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex); return -1; } static void confdb_notify_lib_of_key_change(object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_name_len, const void *key_value_pt, size_t key_value_len, void *priv_data_pt) { struct res_lib_confdb_key_change_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK; res.header.error = CS_OK; // handle & type res.change_type = change_type; res.parent_object_handle = parent_object_handle; res.object_handle = object_handle; //object memcpy(res.object_name.value, object_name_pt, object_name_len); res.object_name.length = object_name_len; //key name memcpy(res.key_name.value, key_name_pt, key_name_len); res.key_name.length = key_name_len; //key value memcpy(res.key_value.value, key_value_pt, key_value_len); res.key_value.length = key_value_len; ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res)); } static void confdb_notify_lib_of_new_object(hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len, void *priv_data_pt) { struct res_lib_confdb_object_create_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK; res.header.error = CS_OK; res.parent_object_handle = parent_object_handle; res.object_handle = object_handle; memcpy(res.name.value, name_pt, name_len); res.name.length = name_len; ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res)); } static void confdb_notify_lib_of_destroyed_object( hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len, void *priv_data_pt) { struct res_lib_confdb_object_destroy_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK; res.header.error = CS_OK; res.parent_object_handle = parent_object_handle; memcpy(res.name.value, name_pt, name_len); res.name.length = name_len; ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res)); } static void confdb_notify_lib_of_reload(objdb_reload_notify_type_t notify_type, int flush, void *priv_data_pt) { struct res_lib_confdb_reload_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_RELOAD_CALLBACK; res.header.error = CS_OK; res.type = notify_type; ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res)); } static void message_handler_req_lib_confdb_track_start (void *conn, const void *message) { const struct req_lib_confdb_object_track_start *req = message; struct qb_ipc_response_header res; api->object_track_start(req->object_handle, req->flags, confdb_notify_lib_of_key_change, confdb_notify_lib_of_new_object, confdb_notify_lib_of_destroyed_object, confdb_notify_lib_of_reload, conn); res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_TRACK_START; res.error = CS_OK; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_track_stop (void *conn, const void *message) { struct qb_ipc_response_header res; api->object_track_stop(confdb_notify_lib_of_key_change, confdb_notify_lib_of_new_object, confdb_notify_lib_of_destroyed_object, confdb_notify_lib_of_reload, conn); res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_TRACK_STOP; res.error = CS_OK; api->ipc_response_send(conn, &res, sizeof(res)); } diff --git a/services/cpg.c b/services/cpg.c index e7573c5b..633d4b37 100644 --- a/services/cpg.c +++ b/services/cpg.c @@ -1,2054 +1,2052 @@ /* * Copyright (c) 2006-2009 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * Author: Jan Friesse (jfriesse@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #ifdef HAVE_ALLOCA_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LOGSYS_DECLARE_SUBSYS ("CPG"); #define GROUP_HASH_SIZE 32 enum cpg_message_req_types { MESSAGE_REQ_EXEC_CPG_PROCJOIN = 0, MESSAGE_REQ_EXEC_CPG_PROCLEAVE = 1, MESSAGE_REQ_EXEC_CPG_JOINLIST = 2, MESSAGE_REQ_EXEC_CPG_MCAST = 3, MESSAGE_REQ_EXEC_CPG_DOWNLIST_OLD = 4, MESSAGE_REQ_EXEC_CPG_DOWNLIST = 5 }; struct zcb_mapped { struct list_head list; void *addr; size_t size; }; /* * state` exec deliver * match group name, pid -> if matched deliver for YES: * XXX indicates impossible state * * join leave mcast * UNJOINED XXX XXX NO * LEAVE_STARTED XXX YES(unjoined_enter) YES * JOIN_STARTED YES(join_started_enter) XXX NO * JOIN_COMPLETED XXX NO YES * * join_started_enter * set JOIN_COMPLETED * add entry to process_info list * unjoined_enter * set UNJOINED * delete entry from process_info list * * * library accept join error codes * UNJOINED YES(CS_OK) set JOIN_STARTED * LEAVE_STARTED NO(CS_ERR_BUSY) * JOIN_STARTED NO(CS_ERR_EXIST) * JOIN_COMPlETED NO(CS_ERR_EXIST) * * library accept leave error codes * UNJOINED NO(CS_ERR_NOT_EXIST) * LEAVE_STARTED NO(CS_ERR_NOT_EXIST) * JOIN_STARTED NO(CS_ERR_BUSY) * JOIN_COMPLETED YES(CS_OK) set LEAVE_STARTED * * library accept mcast * UNJOINED NO(CS_ERR_NOT_EXIST) * LEAVE_STARTED NO(CS_ERR_NOT_EXIST) * JOIN_STARTED YES(CS_OK) * JOIN_COMPLETED YES(CS_OK) */ enum cpd_state { CPD_STATE_UNJOINED, CPD_STATE_LEAVE_STARTED, CPD_STATE_JOIN_STARTED, CPD_STATE_JOIN_COMPLETED }; enum cpg_sync_state { CPGSYNC_DOWNLIST, CPGSYNC_JOINLIST }; enum cpg_downlist_state_e { CPG_DOWNLIST_NONE, CPG_DOWNLIST_WAITING_FOR_MESSAGES, CPG_DOWNLIST_APPLYING, }; static enum cpg_downlist_state_e downlist_state; static struct list_head downlist_messages_head; struct cpg_pd { void *conn; mar_cpg_name_t group_name; uint32_t pid; enum cpd_state cpd_state; unsigned int flags; int initial_totem_conf_sent; struct list_head list; struct list_head iteration_instance_list_head; struct list_head zcb_mapped_list_head; }; struct cpg_iteration_instance { hdb_handle_t handle; struct list_head list; struct list_head items_list_head; /* List of process_info */ struct list_head *current_pointer; }; DECLARE_HDB_DATABASE(cpg_iteration_handle_t_db,NULL); DECLARE_LIST_INIT(cpg_pd_list_head); static unsigned int my_member_list[PROCESSOR_COUNT_MAX]; static unsigned int my_member_list_entries; static unsigned int my_old_member_list[PROCESSOR_COUNT_MAX]; static unsigned int my_old_member_list_entries = 0; static struct corosync_api_v1 *api = NULL; static enum cpg_sync_state my_sync_state = CPGSYNC_DOWNLIST; static mar_cpg_ring_id_t last_sync_ring_id; struct process_info { unsigned int nodeid; uint32_t pid; mar_cpg_name_t group; struct list_head list; /* on the group_info members list */ }; DECLARE_LIST_INIT(process_info_list_head); struct join_list_entry { uint32_t pid; mar_cpg_name_t group_name; }; /* * Service Interfaces required by service_message_handler struct */ static int cpg_exec_init_fn (struct corosync_api_v1 *); static int cpg_lib_init_fn (void *conn); static int cpg_lib_exit_fn (void *conn); static void message_handler_req_exec_cpg_procjoin ( const void *message, unsigned int nodeid); static void message_handler_req_exec_cpg_procleave ( const void *message, unsigned int nodeid); static void message_handler_req_exec_cpg_joinlist ( const void *message, unsigned int nodeid); static void message_handler_req_exec_cpg_mcast ( const void *message, unsigned int nodeid); static void message_handler_req_exec_cpg_downlist_old ( const void *message, unsigned int nodeid); static void message_handler_req_exec_cpg_downlist ( const void *message, unsigned int nodeid); static void exec_cpg_procjoin_endian_convert (void *msg); static void exec_cpg_joinlist_endian_convert (void *msg); static void exec_cpg_mcast_endian_convert (void *msg); static void exec_cpg_downlist_endian_convert_old (void *msg); static void exec_cpg_downlist_endian_convert (void *msg); static void message_handler_req_lib_cpg_join (void *conn, const void *message); static void message_handler_req_lib_cpg_leave (void *conn, const void *message); static void message_handler_req_lib_cpg_finalize (void *conn, const void *message); static void message_handler_req_lib_cpg_mcast (void *conn, const void *message); static void message_handler_req_lib_cpg_membership (void *conn, const void *message); static void message_handler_req_lib_cpg_local_get (void *conn, const void *message); static void message_handler_req_lib_cpg_iteration_initialize ( void *conn, const void *message); static void message_handler_req_lib_cpg_iteration_next ( void *conn, const void *message); static void message_handler_req_lib_cpg_iteration_finalize ( void *conn, const void *message); static void message_handler_req_lib_cpg_zc_alloc ( void *conn, const void *message); static void message_handler_req_lib_cpg_zc_free ( void *conn, const void *message); static void message_handler_req_lib_cpg_zc_execute ( void *conn, const void *message); static int cpg_node_joinleave_send (unsigned int pid, const mar_cpg_name_t *group_name, int fn, int reason); static int cpg_exec_send_downlist(void); static int cpg_exec_send_joinlist(void); static void downlist_messages_delete (void); static void downlist_master_choose_and_send (void); static void cpg_sync_init_v2 ( const unsigned int *trans_list, size_t trans_list_entries, const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id); static int cpg_sync_process (void); static void cpg_sync_activate (void); static void cpg_sync_abort (void); static int notify_lib_totem_membership ( void *conn, int member_list_entries, const unsigned int *member_list); static inline int zcb_all_free ( struct cpg_pd *cpd); /* * Library Handler Definition */ static struct corosync_lib_handler cpg_lib_engine[] = { { /* 0 */ .lib_handler_fn = message_handler_req_lib_cpg_join, .flow_control = CS_LIB_FLOW_CONTROL_REQUIRED }, { /* 1 */ .lib_handler_fn = message_handler_req_lib_cpg_leave, .flow_control = CS_LIB_FLOW_CONTROL_REQUIRED }, { /* 2 */ .lib_handler_fn = message_handler_req_lib_cpg_mcast, .flow_control = CS_LIB_FLOW_CONTROL_REQUIRED }, { /* 3 */ .lib_handler_fn = message_handler_req_lib_cpg_membership, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 4 */ .lib_handler_fn = message_handler_req_lib_cpg_local_get, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 5 */ .lib_handler_fn = message_handler_req_lib_cpg_iteration_initialize, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 6 */ .lib_handler_fn = message_handler_req_lib_cpg_iteration_next, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 7 */ .lib_handler_fn = message_handler_req_lib_cpg_iteration_finalize, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 8 */ .lib_handler_fn = message_handler_req_lib_cpg_finalize, .flow_control = CS_LIB_FLOW_CONTROL_REQUIRED }, { /* 9 */ .lib_handler_fn = message_handler_req_lib_cpg_zc_alloc, .flow_control = CS_LIB_FLOW_CONTROL_REQUIRED }, { /* 10 */ .lib_handler_fn = message_handler_req_lib_cpg_zc_free, .flow_control = CS_LIB_FLOW_CONTROL_REQUIRED }, { /* 11 */ .lib_handler_fn = message_handler_req_lib_cpg_zc_execute, .flow_control = CS_LIB_FLOW_CONTROL_REQUIRED }, }; static struct corosync_exec_handler cpg_exec_engine[] = { { /* 0 */ .exec_handler_fn = message_handler_req_exec_cpg_procjoin, .exec_endian_convert_fn = exec_cpg_procjoin_endian_convert }, { /* 1 */ .exec_handler_fn = message_handler_req_exec_cpg_procleave, .exec_endian_convert_fn = exec_cpg_procjoin_endian_convert }, { /* 2 */ .exec_handler_fn = message_handler_req_exec_cpg_joinlist, .exec_endian_convert_fn = exec_cpg_joinlist_endian_convert }, { /* 3 */ .exec_handler_fn = message_handler_req_exec_cpg_mcast, .exec_endian_convert_fn = exec_cpg_mcast_endian_convert }, { /* 4 */ .exec_handler_fn = message_handler_req_exec_cpg_downlist_old, .exec_endian_convert_fn = exec_cpg_downlist_endian_convert_old }, { /* 5 */ .exec_handler_fn = message_handler_req_exec_cpg_downlist, .exec_endian_convert_fn = exec_cpg_downlist_endian_convert }, }; struct corosync_service_engine cpg_service_engine = { .name = "corosync cluster closed process group service v1.01", .id = CPG_SERVICE, .priority = 1, .private_data_size = sizeof (struct cpg_pd), .flow_control = CS_LIB_FLOW_CONTROL_REQUIRED, .allow_inquorate = CS_LIB_ALLOW_INQUORATE, .lib_init_fn = cpg_lib_init_fn, .lib_exit_fn = cpg_lib_exit_fn, .lib_engine = cpg_lib_engine, .lib_engine_count = sizeof (cpg_lib_engine) / sizeof (struct corosync_lib_handler), .exec_init_fn = cpg_exec_init_fn, .exec_dump_fn = NULL, .exec_engine = cpg_exec_engine, .exec_engine_count = sizeof (cpg_exec_engine) / sizeof (struct corosync_exec_handler), .sync_mode = CS_SYNC_V1_APIV2, .sync_init = (sync_init_v1_fn_t)cpg_sync_init_v2, .sync_process = cpg_sync_process, .sync_activate = cpg_sync_activate, .sync_abort = cpg_sync_abort }; /* * Dynamic loader definition */ static struct corosync_service_engine *cpg_get_service_engine_ver0 (void); static struct corosync_service_engine_iface_ver0 cpg_service_engine_iface = { .corosync_get_service_engine_ver0 = cpg_get_service_engine_ver0 }; static struct lcr_iface corosync_cpg_ver0[1] = { { .name = "corosync_cpg", .version = 0, .versions_replace = 0, .versions_replace_count = 0, .dependencies = 0, .dependency_count = 0, .constructor = NULL, .destructor = NULL, .interfaces = NULL } }; static struct lcr_comp cpg_comp_ver0 = { .iface_count = 1, .ifaces = corosync_cpg_ver0 }; static struct corosync_service_engine *cpg_get_service_engine_ver0 (void) { return (&cpg_service_engine); } #ifdef COROSYNC_SOLARIS void corosync_lcr_component_register (void); void corosync_lcr_component_register (void) { #else __attribute__ ((constructor)) static void corosync_lcr_component_register (void) { #endif lcr_interfaces_set (&corosync_cpg_ver0[0], &cpg_service_engine_iface); lcr_component_register (&cpg_comp_ver0); } struct req_exec_cpg_procjoin { struct qb_ipc_request_header header __attribute__((aligned(8))); mar_cpg_name_t group_name __attribute__((aligned(8))); mar_uint32_t pid __attribute__((aligned(8))); mar_uint32_t reason __attribute__((aligned(8))); }; struct req_exec_cpg_mcast { struct qb_ipc_request_header header __attribute__((aligned(8))); mar_cpg_name_t group_name __attribute__((aligned(8))); mar_uint32_t msglen __attribute__((aligned(8))); mar_uint32_t pid __attribute__((aligned(8))); mar_message_source_t source __attribute__((aligned(8))); mar_uint8_t message[] __attribute__((aligned(8))); }; struct req_exec_cpg_downlist_old { struct qb_ipc_request_header header __attribute__((aligned(8))); mar_uint32_t left_nodes __attribute__((aligned(8))); mar_uint32_t nodeids[PROCESSOR_COUNT_MAX] __attribute__((aligned(8))); }; struct req_exec_cpg_downlist { struct qb_ipc_request_header header __attribute__((aligned(8))); /* merge decisions */ mar_uint32_t old_members __attribute__((aligned(8))); /* downlist below */ mar_uint32_t left_nodes __attribute__((aligned(8))); mar_uint32_t nodeids[PROCESSOR_COUNT_MAX] __attribute__((aligned(8))); }; struct downlist_msg { mar_uint32_t sender_nodeid; mar_uint32_t old_members __attribute__((aligned(8))); mar_uint32_t left_nodes __attribute__((aligned(8))); mar_uint32_t nodeids[PROCESSOR_COUNT_MAX] __attribute__((aligned(8))); struct list_head list; }; static struct req_exec_cpg_downlist g_req_exec_cpg_downlist; static void cpg_sync_init_v2 ( const unsigned int *trans_list, size_t trans_list_entries, const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id) { int entries; int i, j; int found; my_sync_state = CPGSYNC_DOWNLIST; memcpy (my_member_list, member_list, member_list_entries * sizeof (unsigned int)); my_member_list_entries = member_list_entries; last_sync_ring_id.nodeid = ring_id->rep.nodeid; last_sync_ring_id.seq = ring_id->seq; downlist_state = CPG_DOWNLIST_WAITING_FOR_MESSAGES; entries = 0; /* * Determine list of nodeids for downlist message */ for (i = 0; i < my_old_member_list_entries; i++) { found = 0; for (j = 0; j < trans_list_entries; j++) { if (my_old_member_list[i] == trans_list[j]) { found = 1; break; } } if (found == 0) { g_req_exec_cpg_downlist.nodeids[entries++] = my_old_member_list[i]; } } g_req_exec_cpg_downlist.left_nodes = entries; } static int cpg_sync_process (void) { int res = -1; if (my_sync_state == CPGSYNC_DOWNLIST) { res = cpg_exec_send_downlist(); if (res == -1) { return (-1); } my_sync_state = CPGSYNC_JOINLIST; } if (my_sync_state == CPGSYNC_JOINLIST) { res = cpg_exec_send_joinlist(); } return (res); } static void cpg_sync_activate (void) { memcpy (my_old_member_list, my_member_list, my_member_list_entries * sizeof (unsigned int)); my_old_member_list_entries = my_member_list_entries; if (downlist_state == CPG_DOWNLIST_WAITING_FOR_MESSAGES) { downlist_master_choose_and_send (); } downlist_messages_delete (); downlist_state = CPG_DOWNLIST_NONE; notify_lib_totem_membership (NULL, my_member_list_entries, my_member_list); } static void cpg_sync_abort (void) { downlist_state = CPG_DOWNLIST_NONE; downlist_messages_delete (); } static int notify_lib_totem_membership ( void *conn, int member_list_entries, const unsigned int *member_list) { struct list_head *iter; char *buf; int size; struct res_lib_cpg_totem_confchg_callback *res; size = sizeof(struct res_lib_cpg_totem_confchg_callback) + sizeof(mar_uint32_t) * (member_list_entries); buf = alloca(size); if (!buf) return CS_ERR_LIBRARY; res = (struct res_lib_cpg_totem_confchg_callback *)buf; res->member_list_entries = member_list_entries; res->header.size = size; res->header.id = MESSAGE_RES_CPG_TOTEM_CONFCHG_CALLBACK; res->header.error = CS_OK; memcpy (&res->ring_id, &last_sync_ring_id, sizeof (mar_cpg_ring_id_t)); memcpy (res->member_list, member_list, res->member_list_entries * sizeof (mar_uint32_t)); if (conn == NULL) { for (iter = cpg_pd_list_head.next; iter != &cpg_pd_list_head; iter = iter->next) { struct cpg_pd *cpg_pd = list_entry (iter, struct cpg_pd, list); api->ipc_dispatch_send (cpg_pd->conn, buf, size); } } else { api->ipc_dispatch_send (conn, buf, size); } return CS_OK; } static int notify_lib_joinlist( const mar_cpg_name_t *group_name, void *conn, int joined_list_entries, mar_cpg_address_t *joined_list, int left_list_entries, mar_cpg_address_t *left_list, int id) { int size; char *buf; struct list_head *iter; int count; struct res_lib_cpg_confchg_callback *res; mar_cpg_address_t *retgi; count = 0; for (iter = process_info_list_head.next; iter != &process_info_list_head; iter = iter->next) { struct process_info *pi = list_entry (iter, struct process_info, list); if (mar_name_compare (&pi->group, group_name) == 0) { int i; int founded = 0; for (i = 0; i < left_list_entries; i++) { if (left_list[i].nodeid == pi->nodeid && left_list[i].pid == pi->pid) { founded++; } } if (!founded) count++; } } size = sizeof(struct res_lib_cpg_confchg_callback) + sizeof(mar_cpg_address_t) * (count + left_list_entries + joined_list_entries); buf = alloca(size); if (!buf) return CS_ERR_LIBRARY; res = (struct res_lib_cpg_confchg_callback *)buf; res->joined_list_entries = joined_list_entries; res->left_list_entries = left_list_entries; res->member_list_entries = count; retgi = res->member_list; res->header.size = size; res->header.id = id; res->header.error = CS_OK; memcpy(&res->group_name, group_name, sizeof(mar_cpg_name_t)); for (iter = process_info_list_head.next; iter != &process_info_list_head; iter = iter->next) { struct process_info *pi=list_entry (iter, struct process_info, list); if (mar_name_compare (&pi->group, group_name) == 0) { int i; int founded = 0; for (i = 0;i < left_list_entries; i++) { if (left_list[i].nodeid == pi->nodeid && left_list[i].pid == pi->pid) { founded++; } } if (!founded) { retgi->nodeid = pi->nodeid; retgi->pid = pi->pid; retgi++; } } } if (left_list_entries) { memcpy (retgi, left_list, left_list_entries * sizeof(mar_cpg_address_t)); retgi += left_list_entries; } if (joined_list_entries) { memcpy (retgi, joined_list, joined_list_entries * sizeof(mar_cpg_address_t)); retgi += joined_list_entries; } if (conn) { api->ipc_dispatch_send (conn, buf, size); } else { for (iter = cpg_pd_list_head.next; iter != &cpg_pd_list_head; iter = iter->next) { struct cpg_pd *cpd = list_entry (iter, struct cpg_pd, list); if (mar_name_compare (&cpd->group_name, group_name) == 0) { assert (left_list_entries <= 1); assert (joined_list_entries <= 1); if (joined_list_entries) { if (joined_list[0].pid == cpd->pid && joined_list[0].nodeid == api->totem_nodeid_get()) { cpd->cpd_state = CPD_STATE_JOIN_COMPLETED; } } if (cpd->cpd_state == CPD_STATE_JOIN_COMPLETED || cpd->cpd_state == CPD_STATE_LEAVE_STARTED) { api->ipc_dispatch_send (cpd->conn, buf, size); } if (left_list_entries) { if (left_list[0].pid == cpd->pid && left_list[0].nodeid == api->totem_nodeid_get()) { cpd->pid = 0; memset (&cpd->group_name, 0, sizeof(cpd->group_name)); cpd->cpd_state = CPD_STATE_UNJOINED; } } } } } /* * Traverse thru cpds and send totem membership for cpd, where it is not send yet */ for (iter = cpg_pd_list_head.next; iter != &cpg_pd_list_head; iter = iter->next) { struct cpg_pd *cpd = list_entry (iter, struct cpg_pd, list); if ((cpd->flags & CPG_MODEL_V1_DELIVER_INITIAL_TOTEM_CONF) && (cpd->initial_totem_conf_sent == 0)) { cpd->initial_totem_conf_sent = 1; notify_lib_totem_membership (cpd->conn, my_old_member_list_entries, my_old_member_list); } } return CS_OK; } static void downlist_log(int loglevel, const char *msg, struct downlist_msg* dl) { log_printf (loglevel, "%s: sender %s; members(old:%d left:%d)", msg, api->totem_ifaces_print(dl->sender_nodeid), dl->old_members, dl->left_nodes); } static struct downlist_msg* downlist_master_choose (void) { struct downlist_msg *cmp; struct downlist_msg *best = NULL; struct list_head *iter; uint32_t cmp_members; uint32_t best_members; for (iter = downlist_messages_head.next; iter != &downlist_messages_head; iter = iter->next) { cmp = list_entry(iter, struct downlist_msg, list); downlist_log(LOGSYS_LEVEL_DEBUG, "comparing", cmp); if (best == NULL) { best = cmp; continue; } best_members = best->old_members - best->left_nodes; cmp_members = cmp->old_members - cmp->left_nodes; if (cmp_members < best_members) { continue; } else if (cmp_members > best_members) { best = cmp; } else if (cmp->sender_nodeid < best->sender_nodeid) { best = cmp; } } return best; } static void downlist_master_choose_and_send (void) { struct downlist_msg *stored_msg; struct list_head *iter; mar_cpg_address_t left_list; int i; downlist_state = CPG_DOWNLIST_APPLYING; stored_msg = downlist_master_choose (); if (!stored_msg) { log_printf (LOGSYS_LEVEL_DEBUG, "NO chosen downlist"); return; } downlist_log(LOGSYS_LEVEL_DEBUG, "chosen downlist", stored_msg); /* send events */ for (iter = process_info_list_head.next; iter != &process_info_list_head; ) { struct process_info *pi = list_entry(iter, struct process_info, list); iter = iter->next; for (i = 0; i < stored_msg->left_nodes; i++) { if (pi->nodeid == stored_msg->nodeids[i]) { left_list.nodeid = pi->nodeid; left_list.pid = pi->pid; left_list.reason = CONFCHG_CPG_REASON_NODEDOWN; notify_lib_joinlist(&pi->group, NULL, 0, NULL, 1, &left_list, MESSAGE_RES_CPG_CONFCHG_CALLBACK); list_del (&pi->list); free (pi); break; } } } } static void downlist_messages_delete (void) { struct downlist_msg *stored_msg; struct list_head *iter, *iter_next; for (iter = downlist_messages_head.next; iter != &downlist_messages_head; iter = iter_next) { iter_next = iter->next; stored_msg = list_entry(iter, struct downlist_msg, list); list_del (&stored_msg->list); free (stored_msg); } } static int cpg_exec_init_fn (struct corosync_api_v1 *corosync_api) { #ifdef COROSYNC_SOLARIS logsys_subsys_init(); #endif list_init (&downlist_messages_head); api = corosync_api; return (0); } static void cpg_iteration_instance_finalize (struct cpg_iteration_instance *cpg_iteration_instance) { struct list_head *iter, *iter_next; struct process_info *pi; for (iter = cpg_iteration_instance->items_list_head.next; iter != &cpg_iteration_instance->items_list_head; iter = iter_next) { iter_next = iter->next; pi = list_entry (iter, struct process_info, list); list_del (&pi->list); free (pi); } list_del (&cpg_iteration_instance->list); hdb_handle_destroy (&cpg_iteration_handle_t_db, cpg_iteration_instance->handle); } static void cpg_pd_finalize (struct cpg_pd *cpd) { struct list_head *iter, *iter_next; struct cpg_iteration_instance *cpii; zcb_all_free(cpd); for (iter = cpd->iteration_instance_list_head.next; iter != &cpd->iteration_instance_list_head; iter = iter_next) { iter_next = iter->next; cpii = list_entry (iter, struct cpg_iteration_instance, list); cpg_iteration_instance_finalize (cpii); } list_del (&cpd->list); } static int cpg_lib_exit_fn (void *conn) { struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); log_printf(LOGSYS_LEVEL_DEBUG, "exit_fn for conn=%p\n", conn); if (cpd->group_name.length > 0) { cpg_node_joinleave_send (cpd->pid, &cpd->group_name, MESSAGE_REQ_EXEC_CPG_PROCLEAVE, CONFCHG_CPG_REASON_PROCDOWN); } cpg_pd_finalize (cpd); api->ipc_refcnt_dec (conn); return (0); } static int cpg_node_joinleave_send (unsigned int pid, const mar_cpg_name_t *group_name, int fn, int reason) { struct req_exec_cpg_procjoin req_exec_cpg_procjoin; struct iovec req_exec_cpg_iovec; int result; memcpy(&req_exec_cpg_procjoin.group_name, group_name, sizeof(mar_cpg_name_t)); req_exec_cpg_procjoin.pid = pid; req_exec_cpg_procjoin.reason = reason; req_exec_cpg_procjoin.header.size = sizeof(req_exec_cpg_procjoin); req_exec_cpg_procjoin.header.id = SERVICE_ID_MAKE(CPG_SERVICE, fn); req_exec_cpg_iovec.iov_base = (char *)&req_exec_cpg_procjoin; req_exec_cpg_iovec.iov_len = sizeof(req_exec_cpg_procjoin); result = api->totem_mcast (&req_exec_cpg_iovec, 1, TOTEM_AGREED); return (result); } /* Can byteswap join & leave messages */ static void exec_cpg_procjoin_endian_convert (void *msg) { struct req_exec_cpg_procjoin *req_exec_cpg_procjoin = msg; req_exec_cpg_procjoin->pid = swab32(req_exec_cpg_procjoin->pid); swab_mar_cpg_name_t (&req_exec_cpg_procjoin->group_name); req_exec_cpg_procjoin->reason = swab32(req_exec_cpg_procjoin->reason); } static void exec_cpg_joinlist_endian_convert (void *msg_v) { char *msg = msg_v; struct qb_ipc_response_header *res = (struct qb_ipc_response_header *)msg; struct join_list_entry *jle = (struct join_list_entry *)(msg + sizeof(struct qb_ipc_response_header)); swab_mar_int32_t (&res->size); while ((const char*)jle < msg + res->size) { jle->pid = swab32(jle->pid); swab_mar_cpg_name_t (&jle->group_name); jle++; } } static void exec_cpg_downlist_endian_convert_old (void *msg) { } static void exec_cpg_downlist_endian_convert (void *msg) { struct req_exec_cpg_downlist *req_exec_cpg_downlist = msg; unsigned int i; req_exec_cpg_downlist->left_nodes = swab32(req_exec_cpg_downlist->left_nodes); req_exec_cpg_downlist->old_members = swab32(req_exec_cpg_downlist->old_members); for (i = 0; i < req_exec_cpg_downlist->left_nodes; i++) { req_exec_cpg_downlist->nodeids[i] = swab32(req_exec_cpg_downlist->nodeids[i]); } } static void exec_cpg_mcast_endian_convert (void *msg) { struct req_exec_cpg_mcast *req_exec_cpg_mcast = msg; swab_coroipc_request_header_t (&req_exec_cpg_mcast->header); swab_mar_cpg_name_t (&req_exec_cpg_mcast->group_name); req_exec_cpg_mcast->pid = swab32(req_exec_cpg_mcast->pid); req_exec_cpg_mcast->msglen = swab32(req_exec_cpg_mcast->msglen); swab_mar_message_source_t (&req_exec_cpg_mcast->source); } static struct process_info *process_info_find(const mar_cpg_name_t *group_name, uint32_t pid, unsigned int nodeid) { struct list_head *iter; for (iter = process_info_list_head.next; iter != &process_info_list_head; ) { struct process_info *pi = list_entry (iter, struct process_info, list); iter = iter->next; if (pi->pid == pid && pi->nodeid == nodeid && mar_name_compare (&pi->group, group_name) == 0) { return pi; } } return NULL; } static void do_proc_join( const mar_cpg_name_t *name, uint32_t pid, unsigned int nodeid, int reason) { struct process_info *pi; struct process_info *pi_entry; mar_cpg_address_t notify_info; struct list_head *list; struct list_head *list_to_add = NULL; if (process_info_find (name, pid, nodeid) != NULL) { return ; } pi = malloc (sizeof (struct process_info)); if (!pi) { log_printf(LOGSYS_LEVEL_WARNING, "Unable to allocate process_info struct"); return; } pi->nodeid = nodeid; pi->pid = pid; memcpy(&pi->group, name, sizeof(*name)); list_init(&pi->list); /* * Insert new process in sorted order so synchronization works properly */ list_to_add = &process_info_list_head; for (list = process_info_list_head.next; list != &process_info_list_head; list = list->next) { pi_entry = list_entry(list, struct process_info, list); if (pi_entry->nodeid > pi->nodeid || (pi_entry->nodeid == pi->nodeid && pi_entry->pid > pi->pid)) { break; } list_to_add = list; } list_add (&pi->list, list_to_add); notify_info.pid = pi->pid; notify_info.nodeid = nodeid; notify_info.reason = reason; notify_lib_joinlist(&pi->group, NULL, 1, ¬ify_info, 0, NULL, MESSAGE_RES_CPG_CONFCHG_CALLBACK); } static void message_handler_req_exec_cpg_downlist_old ( const void *message, unsigned int nodeid) { log_printf (LOGSYS_LEVEL_WARNING, "downlist OLD from node %d", nodeid); } static void message_handler_req_exec_cpg_downlist( const void *message, unsigned int nodeid) { const struct req_exec_cpg_downlist *req_exec_cpg_downlist = message; int i; struct list_head *iter; struct downlist_msg *stored_msg; int found; if (downlist_state != CPG_DOWNLIST_WAITING_FOR_MESSAGES) { log_printf (LOGSYS_LEVEL_WARNING, "downlist left_list: %d received in state %d", req_exec_cpg_downlist->left_nodes, downlist_state); return; } stored_msg = malloc (sizeof (struct downlist_msg)); stored_msg->sender_nodeid = nodeid; stored_msg->old_members = req_exec_cpg_downlist->old_members; stored_msg->left_nodes = req_exec_cpg_downlist->left_nodes; memcpy (stored_msg->nodeids, req_exec_cpg_downlist->nodeids, req_exec_cpg_downlist->left_nodes * sizeof (mar_uint32_t)); list_init (&stored_msg->list); list_add (&stored_msg->list, &downlist_messages_head); for (i = 0; i < my_member_list_entries; i++) { found = 0; for (iter = downlist_messages_head.next; iter != &downlist_messages_head; iter = iter->next) { stored_msg = list_entry(iter, struct downlist_msg, list); if (my_member_list[i] == stored_msg->sender_nodeid) { found = 1; } } if (!found) { return; } } downlist_master_choose_and_send (); } static void message_handler_req_exec_cpg_procjoin ( const void *message, unsigned int nodeid) { const struct req_exec_cpg_procjoin *req_exec_cpg_procjoin = message; log_printf(LOGSYS_LEVEL_DEBUG, "got procjoin message from cluster node %d\n", nodeid); do_proc_join (&req_exec_cpg_procjoin->group_name, req_exec_cpg_procjoin->pid, nodeid, CONFCHG_CPG_REASON_JOIN); } static void message_handler_req_exec_cpg_procleave ( const void *message, unsigned int nodeid) { const struct req_exec_cpg_procjoin *req_exec_cpg_procjoin = message; struct process_info *pi; struct list_head *iter; mar_cpg_address_t notify_info; log_printf(LOGSYS_LEVEL_DEBUG, "got procleave message from cluster node %d\n", nodeid); notify_info.pid = req_exec_cpg_procjoin->pid; notify_info.nodeid = nodeid; notify_info.reason = req_exec_cpg_procjoin->reason; notify_lib_joinlist(&req_exec_cpg_procjoin->group_name, NULL, 0, NULL, 1, ¬ify_info, MESSAGE_RES_CPG_CONFCHG_CALLBACK); for (iter = process_info_list_head.next; iter != &process_info_list_head; ) { pi = list_entry(iter, struct process_info, list); iter = iter->next; if (pi->pid == req_exec_cpg_procjoin->pid && pi->nodeid == nodeid && mar_name_compare (&pi->group, &req_exec_cpg_procjoin->group_name)==0) { list_del (&pi->list); free (pi); } } } /* Got a proclist from another node */ static void message_handler_req_exec_cpg_joinlist ( const void *message_v, unsigned int nodeid) { const char *message = message_v; const struct qb_ipc_response_header *res = (const struct qb_ipc_response_header *)message; const struct join_list_entry *jle = (const struct join_list_entry *)(message + sizeof(struct qb_ipc_response_header)); log_printf(LOGSYS_LEVEL_DEBUG, "got joinlist message from node %x\n", nodeid); /* Ignore our own messages */ if (nodeid == api->totem_nodeid_get()) { return; } while ((const char*)jle < message + res->size) { do_proc_join (&jle->group_name, jle->pid, nodeid, CONFCHG_CPG_REASON_NODEUP); jle++; } } static void message_handler_req_exec_cpg_mcast ( const void *message, unsigned int nodeid) { const struct req_exec_cpg_mcast *req_exec_cpg_mcast = message; struct res_lib_cpg_deliver_callback res_lib_cpg_mcast; int msglen = req_exec_cpg_mcast->msglen; struct list_head *iter, *pi_iter; struct cpg_pd *cpd; struct iovec iovec[2]; int known_node = 0; res_lib_cpg_mcast.header.id = MESSAGE_RES_CPG_DELIVER_CALLBACK; res_lib_cpg_mcast.header.size = sizeof(res_lib_cpg_mcast) + msglen; res_lib_cpg_mcast.msglen = msglen; res_lib_cpg_mcast.pid = req_exec_cpg_mcast->pid; res_lib_cpg_mcast.nodeid = nodeid; memcpy(&res_lib_cpg_mcast.group_name, &req_exec_cpg_mcast->group_name, sizeof(mar_cpg_name_t)); iovec[0].iov_base = (void *)&res_lib_cpg_mcast; iovec[0].iov_len = sizeof (res_lib_cpg_mcast); iovec[1].iov_base = (char*)message+sizeof(*req_exec_cpg_mcast); iovec[1].iov_len = msglen; for (iter = cpg_pd_list_head.next; iter != &cpg_pd_list_head; ) { cpd = list_entry(iter, struct cpg_pd, list); iter = iter->next; if ((cpd->cpd_state == CPD_STATE_LEAVE_STARTED || cpd->cpd_state == CPD_STATE_JOIN_COMPLETED) && (mar_name_compare (&cpd->group_name, &req_exec_cpg_mcast->group_name) == 0)) { if (!known_node) { /* Try to find, if we know the node */ for (pi_iter = process_info_list_head.next; pi_iter != &process_info_list_head; pi_iter = pi_iter->next) { struct process_info *pi = list_entry (pi_iter, struct process_info, list); if (pi->nodeid == nodeid && mar_name_compare (&pi->group, &req_exec_cpg_mcast->group_name) == 0) { known_node = 1; break; } } } if (!known_node) { log_printf(LOGSYS_LEVEL_WARNING, "Unknown node -> we will not deliver message"); return ; } api->ipc_dispatch_iov_send (cpd->conn, iovec, 2); } } } static int cpg_exec_send_downlist(void) { struct iovec iov; g_req_exec_cpg_downlist.header.id = SERVICE_ID_MAKE(CPG_SERVICE, MESSAGE_REQ_EXEC_CPG_DOWNLIST); g_req_exec_cpg_downlist.header.size = sizeof(struct req_exec_cpg_downlist); g_req_exec_cpg_downlist.old_members = my_old_member_list_entries; iov.iov_base = (void *)&g_req_exec_cpg_downlist; iov.iov_len = g_req_exec_cpg_downlist.header.size; return (api->totem_mcast (&iov, 1, TOTEM_AGREED)); } static int cpg_exec_send_joinlist(void) { int count = 0; struct list_head *iter; struct qb_ipc_response_header *res; char *buf; struct join_list_entry *jle; struct iovec req_exec_cpg_iovec; for (iter = process_info_list_head.next; iter != &process_info_list_head; iter = iter->next) { struct process_info *pi = list_entry (iter, struct process_info, list); if (pi->nodeid == api->totem_nodeid_get ()) { count++; } } /* Nothing to send */ if (!count) return 0; buf = alloca(sizeof(struct qb_ipc_response_header) + sizeof(struct join_list_entry) * count); if (!buf) { log_printf(LOGSYS_LEVEL_WARNING, "Unable to allocate joinlist buffer"); return -1; } jle = (struct join_list_entry *)(buf + sizeof(struct qb_ipc_response_header)); res = (struct qb_ipc_response_header *)buf; for (iter = process_info_list_head.next; iter != &process_info_list_head; iter = iter->next) { struct process_info *pi = list_entry (iter, struct process_info, list); if (pi->nodeid == api->totem_nodeid_get ()) { memcpy (&jle->group_name, &pi->group, sizeof (mar_cpg_name_t)); jle->pid = pi->pid; jle++; } } res->id = SERVICE_ID_MAKE(CPG_SERVICE, MESSAGE_REQ_EXEC_CPG_JOINLIST); res->size = sizeof(struct qb_ipc_response_header)+sizeof(struct join_list_entry) * count; req_exec_cpg_iovec.iov_base = buf; req_exec_cpg_iovec.iov_len = res->size; return (api->totem_mcast (&req_exec_cpg_iovec, 1, TOTEM_AGREED)); } static int cpg_lib_init_fn (void *conn) { struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); memset (cpd, 0, sizeof(struct cpg_pd)); cpd->conn = conn; list_add (&cpd->list, &cpg_pd_list_head); list_init (&cpd->iteration_instance_list_head); list_init (&cpd->zcb_mapped_list_head); api->ipc_refcnt_inc (conn); log_printf(LOGSYS_LEVEL_DEBUG, "lib_init_fn: conn=%p, cpd=%p\n", conn, cpd); return (0); } /* Join message from the library */ static void message_handler_req_lib_cpg_join (void *conn, const void *message) { const struct req_lib_cpg_join *req_lib_cpg_join = message; struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); struct res_lib_cpg_join res_lib_cpg_join; cs_error_t error = CS_OK; struct list_head *iter; /* Test, if we don't have same pid and group name joined */ for (iter = cpg_pd_list_head.next; iter != &cpg_pd_list_head; iter = iter->next) { struct cpg_pd *cpd_item = list_entry (iter, struct cpg_pd, list); if (cpd_item->pid == req_lib_cpg_join->pid && mar_name_compare(&req_lib_cpg_join->group_name, &cpd_item->group_name) == 0) { /* We have same pid and group name joined -> return error */ error = CS_ERR_EXIST; goto response_send; } } /* * Same check must be done in process info list, because there may be not yet delivered * leave of client. */ for (iter = process_info_list_head.next; iter != &process_info_list_head; iter = iter->next) { struct process_info *pi = list_entry (iter, struct process_info, list); if (pi->nodeid == api->totem_nodeid_get () && pi->pid == req_lib_cpg_join->pid && mar_name_compare(&req_lib_cpg_join->group_name, &pi->group) == 0) { /* We have same pid and group name joined -> return error */ error = CS_ERR_TRY_AGAIN; goto response_send; } } switch (cpd->cpd_state) { case CPD_STATE_UNJOINED: error = CS_OK; cpd->cpd_state = CPD_STATE_JOIN_STARTED; cpd->pid = req_lib_cpg_join->pid; cpd->flags = req_lib_cpg_join->flags; memcpy (&cpd->group_name, &req_lib_cpg_join->group_name, sizeof (cpd->group_name)); cpg_node_joinleave_send (req_lib_cpg_join->pid, &req_lib_cpg_join->group_name, MESSAGE_REQ_EXEC_CPG_PROCJOIN, CONFCHG_CPG_REASON_JOIN); break; case CPD_STATE_LEAVE_STARTED: error = CS_ERR_BUSY; break; case CPD_STATE_JOIN_STARTED: error = CS_ERR_EXIST; break; case CPD_STATE_JOIN_COMPLETED: error = CS_ERR_EXIST; break; } response_send: res_lib_cpg_join.header.size = sizeof(res_lib_cpg_join); res_lib_cpg_join.header.id = MESSAGE_RES_CPG_JOIN; res_lib_cpg_join.header.error = error; api->ipc_response_send (conn, &res_lib_cpg_join, sizeof(res_lib_cpg_join)); } /* Leave message from the library */ static void message_handler_req_lib_cpg_leave (void *conn, const void *message) { struct res_lib_cpg_leave res_lib_cpg_leave; cs_error_t error = CS_OK; struct req_lib_cpg_leave *req_lib_cpg_leave = (struct req_lib_cpg_leave *)message; struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); log_printf(LOGSYS_LEVEL_DEBUG, "got leave request on %p\n", conn); switch (cpd->cpd_state) { case CPD_STATE_UNJOINED: error = CS_ERR_NOT_EXIST; break; case CPD_STATE_LEAVE_STARTED: error = CS_ERR_NOT_EXIST; break; case CPD_STATE_JOIN_STARTED: error = CS_ERR_BUSY; break; case CPD_STATE_JOIN_COMPLETED: error = CS_OK; cpd->cpd_state = CPD_STATE_LEAVE_STARTED; cpg_node_joinleave_send (req_lib_cpg_leave->pid, &req_lib_cpg_leave->group_name, MESSAGE_REQ_EXEC_CPG_PROCLEAVE, CONFCHG_CPG_REASON_LEAVE); break; } /* send return */ res_lib_cpg_leave.header.size = sizeof(res_lib_cpg_leave); res_lib_cpg_leave.header.id = MESSAGE_RES_CPG_LEAVE; res_lib_cpg_leave.header.error = error; api->ipc_response_send(conn, &res_lib_cpg_leave, sizeof(res_lib_cpg_leave)); } /* Finalize message from library */ static void message_handler_req_lib_cpg_finalize ( void *conn, const void *message) { struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); struct res_lib_cpg_finalize res_lib_cpg_finalize; cs_error_t error = CS_OK; log_printf (LOGSYS_LEVEL_DEBUG, "cpg finalize for conn=%p\n", conn); /* * We will just remove cpd from list. After this call, connection will be * closed on lib side, and cpg_lib_exit_fn will be called */ list_del (&cpd->list); list_init (&cpd->list); res_lib_cpg_finalize.header.size = sizeof (res_lib_cpg_finalize); res_lib_cpg_finalize.header.id = MESSAGE_RES_CPG_FINALIZE; res_lib_cpg_finalize.header.error = error; api->ipc_response_send (conn, &res_lib_cpg_finalize, sizeof (res_lib_cpg_finalize)); } static int memory_map ( const char *path, size_t bytes, void **buf) { int32_t fd; void *addr_orig; void *addr; int32_t res; fd = open (path, O_RDWR, 0600); unlink (path); if (fd == -1) { return (-1); } res = ftruncate (fd, bytes); if (res == -1) { goto error_close_unlink; } addr_orig = mmap (NULL, bytes, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (addr_orig == MAP_FAILED) { goto error_close_unlink; } addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, 0); if (addr != addr_orig) { munmap(addr_orig, bytes); goto error_close_unlink; } #ifdef COROSYNC_BSD madvise(addr, bytes, MADV_NOSYNC); #endif res = close (fd); if (res) { return (-1); } *buf = addr_orig; return (0); error_close_unlink: close (fd); unlink(path); return -1; } static inline int zcb_alloc ( struct cpg_pd *cpd, const char *path_to_file, size_t size, void **addr) { struct zcb_mapped *zcb_mapped; unsigned int res; zcb_mapped = malloc (sizeof (struct zcb_mapped)); if (zcb_mapped == NULL) { return (-1); } res = memory_map ( path_to_file, size, addr); if (res == -1) { free (zcb_mapped); return (-1); } list_init (&zcb_mapped->list); zcb_mapped->addr = *addr; zcb_mapped->size = size; list_add_tail (&zcb_mapped->list, &cpd->zcb_mapped_list_head); return (0); } static inline int zcb_free (struct zcb_mapped *zcb_mapped) { unsigned int res; res = munmap (zcb_mapped->addr, zcb_mapped->size); list_del (&zcb_mapped->list); free (zcb_mapped); return (res); } static inline int zcb_by_addr_free (struct cpg_pd *cpd, void *addr) { struct list_head *list; struct zcb_mapped *zcb_mapped; unsigned int res = 0; for (list = cpd->zcb_mapped_list_head.next; list != &cpd->zcb_mapped_list_head; list = list->next) { zcb_mapped = list_entry (list, struct zcb_mapped, list); if (zcb_mapped->addr == addr) { res = zcb_free (zcb_mapped); break; } } return (res); } static inline int zcb_all_free ( struct cpg_pd *cpd) { struct list_head *list; struct zcb_mapped *zcb_mapped; for (list = cpd->zcb_mapped_list_head.next; list != &cpd->zcb_mapped_list_head;) { zcb_mapped = list_entry (list, struct zcb_mapped, list); list = list->next; zcb_free (zcb_mapped); } return (0); } union u { uint64_t server_addr; void *server_ptr; }; static uint64_t void2serveraddr (void *server_ptr) { union u u; u.server_ptr = server_ptr; return (u.server_addr); } static void *serveraddr2void (uint64_t server_addr) { union u u; u.server_addr = server_addr; return (u.server_ptr); }; static void message_handler_req_lib_cpg_zc_alloc ( void *conn, const void *message) { mar_req_coroipcc_zc_alloc_t *hdr = (mar_req_coroipcc_zc_alloc_t *)message; struct qb_ipc_response_header res_header; void *addr = NULL; struct coroipcs_zc_header *zc_header; unsigned int res; struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); log_printf(LOGSYS_LEVEL_DEBUG, "path: %s", hdr->path_to_file); res = zcb_alloc (cpd, hdr->path_to_file, hdr->map_size, &addr); assert(res == 0); zc_header = (struct coroipcs_zc_header *)addr; zc_header->server_address = void2serveraddr(addr); res_header.size = sizeof (struct qb_ipc_response_header); res_header.id = 0; api->ipc_response_send (conn, &res_header, res_header.size); } static void message_handler_req_lib_cpg_zc_free ( void *conn, const void *message) { mar_req_coroipcc_zc_free_t *hdr = (mar_req_coroipcc_zc_free_t *)message; struct qb_ipc_response_header res_header; void *addr = NULL; struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); log_printf(LOGSYS_LEVEL_DEBUG, " free'ing"); addr = serveraddr2void (hdr->server_address); zcb_by_addr_free (cpd, addr); res_header.size = sizeof (struct qb_ipc_response_header); res_header.id = 0; api->ipc_response_send ( conn, &res_header, res_header.size); } /* Mcast message from the library */ static void message_handler_req_lib_cpg_mcast (void *conn, const void *message) { const struct req_lib_cpg_mcast *req_lib_cpg_mcast = message; struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); mar_cpg_name_t group_name = cpd->group_name; struct iovec req_exec_cpg_iovec[2]; struct req_exec_cpg_mcast req_exec_cpg_mcast; int msglen = req_lib_cpg_mcast->msglen; int result; cs_error_t error = CS_ERR_NOT_EXIST; log_printf(LOGSYS_LEVEL_DEBUG, "got mcast request on %p\n", conn); switch (cpd->cpd_state) { case CPD_STATE_UNJOINED: error = CS_ERR_NOT_EXIST; break; case CPD_STATE_LEAVE_STARTED: error = CS_ERR_NOT_EXIST; break; case CPD_STATE_JOIN_STARTED: error = CS_OK; break; case CPD_STATE_JOIN_COMPLETED: error = CS_OK; break; } if (error == CS_OK) { req_exec_cpg_mcast.header.size = sizeof(req_exec_cpg_mcast) + msglen; req_exec_cpg_mcast.header.id = SERVICE_ID_MAKE(CPG_SERVICE, MESSAGE_REQ_EXEC_CPG_MCAST); req_exec_cpg_mcast.pid = cpd->pid; req_exec_cpg_mcast.msglen = msglen; api->ipc_source_set (&req_exec_cpg_mcast.source, conn); memcpy(&req_exec_cpg_mcast.group_name, &group_name, sizeof(mar_cpg_name_t)); req_exec_cpg_iovec[0].iov_base = (char *)&req_exec_cpg_mcast; req_exec_cpg_iovec[0].iov_len = sizeof(req_exec_cpg_mcast); req_exec_cpg_iovec[1].iov_base = (char *)&req_lib_cpg_mcast->message; req_exec_cpg_iovec[1].iov_len = msglen; result = api->totem_mcast (req_exec_cpg_iovec, 2, TOTEM_AGREED); assert(result == 0); } else { log_printf(LOGSYS_LEVEL_ERROR, "*** %p can't mcast to group %s state:%d, error:%d\n", conn, group_name.value, cpd->cpd_state, error); } } static void message_handler_req_lib_cpg_zc_execute ( void *conn, const void *message) { mar_req_coroipcc_zc_execute_t *hdr = (mar_req_coroipcc_zc_execute_t *)message; struct qb_ipc_request_header *header; struct res_lib_cpg_mcast res_lib_cpg_mcast; struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); struct iovec req_exec_cpg_iovec[2]; struct req_exec_cpg_mcast req_exec_cpg_mcast; struct req_lib_cpg_mcast *req_lib_cpg_mcast; int result; cs_error_t error = CS_ERR_NOT_EXIST; - struct coroipcs_zc_header *zc_hdr; log_printf(LOGSYS_LEVEL_DEBUG, "got ZC mcast request on %p\n", conn); - zc_hdr = (struct coroipcs_zc_header *)((char *)serveraddr2void(hdr->server_address)); header = (struct qb_ipc_request_header *)(((char *)serveraddr2void(hdr->server_address) + sizeof (struct coroipcs_zc_header))); req_lib_cpg_mcast = (struct req_lib_cpg_mcast *)header; switch (cpd->cpd_state) { case CPD_STATE_UNJOINED: error = CS_ERR_NOT_EXIST; break; case CPD_STATE_LEAVE_STARTED: error = CS_ERR_NOT_EXIST; break; case CPD_STATE_JOIN_STARTED: error = CS_OK; break; case CPD_STATE_JOIN_COMPLETED: error = CS_OK; break; } res_lib_cpg_mcast.header.size = sizeof(res_lib_cpg_mcast); res_lib_cpg_mcast.header.id = MESSAGE_RES_CPG_MCAST; if (error == CS_OK) { req_exec_cpg_mcast.header.size = sizeof(req_exec_cpg_mcast) + req_lib_cpg_mcast->msglen; req_exec_cpg_mcast.header.id = SERVICE_ID_MAKE(CPG_SERVICE, MESSAGE_REQ_EXEC_CPG_MCAST); req_exec_cpg_mcast.pid = cpd->pid; req_exec_cpg_mcast.msglen = req_lib_cpg_mcast->msglen; api->ipc_source_set (&req_exec_cpg_mcast.source, conn); memcpy(&req_exec_cpg_mcast.group_name, &cpd->group_name, sizeof(mar_cpg_name_t)); req_exec_cpg_iovec[0].iov_base = (char *)&req_exec_cpg_mcast; req_exec_cpg_iovec[0].iov_len = sizeof(req_exec_cpg_mcast); req_exec_cpg_iovec[1].iov_base = (char *)header + sizeof(struct req_lib_cpg_mcast); req_exec_cpg_iovec[1].iov_len = req_exec_cpg_mcast.msglen; result = api->totem_mcast (req_exec_cpg_iovec, 2, TOTEM_AGREED); if (result == 0) { res_lib_cpg_mcast.header.error = CS_OK; } else { res_lib_cpg_mcast.header.error = CS_ERR_TRY_AGAIN; } } else { res_lib_cpg_mcast.header.error = error; } api->ipc_response_send (conn, &res_lib_cpg_mcast, sizeof (res_lib_cpg_mcast)); } static void message_handler_req_lib_cpg_membership (void *conn, const void *message) { struct req_lib_cpg_membership_get *req_lib_cpg_membership_get = (struct req_lib_cpg_membership_get *)message; struct res_lib_cpg_membership_get res_lib_cpg_membership_get; struct list_head *iter; int member_count = 0; res_lib_cpg_membership_get.header.id = MESSAGE_RES_CPG_MEMBERSHIP; res_lib_cpg_membership_get.header.error = CS_OK; res_lib_cpg_membership_get.header.size = sizeof (struct req_lib_cpg_membership_get); for (iter = process_info_list_head.next; iter != &process_info_list_head; iter = iter->next) { struct process_info *pi = list_entry (iter, struct process_info, list); if (mar_name_compare (&pi->group, &req_lib_cpg_membership_get->group_name) == 0) { res_lib_cpg_membership_get.member_list[member_count].nodeid = pi->nodeid; res_lib_cpg_membership_get.member_list[member_count].pid = pi->pid; member_count += 1; } } res_lib_cpg_membership_get.member_count = member_count; api->ipc_response_send (conn, &res_lib_cpg_membership_get, sizeof (res_lib_cpg_membership_get)); } static void message_handler_req_lib_cpg_local_get (void *conn, const void *message) { struct res_lib_cpg_local_get res_lib_cpg_local_get; res_lib_cpg_local_get.header.size = sizeof (res_lib_cpg_local_get); res_lib_cpg_local_get.header.id = MESSAGE_RES_CPG_LOCAL_GET; res_lib_cpg_local_get.header.error = CS_OK; res_lib_cpg_local_get.local_nodeid = api->totem_nodeid_get (); api->ipc_response_send (conn, &res_lib_cpg_local_get, sizeof (res_lib_cpg_local_get)); } static void message_handler_req_lib_cpg_iteration_initialize ( void *conn, const void *message) { const struct req_lib_cpg_iterationinitialize *req_lib_cpg_iterationinitialize = message; struct cpg_pd *cpd = (struct cpg_pd *)api->ipc_private_data_get (conn); hdb_handle_t cpg_iteration_handle = 0; struct res_lib_cpg_iterationinitialize res_lib_cpg_iterationinitialize; struct list_head *iter, *iter2; struct cpg_iteration_instance *cpg_iteration_instance; cs_error_t error = CS_OK; int res; log_printf (LOGSYS_LEVEL_DEBUG, "cpg iteration initialize\n"); /* Because between calling this function and *next can be some operations which will * change list, we must do full copy. */ /* * Create new iteration instance */ res = hdb_handle_create (&cpg_iteration_handle_t_db, sizeof (struct cpg_iteration_instance), &cpg_iteration_handle); if (res != 0) { error = CS_ERR_NO_MEMORY; goto response_send; } res = hdb_handle_get (&cpg_iteration_handle_t_db, cpg_iteration_handle, (void *)&cpg_iteration_instance); if (res != 0) { error = CS_ERR_BAD_HANDLE; goto error_destroy; } list_init (&cpg_iteration_instance->items_list_head); cpg_iteration_instance->handle = cpg_iteration_handle; /* * Create copy of process_info list "grouped by" group name */ for (iter = process_info_list_head.next; iter != &process_info_list_head; iter = iter->next) { struct process_info *pi = list_entry (iter, struct process_info, list); struct process_info *new_pi; if (req_lib_cpg_iterationinitialize->iteration_type == CPG_ITERATION_NAME_ONLY) { /* * Try to find processed group name in our list new list */ int found = 0; for (iter2 = cpg_iteration_instance->items_list_head.next; iter2 != &cpg_iteration_instance->items_list_head; iter2 = iter2->next) { struct process_info *pi2 = list_entry (iter2, struct process_info, list); if (mar_name_compare (&pi2->group, &pi->group) == 0) { found = 1; break; } } if (found) { /* * We have this name in list -> don't add */ continue ; } } else if (req_lib_cpg_iterationinitialize->iteration_type == CPG_ITERATION_ONE_GROUP) { /* * Test pi group name with request */ if (mar_name_compare (&pi->group, &req_lib_cpg_iterationinitialize->group_name) != 0) /* * Not same -> don't add */ continue ; } new_pi = malloc (sizeof (struct process_info)); if (!new_pi) { log_printf(LOGSYS_LEVEL_WARNING, "Unable to allocate process_info struct"); error = CS_ERR_NO_MEMORY; goto error_put_destroy; } memcpy (new_pi, pi, sizeof (struct process_info)); list_init (&new_pi->list); if (req_lib_cpg_iterationinitialize->iteration_type == CPG_ITERATION_NAME_ONLY) { /* * pid and nodeid -> undefined */ new_pi->pid = new_pi->nodeid = 0; } /* * We will return list "grouped" by "group name", so try to find right place to add */ for (iter2 = cpg_iteration_instance->items_list_head.next; iter2 != &cpg_iteration_instance->items_list_head; iter2 = iter2->next) { struct process_info *pi2 = list_entry (iter2, struct process_info, list); if (mar_name_compare (&pi2->group, &pi->group) == 0) { break; } } list_add (&new_pi->list, iter2); } /* * Now we have a full "grouped by" copy of process_info list */ /* * Add instance to current cpd list */ list_init (&cpg_iteration_instance->list); list_add (&cpg_iteration_instance->list, &cpd->iteration_instance_list_head); cpg_iteration_instance->current_pointer = &cpg_iteration_instance->items_list_head; error_put_destroy: hdb_handle_put (&cpg_iteration_handle_t_db, cpg_iteration_handle); error_destroy: if (error != CS_OK) { hdb_handle_destroy (&cpg_iteration_handle_t_db, cpg_iteration_handle); } response_send: res_lib_cpg_iterationinitialize.header.size = sizeof (res_lib_cpg_iterationinitialize); res_lib_cpg_iterationinitialize.header.id = MESSAGE_RES_CPG_ITERATIONINITIALIZE; res_lib_cpg_iterationinitialize.header.error = error; res_lib_cpg_iterationinitialize.iteration_handle = cpg_iteration_handle; api->ipc_response_send (conn, &res_lib_cpg_iterationinitialize, sizeof (res_lib_cpg_iterationinitialize)); } static void message_handler_req_lib_cpg_iteration_next ( void *conn, const void *message) { const struct req_lib_cpg_iterationnext *req_lib_cpg_iterationnext = message; struct res_lib_cpg_iterationnext res_lib_cpg_iterationnext; struct cpg_iteration_instance *cpg_iteration_instance; cs_error_t error = CS_OK; int res; struct process_info *pi; log_printf (LOGSYS_LEVEL_DEBUG, "cpg iteration next\n"); res = hdb_handle_get (&cpg_iteration_handle_t_db, req_lib_cpg_iterationnext->iteration_handle, (void *)&cpg_iteration_instance); if (res != 0) { error = CS_ERR_LIBRARY; goto error_exit; } assert (cpg_iteration_instance); cpg_iteration_instance->current_pointer = cpg_iteration_instance->current_pointer->next; if (cpg_iteration_instance->current_pointer == &cpg_iteration_instance->items_list_head) { error = CS_ERR_NO_SECTIONS; goto error_put; } pi = list_entry (cpg_iteration_instance->current_pointer, struct process_info, list); /* * Copy iteration data */ res_lib_cpg_iterationnext.description.nodeid = pi->nodeid; res_lib_cpg_iterationnext.description.pid = pi->pid; memcpy (&res_lib_cpg_iterationnext.description.group, &pi->group, sizeof (mar_cpg_name_t)); error_put: hdb_handle_put (&cpg_iteration_handle_t_db, req_lib_cpg_iterationnext->iteration_handle); error_exit: res_lib_cpg_iterationnext.header.size = sizeof (res_lib_cpg_iterationnext); res_lib_cpg_iterationnext.header.id = MESSAGE_RES_CPG_ITERATIONNEXT; res_lib_cpg_iterationnext.header.error = error; api->ipc_response_send (conn, &res_lib_cpg_iterationnext, sizeof (res_lib_cpg_iterationnext)); } static void message_handler_req_lib_cpg_iteration_finalize ( void *conn, const void *message) { const struct req_lib_cpg_iterationfinalize *req_lib_cpg_iterationfinalize = message; struct res_lib_cpg_iterationfinalize res_lib_cpg_iterationfinalize; struct cpg_iteration_instance *cpg_iteration_instance; cs_error_t error = CS_OK; int res; log_printf (LOGSYS_LEVEL_DEBUG, "cpg iteration finalize\n"); res = hdb_handle_get (&cpg_iteration_handle_t_db, req_lib_cpg_iterationfinalize->iteration_handle, (void *)&cpg_iteration_instance); if (res != 0) { error = CS_ERR_LIBRARY; goto error_exit; } assert (cpg_iteration_instance); cpg_iteration_instance_finalize (cpg_iteration_instance); hdb_handle_put (&cpg_iteration_handle_t_db, cpg_iteration_instance->handle); error_exit: res_lib_cpg_iterationfinalize.header.size = sizeof (res_lib_cpg_iterationfinalize); res_lib_cpg_iterationfinalize.header.id = MESSAGE_RES_CPG_ITERATIONFINALIZE; res_lib_cpg_iterationfinalize.header.error = error; api->ipc_response_send (conn, &res_lib_cpg_iterationfinalize, sizeof (res_lib_cpg_iterationfinalize)); }