diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 81 | ||||
-rw-r--r-- | test/Makefile.in | 869 | ||||
-rw-r--r-- | test/cpgbench.c | 197 | ||||
-rw-r--r-- | test/cpgbenchzc.c | 193 | ||||
-rw-r--r-- | test/cpgbound.c | 130 | ||||
-rw-r--r-- | test/cpghum.c | 884 | ||||
-rw-r--r-- | test/cpgverify.c | 183 | ||||
-rw-r--r-- | test/ploadstart.sh | 60 | ||||
-rw-r--r-- | test/stress_cpgcontext.c | 134 | ||||
-rw-r--r-- | test/stress_cpgfdget.c | 117 | ||||
-rw-r--r-- | test/stress_cpgzc.c | 141 | ||||
-rw-r--r-- | test/testcfg.c | 159 | ||||
-rw-r--r-- | test/testcpg.c | 438 | ||||
-rw-r--r-- | test/testcpg2.c | 92 | ||||
-rw-r--r-- | test/testcpgzc.c | 248 | ||||
-rw-r--r-- | test/testquorum.c | 64 | ||||
-rw-r--r-- | test/testquorummodel.c | 102 | ||||
-rw-r--r-- | test/testsam.c | 1476 | ||||
-rw-r--r-- | test/testvotequorum1.c | 200 | ||||
-rw-r--r-- | test/testvotequorum2.c | 236 | ||||
-rw-r--r-- | test/testzcgc.c | 175 |
21 files changed, 6179 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..c8a7462 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,81 @@ +# +# Copyright (c) 2009-2020 Red Hat, Inc. +# +# Authors: Andrew Beekhof +# 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. + +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = ploadstart.sh + +noinst_PROGRAMS = testcpg testcpg2 cpgbench \ + testquorum testvotequorum1 testvotequorum2 \ + stress_cpgfdget stress_cpgcontext cpgbound testsam \ + testcpgzc cpgbenchzc testzcgc stress_cpgzc \ + testquorummodel testcfg + +noinst_SCRIPTS = ploadstart + +testcpg_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +testcpg2_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +testcpgzc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +testzcgc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +stress_cpgzc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +stress_cpgfdget_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +stress_cpgcontext_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +testquorum_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libquorum.la +testquorummodel_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libquorum.la +testvotequorum1_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libvotequorum.la +testvotequorum2_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libvotequorum.la +cpgbound_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +cpgbench_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +cpgbenchzc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la \ + $(top_builddir)/common_lib/libcorosync_common.la +testsam_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libsam.la \ + $(top_builddir)/lib/libcmap.la +testcfg_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcfg.la + +if HAVE_CRC32 +noinst_PROGRAMS += cpghum cpgverify +cpghum_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la -lz +cpgverify_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la -lz +endif + +ploadstart: ploadstart.sh + $(SED) -e 's#@''BASHPATH@#${BASHPATH}#g' $< > $@ + chmod 755 $@ + +LINT_FILES1:=$(filter-out sa_error.c, $(wildcard *.c)) +LINT_FILES:=$(filter-out testparse.c, $(LINT_FILES1)) + +lint: + -for f in $(LINT_FILES) ; do echo Splint $$f ; splint $(LINT_FLAGS) $(CPPFLAGS) $(CFLAGS) $$f ; done + +clean-local: + rm -f ploadstart diff --git a/test/Makefile.in b/test/Makefile.in new file mode 100644 index 0000000..c8b29d2 --- /dev/null +++ b/test/Makefile.in @@ -0,0 +1,869 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Copyright (c) 2009-2020 Red Hat, Inc. +# +# Authors: Andrew Beekhof +# 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. + + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = testcpg$(EXEEXT) testcpg2$(EXEEXT) cpgbench$(EXEEXT) \ + testquorum$(EXEEXT) testvotequorum1$(EXEEXT) \ + testvotequorum2$(EXEEXT) stress_cpgfdget$(EXEEXT) \ + stress_cpgcontext$(EXEEXT) cpgbound$(EXEEXT) testsam$(EXEEXT) \ + testcpgzc$(EXEEXT) cpgbenchzc$(EXEEXT) testzcgc$(EXEEXT) \ + stress_cpgzc$(EXEEXT) testquorummodel$(EXEEXT) \ + testcfg$(EXEEXT) $(am__EXEEXT_1) +@HAVE_CRC32_TRUE@am__append_1 = cpghum cpgverify +subdir = test +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/lib/libcfg.verso $(top_srcdir)/lib/libcpg.verso \ + $(top_srcdir)/lib/libquorum.verso \ + $(top_srcdir)/lib/libsam.verso \ + $(top_srcdir)/lib/libvotequorum.verso \ + $(top_srcdir)/lib/libcmap.verso $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/corosync/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_CRC32_TRUE@am__EXEEXT_1 = cpghum$(EXEEXT) cpgverify$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +cpgbench_SOURCES = cpgbench.c +cpgbench_OBJECTS = cpgbench.$(OBJEXT) +am__DEPENDENCIES_1 = +cpgbench_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +cpgbenchzc_SOURCES = cpgbenchzc.c +cpgbenchzc_OBJECTS = cpgbenchzc.$(OBJEXT) +cpgbenchzc_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la \ + $(top_builddir)/common_lib/libcorosync_common.la +cpgbound_SOURCES = cpgbound.c +cpgbound_OBJECTS = cpgbound.$(OBJEXT) +cpgbound_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +cpghum_SOURCES = cpghum.c +cpghum_OBJECTS = cpghum.$(OBJEXT) +@HAVE_CRC32_TRUE@cpghum_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +@HAVE_CRC32_TRUE@ $(top_builddir)/lib/libcpg.la +cpgverify_SOURCES = cpgverify.c +cpgverify_OBJECTS = cpgverify.$(OBJEXT) +@HAVE_CRC32_TRUE@cpgverify_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +@HAVE_CRC32_TRUE@ $(top_builddir)/lib/libcpg.la +stress_cpgcontext_SOURCES = stress_cpgcontext.c +stress_cpgcontext_OBJECTS = stress_cpgcontext.$(OBJEXT) +stress_cpgcontext_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +stress_cpgfdget_SOURCES = stress_cpgfdget.c +stress_cpgfdget_OBJECTS = stress_cpgfdget.$(OBJEXT) +stress_cpgfdget_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +stress_cpgzc_SOURCES = stress_cpgzc.c +stress_cpgzc_OBJECTS = stress_cpgzc.$(OBJEXT) +stress_cpgzc_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +testcfg_SOURCES = testcfg.c +testcfg_OBJECTS = testcfg.$(OBJEXT) +testcfg_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcfg.la +testcpg_SOURCES = testcpg.c +testcpg_OBJECTS = testcpg.$(OBJEXT) +testcpg_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +testcpg2_SOURCES = testcpg2.c +testcpg2_OBJECTS = testcpg2.$(OBJEXT) +testcpg2_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +testcpgzc_SOURCES = testcpgzc.c +testcpgzc_OBJECTS = testcpgzc.$(OBJEXT) +testcpgzc_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +testquorum_SOURCES = testquorum.c +testquorum_OBJECTS = testquorum.$(OBJEXT) +testquorum_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libquorum.la +testquorummodel_SOURCES = testquorummodel.c +testquorummodel_OBJECTS = testquorummodel.$(OBJEXT) +testquorummodel_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libquorum.la +testsam_SOURCES = testsam.c +testsam_OBJECTS = testsam.$(OBJEXT) +testsam_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libsam.la $(top_builddir)/lib/libcmap.la +testvotequorum1_SOURCES = testvotequorum1.c +testvotequorum1_OBJECTS = testvotequorum1.$(OBJEXT) +testvotequorum1_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libvotequorum.la +testvotequorum2_SOURCES = testvotequorum2.c +testvotequorum2_OBJECTS = testvotequorum2.$(OBJEXT) +testvotequorum2_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libvotequorum.la +testzcgc_SOURCES = testzcgc.c +testzcgc_OBJECTS = testzcgc.$(OBJEXT) +testzcgc_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/libcpg.la +SCRIPTS = $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/corosync +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = cpgbench.c cpgbenchzc.c cpgbound.c cpghum.c cpgverify.c \ + stress_cpgcontext.c stress_cpgfdget.c stress_cpgzc.c testcfg.c \ + testcpg.c testcpg2.c testcpgzc.c testquorum.c \ + testquorummodel.c testsam.c testvotequorum1.c \ + testvotequorum2.c testzcgc.c +DIST_SOURCES = cpgbench.c cpgbenchzc.c cpgbound.c cpghum.c cpgverify.c \ + stress_cpgcontext.c stress_cpgfdget.c stress_cpgzc.c testcfg.c \ + testcpg.c testcpg2.c testcpgzc.c testquorum.c \ + testquorummodel.c testsam.c testvotequorum1.c \ + testvotequorum2.c testzcgc.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUGTOOL = @AUGTOOL@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASHPATH = @BASHPATH@ +BINDGEN = @BINDGEN@ +CARGO = @CARGO@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFG_SONAME = @CFG_SONAME@ +CFLAGS = @CFLAGS@ +CLIPPY = @CLIPPY@ +CMAP_SONAME = @CMAP_SONAME@ +COROSYSCONFDIR = @COROSYSCONFDIR@ +CPG_SONAME = @CPG_SONAME@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOT = @DOT@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GROFF = @GROFF@ +INITCONFIGDIR = @INITCONFIGDIR@ +INITDDIR = @INITDDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBQB_CFLAGS = @LIBQB_CFLAGS@ +LIBQB_LIBS = @LIBQB_LIBS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINT_FLAGS = @LINT_FLAGS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOGDIR = @LOGDIR@ +LOGROTATEDIR = @LOGROTATEDIR@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +QUORUM_SONAME = @QUORUM_SONAME@ +RANLIB = @RANLIB@ +RUSTC = @RUSTC@ +RUSTDOC = @RUSTDOC@ +RUSTFMT = @RUSTFMT@ +RUST_FLAGS = @RUST_FLAGS@ +RUST_TARGET_DIR = @RUST_TARGET_DIR@ +SAM_SONAME = @SAM_SONAME@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SNMPCONFIG = @SNMPCONFIG@ +SNMP_LIBS = @SNMP_LIBS@ +SOMAJOR = @SOMAJOR@ +SOMICRO = @SOMICRO@ +SOMINOR = @SOMINOR@ +SONAME = @SONAME@ +STRIP = @STRIP@ +SYSTEMDDIR = @SYSTEMDDIR@ +VERSCRIPT_LDFLAGS = @VERSCRIPT_LDFLAGS@ +VERSION = @VERSION@ +VOTEQUORUM_SONAME = @VOTEQUORUM_SONAME@ +WITH_LIST = @WITH_LIST@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +corosyncrustver = @corosyncrustver@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +knet_CFLAGS = @knet_CFLAGS@ +knet_LIBS = @knet_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libsystemd_CFLAGS = @libsystemd_CFLAGS@ +libsystemd_LIBS = @libsystemd_LIBS@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nozzle_CFLAGS = @nozzle_CFLAGS@ +nozzle_LIBS = @nozzle_LIBS@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +statgrab_CFLAGS = @statgrab_CFLAGS@ +statgrab_LIBS = @statgrab_LIBS@ +statgrabge090_CFLAGS = @statgrabge090_CFLAGS@ +statgrabge090_LIBS = @statgrabge090_LIBS@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAINTAINERCLEANFILES = Makefile.in +EXTRA_DIST = ploadstart.sh +noinst_SCRIPTS = ploadstart +testcpg_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +testcpg2_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +testcpgzc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +testzcgc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +stress_cpgzc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +stress_cpgfdget_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +stress_cpgcontext_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +testquorum_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libquorum.la +testquorummodel_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libquorum.la +testvotequorum1_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libvotequorum.la +testvotequorum2_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libvotequorum.la +cpgbound_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +cpgbench_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la +cpgbenchzc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la \ + $(top_builddir)/common_lib/libcorosync_common.la + +testsam_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libsam.la \ + $(top_builddir)/lib/libcmap.la + +testcfg_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcfg.la +@HAVE_CRC32_TRUE@cpghum_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la -lz +@HAVE_CRC32_TRUE@cpgverify_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la -lz +LINT_FILES1 := $(filter-out sa_error.c, $(wildcard *.c)) +LINT_FILES := $(filter-out testparse.c, $(LINT_FILES1)) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign test/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +cpgbench$(EXEEXT): $(cpgbench_OBJECTS) $(cpgbench_DEPENDENCIES) $(EXTRA_cpgbench_DEPENDENCIES) + @rm -f cpgbench$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cpgbench_OBJECTS) $(cpgbench_LDADD) $(LIBS) + +cpgbenchzc$(EXEEXT): $(cpgbenchzc_OBJECTS) $(cpgbenchzc_DEPENDENCIES) $(EXTRA_cpgbenchzc_DEPENDENCIES) + @rm -f cpgbenchzc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cpgbenchzc_OBJECTS) $(cpgbenchzc_LDADD) $(LIBS) + +cpgbound$(EXEEXT): $(cpgbound_OBJECTS) $(cpgbound_DEPENDENCIES) $(EXTRA_cpgbound_DEPENDENCIES) + @rm -f cpgbound$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cpgbound_OBJECTS) $(cpgbound_LDADD) $(LIBS) + +cpghum$(EXEEXT): $(cpghum_OBJECTS) $(cpghum_DEPENDENCIES) $(EXTRA_cpghum_DEPENDENCIES) + @rm -f cpghum$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cpghum_OBJECTS) $(cpghum_LDADD) $(LIBS) + +cpgverify$(EXEEXT): $(cpgverify_OBJECTS) $(cpgverify_DEPENDENCIES) $(EXTRA_cpgverify_DEPENDENCIES) + @rm -f cpgverify$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cpgverify_OBJECTS) $(cpgverify_LDADD) $(LIBS) + +stress_cpgcontext$(EXEEXT): $(stress_cpgcontext_OBJECTS) $(stress_cpgcontext_DEPENDENCIES) $(EXTRA_stress_cpgcontext_DEPENDENCIES) + @rm -f stress_cpgcontext$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(stress_cpgcontext_OBJECTS) $(stress_cpgcontext_LDADD) $(LIBS) + +stress_cpgfdget$(EXEEXT): $(stress_cpgfdget_OBJECTS) $(stress_cpgfdget_DEPENDENCIES) $(EXTRA_stress_cpgfdget_DEPENDENCIES) + @rm -f stress_cpgfdget$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(stress_cpgfdget_OBJECTS) $(stress_cpgfdget_LDADD) $(LIBS) + +stress_cpgzc$(EXEEXT): $(stress_cpgzc_OBJECTS) $(stress_cpgzc_DEPENDENCIES) $(EXTRA_stress_cpgzc_DEPENDENCIES) + @rm -f stress_cpgzc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(stress_cpgzc_OBJECTS) $(stress_cpgzc_LDADD) $(LIBS) + +testcfg$(EXEEXT): $(testcfg_OBJECTS) $(testcfg_DEPENDENCIES) $(EXTRA_testcfg_DEPENDENCIES) + @rm -f testcfg$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testcfg_OBJECTS) $(testcfg_LDADD) $(LIBS) + +testcpg$(EXEEXT): $(testcpg_OBJECTS) $(testcpg_DEPENDENCIES) $(EXTRA_testcpg_DEPENDENCIES) + @rm -f testcpg$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testcpg_OBJECTS) $(testcpg_LDADD) $(LIBS) + +testcpg2$(EXEEXT): $(testcpg2_OBJECTS) $(testcpg2_DEPENDENCIES) $(EXTRA_testcpg2_DEPENDENCIES) + @rm -f testcpg2$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testcpg2_OBJECTS) $(testcpg2_LDADD) $(LIBS) + +testcpgzc$(EXEEXT): $(testcpgzc_OBJECTS) $(testcpgzc_DEPENDENCIES) $(EXTRA_testcpgzc_DEPENDENCIES) + @rm -f testcpgzc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testcpgzc_OBJECTS) $(testcpgzc_LDADD) $(LIBS) + +testquorum$(EXEEXT): $(testquorum_OBJECTS) $(testquorum_DEPENDENCIES) $(EXTRA_testquorum_DEPENDENCIES) + @rm -f testquorum$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testquorum_OBJECTS) $(testquorum_LDADD) $(LIBS) + +testquorummodel$(EXEEXT): $(testquorummodel_OBJECTS) $(testquorummodel_DEPENDENCIES) $(EXTRA_testquorummodel_DEPENDENCIES) + @rm -f testquorummodel$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testquorummodel_OBJECTS) $(testquorummodel_LDADD) $(LIBS) + +testsam$(EXEEXT): $(testsam_OBJECTS) $(testsam_DEPENDENCIES) $(EXTRA_testsam_DEPENDENCIES) + @rm -f testsam$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testsam_OBJECTS) $(testsam_LDADD) $(LIBS) + +testvotequorum1$(EXEEXT): $(testvotequorum1_OBJECTS) $(testvotequorum1_DEPENDENCIES) $(EXTRA_testvotequorum1_DEPENDENCIES) + @rm -f testvotequorum1$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testvotequorum1_OBJECTS) $(testvotequorum1_LDADD) $(LIBS) + +testvotequorum2$(EXEEXT): $(testvotequorum2_OBJECTS) $(testvotequorum2_DEPENDENCIES) $(EXTRA_testvotequorum2_DEPENDENCIES) + @rm -f testvotequorum2$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testvotequorum2_OBJECTS) $(testvotequorum2_LDADD) $(LIBS) + +testzcgc$(EXEEXT): $(testzcgc_OBJECTS) $(testzcgc_DEPENDENCIES) $(EXTRA_testzcgc_DEPENDENCIES) + @rm -f testzcgc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testzcgc_OBJECTS) $(testzcgc_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpgbench.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpgbenchzc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpgbound.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpghum.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpgverify.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stress_cpgcontext.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stress_cpgfdget.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stress_cpgzc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcfg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcpg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcpg2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcpgzc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testquorum.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testquorummodel.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testsam.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testvotequorum1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testvotequorum2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testzcgc.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(SCRIPTS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-local clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + + +ploadstart: ploadstart.sh + $(SED) -e 's#@''BASHPATH@#${BASHPATH}#g' $< > $@ + chmod 755 $@ + +lint: + -for f in $(LINT_FILES) ; do echo Splint $$f ; splint $(LINT_FLAGS) $(CPPFLAGS) $(CFLAGS) $$f ; done + +clean-local: + rm -f ploadstart + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/test/cpgbench.c b/test/cpgbench.c new file mode 100644 index 0000000..059effe --- /dev/null +++ b/test/cpgbench.c @@ -0,0 +1,197 @@ +/* + * 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 <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <errno.h> +#include <time.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <pthread.h> + +#include <qb/qblog.h> +#include <qb/qbutil.h> + +#include <corosync/corotypes.h> +#include <corosync/cpg.h> + +static cpg_handle_t handle; + +static pthread_t thread; + +#ifndef timersub +#define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* timersub */ + +static int alarm_notice; + +static void cpg_bm_confchg_fn ( + cpg_handle_t handle_in, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ +} + +static unsigned int write_count; + +static void cpg_bm_deliver_fn ( + cpg_handle_t handle_in, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *msg, + size_t msg_len) +{ + write_count++; +} + +static cpg_callbacks_t callbacks = { + .cpg_deliver_fn = cpg_bm_deliver_fn, + .cpg_confchg_fn = cpg_bm_confchg_fn +}; + +#define ONE_MEG 1048576 +static char data[ONE_MEG]; + +static void cpg_benchmark ( + cpg_handle_t handle_in, + int write_size) +{ + struct timeval tv1, tv2, tv_elapsed; + struct iovec iov; + unsigned int res; + + alarm_notice = 0; + iov.iov_base = data; + iov.iov_len = write_size; + + write_count = 0; + alarm (10); + + gettimeofday (&tv1, NULL); + do { + res = cpg_mcast_joined (handle_in, CPG_TYPE_AGREED, &iov, 1); + } while (alarm_notice == 0 && (res == CS_OK || res == CS_ERR_TRY_AGAIN)); + gettimeofday (&tv2, NULL); + timersub (&tv2, &tv1, &tv_elapsed); + + printf ("%5d messages received ", write_count); + printf ("%5d bytes per write ", write_size); + printf ("%7.3f Seconds runtime ", + (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0))); + printf ("%9.3f TP/s ", + ((float)write_count) / (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0))); + printf ("%7.3f MB/s.\n", + ((float)write_count) * ((float)write_size) / ((tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)) * 1000000.0)); +} + +static void sigalrm_handler (int num) +{ + alarm_notice = 1; +} + +static struct cpg_name group_name = { + .value = "cpg_bm", + .length = 6 +}; + +static void* dispatch_thread (void *arg) +{ + cpg_dispatch (handle, CS_DISPATCH_BLOCKING); + return NULL; +} + +int main (void) { + unsigned int size; + int i; + unsigned int res; + + qb_log_init("cpgbench", LOG_USER, LOG_EMERG); + qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE); + qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD, + QB_LOG_FILTER_FILE, "*", LOG_DEBUG); + qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); + + size = 64; + signal (SIGALRM, sigalrm_handler); + res = cpg_initialize (&handle, &callbacks); + if (res != CS_OK) { + printf ("cpg_initialize failed with result %d\n", res); + exit (1); + } + pthread_create (&thread, NULL, dispatch_thread, NULL); + + res = cpg_join (handle, &group_name); + if (res != CS_OK) { + printf ("cpg_join failed with result %d\n", res); + exit (1); + } + + for (i = 0; i < 10; i++) { /* number of repetitions - up to 50k */ + cpg_benchmark (handle, size); + signal (SIGALRM, sigalrm_handler); + size *= 5; + if (size >= (ONE_MEG - 100)) { + break; + } + } + + res = cpg_finalize (handle); + if (res != CS_OK) { + printf ("cpg_finalize failed with result %d\n", res); + exit (1); + } + return (0); +} diff --git a/test/cpgbenchzc.c b/test/cpgbenchzc.c new file mode 100644 index 0000000..92f55ee --- /dev/null +++ b/test/cpgbenchzc.c @@ -0,0 +1,193 @@ +/* + * 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 <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <errno.h> +#include <time.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <corosync/corotypes.h> +#include <corosync/cpg.h> +#include "../lib/util.h" + +#ifndef timersub +#define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif + +static int alarm_notice; + +static void cpg_bm_confchg_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ +} + +static unsigned int write_count; + +static void cpg_bm_deliver_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *msg, + size_t msg_len) +{ + write_count++; +} + +static cpg_callbacks_t callbacks = { + .cpg_deliver_fn = cpg_bm_deliver_fn, + .cpg_confchg_fn = cpg_bm_confchg_fn +}; + + +void *data; + +static void cpg_benchmark ( + cpg_handle_t handle, + int write_size) +{ + struct timeval tv1, tv2, tv_elapsed; + unsigned int res; + cpg_flow_control_state_t flow_control_state; + + alarm_notice = 0; + + write_count = 0; + alarm (10); + + gettimeofday (&tv1, NULL); + do { + /* + * Test checkpoint write + */ + cpg_flow_control_state_get (handle, &flow_control_state); + if (flow_control_state == CPG_FLOW_CONTROL_DISABLED) { +retry: + res = cpg_zcb_mcast_joined (handle, CPG_TYPE_AGREED, data, write_size); + if (res == CS_ERR_TRY_AGAIN) { + goto retry; + } + } + res = cpg_dispatch (handle, CS_DISPATCH_ALL); + if (res != CS_OK) { + printf ("cpg dispatch returned error %d\n", res); + exit (1); + } + } while (alarm_notice == 0); + gettimeofday (&tv2, NULL); + timersub (&tv2, &tv1, &tv_elapsed); + + printf ("%5d messages received ", write_count); + printf ("%5d bytes per write ", write_size); + printf ("%7.3f Seconds runtime ", + (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0))); + printf ("%9.3f TP/s ", + ((float)write_count) / (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0))); + printf ("%7.3f MB/s.\n", + ((float)write_count) * ((float)write_size) / ((tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)) * 1000000.0)); +} + +static void sigalrm_handler (int num) +{ + alarm_notice = 1; +} + +static struct cpg_name group_name = { + .value = "cpg_bm", + .length = 6 +}; + +int main (void) { + cpg_handle_t handle; + unsigned int size; + int i; + unsigned int res; + + + + size = 1000; + signal (SIGALRM, sigalrm_handler); + res = cpg_initialize (&handle, &callbacks); + if (res != CS_OK) { + printf ("cpg_initialize failed with result %d\n", res); + exit (1); + } + cpg_zcb_alloc (handle, 500000, &data); + if (res != CS_OK) { + printf ("cpg_zcb_alloc couldn't allocate zero copy buffer %d\n", res); + exit (1); + } + + res = cpg_join (handle, &group_name); + if (res != CS_OK) { + printf ("cpg_join failed with result %s\n", cs_strerror(res)); + exit (1); + } + + for (i = 0; i < 50; i++) { /* number of repetitions - up to 50k */ + cpg_benchmark (handle, size); + size += 1000; + } + + res = cpg_finalize (handle); + if (res != CS_OK) { + printf ("cpg_finalize failed with result %s\n", cs_strerror(res)); + exit (1); + } + return (0); +} diff --git a/test/cpgbound.c b/test/cpgbound.c new file mode 100644 index 0000000..f3ac375 --- /dev/null +++ b/test/cpgbound.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 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 <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <string.h> +#include <corosync/corotypes.h> +#include <corosync/cpg.h> + +static void cpg_deliver_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *m, + size_t msg_len) +{ +} + +static void cpg_confchg_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ +} + +static cpg_callbacks_t callbacks = { + cpg_deliver_fn, + cpg_confchg_fn +}; + +static struct cpg_name group_name = { + .value = "cpg_bm", + .length = 6 +}; + + +static unsigned char buffer[2000000]; +int main (void) +{ + cpg_handle_t handle; + cs_error_t result; + unsigned int i = 0; + struct iovec iov; + int res; + unsigned int msg_size; + + result = cpg_initialize (&handle, &callbacks); + if (result != CS_OK) { + printf ("Couldn't initialize CPG service %d\n", result); + exit (0); + } + + res = cpg_join (handle, &group_name); + if (res != CS_OK) { + printf ("cpg_join failed with result %d\n", res); + exit (1); + } + + iov.iov_base = (void *)buffer; + + /* + * Demonstrate cpg_mcast_joined + */ + msg_size = 1025000; + for (i = 0; i < 1000000000; i++) { + iov.iov_len = msg_size; +try_again_one: + result = cpg_mcast_joined (handle, CPG_TYPE_AGREED, + &iov, 1); + if (result == CS_ERR_TRY_AGAIN) { + goto try_again_one; + } + if (result == CS_ERR_INVALID_PARAM) { + printf ("found boundary at %d\n", msg_size); + exit (1); + } + msg_size += 1; + printf ("msg size %d\n", msg_size); + result = cpg_dispatch (handle, CS_DISPATCH_ALL); + if (result != CS_OK && result != CS_ERR_TRY_AGAIN) { + printf ("cpg_dispatch failed with result %d\n", res); + exit (1); + } + } + + cpg_finalize (handle); + + return (0); +} diff --git a/test/cpghum.c b/test/cpghum.c new file mode 100644 index 0000000..fd1e388 --- /dev/null +++ b/test/cpghum.c @@ -0,0 +1,884 @@ +/* + * Copyright (c) 2015-2017 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <assert.h> +#include <errno.h> +#include <time.h> +#include <limits.h> +#include <ctype.h> +#include <syslog.h> +#include <stdarg.h> +#include <inttypes.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <pthread.h> +#include <zlib.h> +#include <libgen.h> +#include <getopt.h> + +#include <corosync/corotypes.h> +#include <corosync/cpg.h> + +static cpg_handle_t handle; + +static pthread_t thread; + +#ifndef timersub +#define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* timersub */ + +static int alarm_notice; +#define MAX_NODEID 65536 +#define ONE_MEG 1048576 +#define DATASIZE (ONE_MEG*20) +static char data[DATASIZE]; +static int send_counter = 0; +static int do_syslog = 0; +static int quiet = 0; +static int report_rtt = 0; +static int abort_on_error = 0; +static int machine_readable = 0; +static char delimiter = ','; +static int to_stderr = 0; +static unsigned int g_our_nodeid; +static volatile int stopped; +static unsigned int flood_start = 64; +static unsigned int flood_multiplier = 5; +static unsigned long flood_max = (ONE_MEG - 100); + +// stats +static unsigned int length_errors=0; +static unsigned int crc_errors=0; +static unsigned int sequence_errors=0; +static unsigned int packets_sent=0; +static unsigned int packets_recvd=0; +static unsigned int packets_recvd1=0; /* For flood intermediates */ +static unsigned int send_retries=0; +static unsigned int send_fails=0; +static unsigned long avg_rtt=0; +static unsigned long max_rtt=0; +static unsigned long min_rtt=LONG_MAX; +static unsigned long interim_avg_rtt=0; +static unsigned long interim_max_rtt=0; +static unsigned long interim_min_rtt=LONG_MAX; + +struct cpghum_header { + unsigned int counter; + unsigned int crc; + unsigned int size; + struct timeval timestamp; +}; + +static void cpg_bm_confchg_fn ( + cpg_handle_t handle_in, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ +} + +static unsigned int g_recv_count; +static unsigned int g_recv_length; +static int g_recv_start[MAX_NODEID+1]; +static int g_recv_counter[MAX_NODEID+1]; +static int g_recv_size[MAX_NODEID+1]; +static int g_log_mask = 0xFFFF; +typedef enum +{ + CPGH_LOG_INFO = 1, + CPGH_LOG_PERF = 2, + CPGH_LOG_RTT = 4, + CPGH_LOG_STATS = 8, + CPGH_LOG_ERR = 16 +} log_type_t; + +static void cpgh_print_message(int syslog_level, const char *facility_name, const char *format, va_list ap) + __attribute__((format(printf, 3, 0))); + +static void cpgh_log_printf(log_type_t type, const char *format, ...) + __attribute__((format(printf, 2, 3))); + +static void cpgh_print_message(int syslog_level, const char *facility_name, const char *format, va_list ap) +{ + char msg[1024]; + int start = 0; + + if (machine_readable) { + snprintf(msg, sizeof(msg), "%s%c", facility_name, delimiter); + start = strlen(msg); + } + + assert(vsnprintf(msg+start, sizeof(msg)-start, format, ap) < sizeof(msg)-start); + + if (to_stderr || (syslog_level <= LOG_ERR)) { + fprintf(stderr, "%s", msg); + } + else { + printf("%s", msg); + } + if (do_syslog) { + syslog(syslog_level, "%s", msg); + } +} + +static void cpgh_log_printf(log_type_t type, const char *format, ...) +{ + va_list ap; + + if (!(type & g_log_mask)) { + return; + } + + va_start(ap, format); + + switch (type) { + case CPGH_LOG_INFO: + cpgh_print_message(LOG_INFO, "[Info]", format, ap); + break; + case CPGH_LOG_PERF: + cpgh_print_message(LOG_INFO, "[Perf]", format, ap); + break; + case CPGH_LOG_RTT: + cpgh_print_message(LOG_INFO, "[RTT]", format, ap); + break; + case CPGH_LOG_STATS: + cpgh_print_message(LOG_INFO, "[Stats]", format, ap); + break; + case CPGH_LOG_ERR: + cpgh_print_message(LOG_ERR, "[Err]", format, ap); + break; + default: + break; + } + + va_end(ap); +} + +static unsigned long update_rtt(struct timeval *header_timestamp, int packet_count, + unsigned long *rtt_min, unsigned long *rtt_avg, unsigned long *rtt_max) +{ + struct timeval tv1; + struct timeval rtt; + unsigned long rtt_usecs; + + gettimeofday (&tv1, NULL); + timersub(&tv1, header_timestamp, &rtt); + + rtt_usecs = rtt.tv_usec + rtt.tv_sec*1000000; + if (rtt_usecs > *rtt_max) { + *rtt_max = rtt_usecs; + } + if (rtt_usecs < *rtt_min) { + *rtt_min = rtt_usecs; + } + + /* Don't start the average with 0 */ + if (*rtt_avg == 0) { + *rtt_avg = rtt_usecs; + } + else { + *rtt_avg = ((*rtt_avg * packet_count) + rtt_usecs) / (packet_count+1); + } + + return rtt_usecs; +} + + +static void cpg_bm_deliver_fn ( + cpg_handle_t handle_in, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *msg, + size_t msg_len) +{ + uLong crc=0; + struct cpghum_header *header = (struct cpghum_header *)msg; + uLong recv_crc = header->crc & 0xFFFFFFFF; + unsigned int *dataint = (unsigned int *)((char*)msg + sizeof(struct cpghum_header)); + unsigned int datalen; + + if (nodeid > MAX_NODEID) { + cpgh_log_printf(CPGH_LOG_ERR, "Got message from invalid nodeid " CS_PRI_NODE_ID " (too high for us). Quitting\n", nodeid); + exit(1); + } + + packets_recvd++; + packets_recvd1++; + g_recv_length = msg_len; + datalen = header->size - sizeof(struct cpghum_header); + + // Report RTT first in case abort_on_error is set + if (nodeid == g_our_nodeid) { + unsigned long rtt_usecs; + + // For flood + update_rtt(&header->timestamp, packets_recvd1, &interim_min_rtt, &interim_avg_rtt, &interim_max_rtt); + + rtt_usecs = update_rtt(&header->timestamp, g_recv_counter[nodeid], &min_rtt, &avg_rtt, &max_rtt); + + if (report_rtt) { + if (machine_readable) { + cpgh_log_printf(CPGH_LOG_RTT, "%ld%c%ld%c%ld%c%ld\n", rtt_usecs, delimiter, min_rtt, delimiter, avg_rtt, delimiter, max_rtt); + } + else { + cpgh_log_printf(CPGH_LOG_RTT, "%s: RTT %ld uS (min/avg/max): %ld/%ld/%ld\n", group_name->value, rtt_usecs, min_rtt, avg_rtt, max_rtt); + } + } + } + + // Basic check, packets should all be the right size + if (msg_len != header->size) { + length_errors++; + cpgh_log_printf(CPGH_LOG_ERR, "%s: message sizes don't match. got %zu, expected %u from node " CS_PRI_NODE_ID "\n", group_name->value, msg_len, header->size, nodeid); + + if (abort_on_error) { + exit(2); + } + } + g_recv_size[nodeid] = msg_len; + + // Sequence counters are incrementing in step? + if (header->counter != g_recv_counter[nodeid]) { + + /* Don't report the first mismatch or a newly restarted sender, we're just catching up */ + if (g_recv_counter[nodeid] && header->counter) { + sequence_errors++; + cpgh_log_printf(CPGH_LOG_ERR, "%s: counters don't match. got %d, expected %d from node " CS_PRI_NODE_ID "\n", group_name->value, header->counter, g_recv_counter[nodeid], nodeid); + + if (abort_on_error) { + exit(2); + } + } + else { + g_recv_start[nodeid] = header->counter; + } + + /* Catch up or we'll be printing errors for ever */ + g_recv_counter[nodeid] = header->counter+1; + } + else { + g_recv_counter[nodeid]++; + } + + /* Check crc */ + crc = crc32(0, NULL, 0); + crc = crc32(crc, (Bytef *)dataint, datalen) & 0xFFFFFFFF; + if (crc != recv_crc) { + crc_errors++; + cpgh_log_printf(CPGH_LOG_ERR, "%s: CRCs don't match. got %lx, expected %lx from nodeid " CS_PRI_NODE_ID "\n", group_name->value, recv_crc, crc, nodeid); + + if (abort_on_error) { + exit(2); + } + + } + + g_recv_count++; + +} + +static cpg_model_v1_data_t model1_data = { + .cpg_deliver_fn = cpg_bm_deliver_fn, + .cpg_confchg_fn = cpg_bm_confchg_fn, +}; + +static cpg_callbacks_t callbacks = { + .cpg_deliver_fn = cpg_bm_deliver_fn, + .cpg_confchg_fn = cpg_bm_confchg_fn +}; + +static struct cpg_name group_name = { + .value = "cpghum", + .length = 7 +}; + +static void set_packet(int write_size, int counter) +{ + struct cpghum_header *header = (struct cpghum_header *)data; + int i; + unsigned int *dataint = (unsigned int *)(data + sizeof(struct cpghum_header)); + unsigned int datalen = write_size - sizeof(struct cpghum_header); + struct timeval tv1; + uLong crc; + + header->counter = counter; + for (i=0; i<(datalen/4); i++) { + dataint[i] = rand(); + } + crc = crc32(0, NULL, 0); + header->crc = crc32(crc, (Bytef*)&dataint[0], datalen); + header->size = write_size; + + gettimeofday (&tv1, NULL); + memcpy(&header->timestamp, &tv1, sizeof(struct timeval)); +} + +/* Basically this is cpgbench.c */ +static void cpg_flood ( + cpg_handle_t handle_in, + int write_size) +{ + struct timeval tv1, tv2, tv_elapsed; + struct iovec iov; + unsigned int res = CS_OK; + + alarm_notice = 0; + iov.iov_base = data; + iov.iov_len = write_size; + + alarm (10); + packets_recvd1 = 0; + interim_avg_rtt = 0; + interim_max_rtt = 0; + interim_min_rtt = LONG_MAX; + + gettimeofday (&tv1, NULL); + do { + if (res == CS_OK) { + set_packet(write_size, send_counter); + } + + res = cpg_mcast_joined (handle_in, CPG_TYPE_AGREED, &iov, 1); + if (res == CS_OK) { + /* Only increment the packet counter if it was sucessfully sent */ + packets_sent++; + send_counter++; + } + else { + if (res == CS_ERR_TRY_AGAIN) { + send_retries++; + } + else { + send_fails++; + } + } + } while (!stopped && alarm_notice == 0 && (res == CS_OK || res == CS_ERR_TRY_AGAIN)); + gettimeofday (&tv2, NULL); + timersub (&tv2, &tv1, &tv_elapsed); + + if (!quiet) { + if (machine_readable) { + cpgh_log_printf (CPGH_LOG_PERF, "%d%c%d%c%f%c%f%c%f%c%ld%c%ld%c%ld\n", packets_recvd1, delimiter, write_size, delimiter, + (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)), delimiter, + ((float)packets_recvd1) / (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)), delimiter, + ((float)packets_recvd1) * ((float)write_size) / ((tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)) * 1000000.0), delimiter, + interim_min_rtt, delimiter, interim_avg_rtt, delimiter, interim_max_rtt); + } + else { + cpgh_log_printf (CPGH_LOG_PERF, "%5d messages received ", packets_recvd1); + cpgh_log_printf (CPGH_LOG_PERF, "%5d bytes per write ", write_size); + cpgh_log_printf (CPGH_LOG_PERF, "%7.3f Seconds runtime ", + (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0))); + cpgh_log_printf (CPGH_LOG_PERF, "%9.3f TP/s ", + ((float)packets_recvd1) / (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0))); + cpgh_log_printf (CPGH_LOG_PERF, "%7.3f MB/s ", + ((float)packets_recvd1) * ((float)write_size) / ((tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)) * 1000000.0)); + cpgh_log_printf (CPGH_LOG_PERF, "RTT for this size (min/avg/max) %ld/%ld/%ld\n", + interim_min_rtt, interim_avg_rtt, interim_max_rtt); + } + } +} + +static int cpg_test ( + cpg_handle_t handle_in, + int write_size, + int delay_time, + int print_time) +{ + struct iovec iov; + unsigned int res; + + alarm_notice = 0; + iov.iov_base = data; + iov.iov_len = write_size; + + g_recv_count = 0; + alarm (print_time); + + do { + send_counter++; + resend: + set_packet(write_size, send_counter); + + res = cpg_mcast_joined (handle_in, CPG_TYPE_AGREED, &iov, 1); + if (res == CS_ERR_TRY_AGAIN) { + usleep(10000); + send_retries++; + goto resend; + } + if (res == CS_ERR_LIBRARY) { + send_counter--; + return -1; + } + if (res != CS_OK) { + cpgh_log_printf(CPGH_LOG_ERR, "send failed: %d\n", res); + send_fails++; + } + else { + packets_sent++; + } + usleep(delay_time*1000); + } while (alarm_notice == 0 && (res == CS_OK || res == CS_ERR_TRY_AGAIN) && stopped == 0); + + if (!quiet) { + if (machine_readable) { + cpgh_log_printf(CPGH_LOG_RTT, "%d%c%ld%c%ld%c%ld\n", 0, delimiter, min_rtt, delimiter, avg_rtt, delimiter, max_rtt); + } + else { + cpgh_log_printf(CPGH_LOG_PERF, "%s: %5d message%s received, ", group_name.value, g_recv_count, g_recv_count==1?"":"s"); + cpgh_log_printf(CPGH_LOG_PERF, "%5d bytes per write. ", write_size); + cpgh_log_printf(CPGH_LOG_RTT, "RTT min/avg/max: %ld/%ld/%ld\n", min_rtt, avg_rtt, max_rtt); + } + } + return 0; +} + +static void sigalrm_handler (int num) +{ + alarm_notice = 1; +} + +static void sigint_handler (int num) +{ + stopped = 1; +} + +static void* dispatch_thread (void *arg) +{ + cpg_dispatch (handle, CS_DISPATCH_BLOCKING); + return NULL; +} + +static void usage(char *cmd) +{ + fprintf(stderr, "%s [OPTIONS]\n", cmd); + fprintf(stderr, "\n"); + fprintf(stderr, "%s sends CPG messages to all registered users of the CPG.\n", cmd); + fprintf(stderr, "The messages have a sequence number and a CRC so that missing or\n"); + fprintf(stderr, "corrupted messages will be detected and reported.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "%s can also be asked to simply listen for (and check) packets\n", cmd); + fprintf(stderr, "so that there is another node in the cluster connected to the CPG.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Multiple copies, in different CPGs, can also be run on the same or\n"); + fprintf(stderr, "different nodes by using the -n option.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "%s can handle more than 1 sender in the same CPG provided they are on\n", cmd); + fprintf(stderr, "different nodes.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -w<num>, --size-bytes Write size in Kbytes, default 4\n"); + fprintf(stderr, " -W<num>, --size-kb Write size in bytes, default 4096\n"); + fprintf(stderr, " -n<name>, --name CPG name to use, default 'cpghum'\n"); + fprintf(stderr, " -M Write machine-readable results\n"); + fprintf(stderr, " -D<char> Delimiter for machine-readable results (default ',')\n"); + fprintf(stderr, " -E Send normal output to stderr instead of stdout\n"); + fprintf(stderr, " -d<num>, --delay Delay between sending packets (mS), default 1000\n"); + fprintf(stderr, " -r<num> Number of repetitions, default 100\n"); + fprintf(stderr, " -p<num> Delay between printing output (seconds), default 10s\n"); + fprintf(stderr, " -l, --listen Listen and check CRCs only, don't send (^C to quit)\n"); + fprintf(stderr, " -t, --rtt Report Round Trip Times for each packet.\n"); + fprintf(stderr, " -m<num> cpg_initialise() model. Default 1.\n"); + fprintf(stderr, " -s Also send errors to syslog.\n"); + fprintf(stderr, " -f, --flood Flood test CPG (cpgbench). see --flood-* long options\n"); + fprintf(stderr, " -a Abort on crc/length/sequence error\n"); + fprintf(stderr, " -q, --quiet Quiet. Don't print messages every 10s (see also -p)\n"); + fprintf(stderr, " -qq Very quiet. Don't print stats at the end\n"); + fprintf(stderr, " --flood-start=bytes Start value for --flood\n"); + fprintf(stderr, " --flood-mult=value Packet size multiplier value for --flood\n"); + fprintf(stderr, " --flood-max=bytes Maximum packet size for --flood\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " values for --flood* and -W can have K or M suffixes to indicate\n"); + fprintf(stderr, " Kilobytes or Megabytes\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "%s exit code is 0 if no error happened, 1 on generic error and 2 on\n", cmd); + fprintf(stderr, "send/crc/length/sequence error"); + fprintf(stderr, "\n"); +} + +/* Parse a size, optionally ending in 'K', 'M' */ +static long parse_bytes(const char *valstring) +{ + unsigned int value; + int multiplier = 1; + char suffix = '\0'; + int have_suffix = 0; + + /* Suffix is optional */ + if (sscanf(valstring, "%u%c", &value, &suffix) == 0) { + return 0; + } + + if (toupper(suffix) == 'M') { + multiplier = 1024*1024; + have_suffix = 1; + } + if (toupper(suffix) == 'K') { + multiplier = 1024; + have_suffix = 1; + } + + if (!have_suffix && suffix != '\0') { + fprintf(stderr, "Invalid suffix '%c', only K or M supported\n", suffix); + return 0; + } + return value * multiplier; +} + +static int connect_and_join(int model, int verbose) +{ + int res; + + switch (model) { + case 0: + res = cpg_initialize (&handle, &callbacks); + break; + case 1: + res = cpg_model_initialize (&handle, CPG_MODEL_V1, (cpg_model_data_t *)&model1_data, NULL); + break; + default: + res=999; // can't get here but it keeps the compiler happy + break; + } + + if (res != CS_OK) { + if (verbose) { + cpgh_log_printf(CPGH_LOG_ERR, "cpg_initialize failed with result %d\n", res); + } + return -1; + } + + res = cpg_join (handle, &group_name); + if (res != CS_OK) { + if (verbose) { + cpgh_log_printf(CPGH_LOG_ERR, "cpg_join failed with result %d\n", res); + } + cpg_finalize(handle); + return -1; + } + pthread_create (&thread, NULL, dispatch_thread, NULL); + return CS_OK; +} + + +int main (int argc, char *argv[]) { + int i; + unsigned int res; + uint32_t maxsize; + int opt; + int bs; + int write_size = 4096; + int delay_time = 1000; + int repetitions = 100; + int print_time = 10; + int have_size = 0; + int listen_only = 0; + int flood = 0; + int model = 1; + int option_index = 0; + struct option long_options[] = { + {"flood-start", required_argument, 0, 0 }, + {"flood-mult", required_argument, 0, 0 }, + {"flood-max", required_argument, 0, 0 }, + {"size-kb", required_argument, 0, 'w' }, + {"size-bytes", required_argument, 0, 'W' }, + {"name", required_argument, 0, 'n' }, + {"rtt", no_argument, 0, 't' }, + {"flood", no_argument, 0, 'f' }, + {"quiet", no_argument, 0, 'q' }, + {"listen", no_argument, 0, 'l' }, + {"help", no_argument, 0, '?' }, + {0, 0, 0, 0 } + }; + + while ( (opt = getopt_long(argc, argv, "qlstafMEn:d:r:p:m:w:W:D:", + long_options, &option_index)) != -1 ) { + switch (opt) { + case 0: // Long-only options + if (strcmp(long_options[option_index].name, "flood-start") == 0) { + flood_start = parse_bytes(optarg); + if (flood_start == 0) { + fprintf(stderr, "flood-start value invalid\n"); + exit(1); + } + } + if (strcmp(long_options[option_index].name, "flood-mult") == 0) { + flood_multiplier = parse_bytes(optarg); + if (flood_multiplier == 0) { + fprintf(stderr, "flood-mult value invalid\n"); + exit(1); + } + } + if (strcmp(long_options[option_index].name, "flood-max") == 0) { + flood_max = parse_bytes(optarg); + if (flood_max == 0) { + fprintf(stderr, "flood-max value invalid\n"); + exit(1); + } + } + break; + case 'w': // Write size in K + bs = atoi(optarg); + if (bs > 0) { + write_size = bs*1024; + have_size = 1; + } + break; + case 'W': // Write size in bytes (or with a suffix) + bs = parse_bytes(optarg); + if (bs > 0) { + write_size = bs; + have_size = 1; + } + break; + case 'n': + if (strlen(optarg) >= CPG_MAX_NAME_LENGTH) { + fprintf(stderr, "CPG name too long\n"); + exit(1); + } + + strcpy(group_name.value, optarg); + group_name.length = strlen(group_name.value); + break; + case 't': + report_rtt = 1; + break; + case 'E': + to_stderr = 1; + break; + case 'M': + machine_readable = 1; + break; + case 'f': + flood = 1; + break; + case 'a': + abort_on_error = 1; + break; + case 'd': + delay_time = atoi(optarg); + break; + case 'D': + delimiter = optarg[0]; + break; + case 'r': + repetitions = atoi(optarg); + break; + case 'p': + print_time = atoi(optarg); + break; + case 'l': + listen_only = 1; + break; + case 's': + do_syslog = 1; + break; + case 'q': + quiet++; + break; + case 'm': + model = atoi(optarg); + if (model < 0 || model > 1) { + fprintf(stderr, "%s: Model must be 0-1\n", argv[0]); + exit(1); + } + break; + case '?': + usage(basename(argv[0])); + exit(1); + } + } + + if (!have_size && flood) { + write_size = flood_start; + } + + signal (SIGALRM, sigalrm_handler); + signal (SIGINT, sigint_handler); + + if (connect_and_join(model, 1) != CS_OK) { + exit(1); + } + + res = cpg_local_get(handle, &g_our_nodeid); + if (res != CS_OK) { + cpgh_log_printf(CPGH_LOG_ERR, "cpg_local_get failed with result %d\n", res); + exit (1); + } + + if (listen_only) { + int secs = 0; + + while (!stopped) { + sleep(1); + if (++secs > print_time && !quiet) { + int nodes_printed = 0; + + if (!machine_readable) { + for (i=1; i<MAX_NODEID; i++) { + if (g_recv_counter[i]) { + cpgh_log_printf(CPGH_LOG_INFO, "%s: %5d message%s of %d bytes received from node " CS_PRI_NODE_ID "\n", + group_name.value, g_recv_counter[i] - g_recv_start[i], + g_recv_counter[i]==1?"":"s", + g_recv_size[i], i); + nodes_printed++; + } + } + } + + /* Separate list of nodes if more than one */ + if (nodes_printed > 1) { + cpgh_log_printf(CPGH_LOG_INFO, "\n"); + } + secs = 0; + } + } + } + else { + cpg_max_atomic_msgsize_get (handle, &maxsize); + if (write_size > maxsize) { + fprintf(stderr, "INFO: packet size (%d) is larger than the maximum atomic size (%d), libcpg will fragment\n", + write_size, maxsize); + } + + /* The main job starts here */ + if (flood) { + for (i = 0; i < 10; i++) { /* number of repetitions - up to 50k */ + cpg_flood (handle, write_size); + signal (SIGALRM, sigalrm_handler); + write_size *= flood_multiplier; + if (write_size > flood_max) { + break; + } + } + } + else { + send_counter = -1; /* So we start from zero to allow listeners to sync */ + for (i = 0; i < repetitions && !stopped; i++) { + if (cpg_test (handle, write_size, delay_time, print_time) == -1) { + /* Try to reconnect when corosync stops */ + res = -1; + cpg_finalize(handle); + pthread_cancel(thread); + signal (SIGINT, SIG_DFL); + printf("Reconnecting..."); + fflush(stdout); + while (res != CS_OK) { + sleep(1); + printf("."); + fflush(stdout); + res = connect_and_join(model, 0); + } + printf("done\n"); + signal (SIGINT, sigint_handler); + } + signal (SIGALRM, sigalrm_handler); + } + } + } + + res = cpg_finalize (handle); + if (res != CS_OK) { + cpgh_log_printf(CPGH_LOG_ERR, "cpg_finalize failed with result %d\n", res); + exit (1); + } + + if (quiet < 2) { + /* Don't print LONG_MAX for min_rtt if we don't have a value */ + if (min_rtt == LONG_MAX) { + min_rtt = 0L; + } + + if (machine_readable) { + cpgh_log_printf(CPGH_LOG_STATS, "%d%c%d%c%d%c%d%c%d%c%d%c%d%c%ld%c%ld%c%ld\n", + packets_sent, delimiter, + send_fails, delimiter, + send_retries, delimiter, + length_errors, delimiter, + packets_recvd, delimiter, + sequence_errors, delimiter, + crc_errors, delimiter, + min_rtt, delimiter, + avg_rtt, delimiter, + max_rtt); + } + else { + cpgh_log_printf(CPGH_LOG_STATS, "\n"); + cpgh_log_printf(CPGH_LOG_STATS, "Stats:\n"); + if (!listen_only) { + cpgh_log_printf(CPGH_LOG_STATS, " packets sent: %d\n", packets_sent); + cpgh_log_printf(CPGH_LOG_STATS, " send failures: %d\n", send_fails); + cpgh_log_printf(CPGH_LOG_STATS, " send retries: %d\n", send_retries); + } + cpgh_log_printf(CPGH_LOG_STATS, " length errors: %d\n", length_errors); + cpgh_log_printf(CPGH_LOG_STATS, " packets recvd: %d\n", packets_recvd); + cpgh_log_printf(CPGH_LOG_STATS, " sequence errors: %d\n", sequence_errors); + cpgh_log_printf(CPGH_LOG_STATS, " crc errors: %d\n", crc_errors); + if (!listen_only) { + cpgh_log_printf(CPGH_LOG_STATS, " min RTT: %ld\n", min_rtt); + cpgh_log_printf(CPGH_LOG_STATS, " max RTT: %ld\n", max_rtt); + cpgh_log_printf(CPGH_LOG_STATS, " avg RTT: %ld\n", avg_rtt); + } + cpgh_log_printf(CPGH_LOG_STATS, "\n"); + } + } + + res = 0; + + if (send_fails > 0 || (have_size && length_errors > 0) || sequence_errors > 0 || crc_errors > 0) { + res = 2; + } + + return (res); +} diff --git a/test/cpgverify.c b/test/cpgverify.c new file mode 100644 index 0000000..6d72cff --- /dev/null +++ b/test/cpgverify.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 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 <config.h> + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <string.h> +#include <inttypes.h> +#include <corosync/corotypes.h> +#include <corosync/cpg.h> + +#include <zlib.h> + +struct my_msg { + unsigned int msg_size; + unsigned char crc32[4]; + unsigned char buffer[0]; +}; + +static int deliveries = 0; + +static void cpg_deliver_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *m, + size_t msg_len) +{ + const struct my_msg *msg2 = m; + uLong chsum; + uint32_t nchsum; + + printf ("msg '%s'\n", msg2->buffer); + + chsum = crc32(0L, Z_NULL, 0); + chsum = crc32(chsum, msg2->buffer, msg2->msg_size) & 0xFFFFFFFF; + + printf ("SIZE %d HASH: 0x%08"PRIx32"\n", msg2->msg_size, (uint32_t)chsum); + + nchsum = htonl((uint32_t)chsum); + + if (memcmp(&nchsum, msg2->crc32, sizeof(nchsum)) != 0) { + printf ("incorrect hash\n"); + exit (1); + } + deliveries++; +} + +static void cpg_confchg_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ +} + +static cpg_callbacks_t callbacks = { + cpg_deliver_fn, + cpg_confchg_fn +}; + +static struct cpg_name group_name = { + .value = "cpg_bm", + .length = 6 +}; + + +static unsigned char buffer[200000]; +int main (int argc, char *argv[]) +{ + cpg_handle_t handle; + cs_error_t result; + int i = 0; + int j; + struct my_msg msg; + struct iovec iov[2]; + const char *options = "i:"; + int iter = 1000; + int opt; + int run_forever = 1; + uLong chsum; + uint32_t nchsum; + + while ((opt = getopt(argc, argv, options)) != -1) { + switch (opt) { + case 'i': + run_forever = 0; + iter = atoi(optarg); + break; + } + } + + result = cpg_initialize (&handle, &callbacks); + if (result != CS_OK) { + printf ("Couldn't initialize CPG service %d\n", result); + exit (0); + } + + result = cpg_join (handle, &group_name); + if (result != CS_OK) { + printf ("cpg_join failed with result %d\n", result); + exit (1); + } + + iov[0].iov_base = (void *)&msg; + iov[0].iov_len = sizeof (struct my_msg); + iov[1].iov_base = (void *)buffer; + + /* + * Demonstrate cpg_mcast_joined + */ + i = 0; + do { + msg.msg_size = 100 + rand() % 100000; + iov[1].iov_len = msg.msg_size; + for (j = 0; j < msg.msg_size; j++) { + buffer[j] = j; + } + sprintf ((char *)buffer, + "cpg_mcast_joined: This is message %12d", i); + + chsum = crc32(0L, Z_NULL, 0); + chsum = crc32(chsum, buffer, msg.msg_size) & 0xFFFFFFFF; + nchsum = htonl((uint32_t)chsum); + memcpy(msg.crc32, &nchsum, sizeof(nchsum)) ; +try_again_one: + result = cpg_mcast_joined (handle, CPG_TYPE_AGREED, + iov, 2); + if (result == CS_ERR_TRY_AGAIN) { + goto try_again_one; + } + result = cpg_dispatch (handle, CS_DISPATCH_ALL); + if (result != CS_OK && result != CS_ERR_TRY_AGAIN) { + printf("cpg_dispatch failed with result %d\n", result); + exit(1); + } + i++; + } while (run_forever || i < iter); + + cpg_finalize (handle); + + return (0); +} diff --git a/test/ploadstart.sh b/test/ploadstart.sh new file mode 100644 index 0000000..bea065b --- /dev/null +++ b/test/ploadstart.sh @@ -0,0 +1,60 @@ +#!@BASHPATH@ + +set -e + +msg_count="" +msg_size="" + +usage() { + echo "ploadstart [options]" + echo "" + echo "Options:" + echo " -c msg_count Number of messages to send (max UINT32_T default 1500000)" + echo " -s msg_size Size of messages in bytes (max 1000000 default 300)" + echo " -h display this help" +} + +while getopts "hs:c:" optflag; do + case "$optflag" in + h) + usage + exit 0 + ;; + c) + msg_count="$OPTARG" + ;; + s) + msg_size="$OPTARG" + ;; + \?|:) + usage + exit 1 + ;; + esac +done + +[ -n "$msg_count" ] && corosync-cmapctl -s pload.count u32 $msg_count +[ -n "$msg_size" ] && corosync-cmapctl -s pload.size u32 $msg_size + +echo "***** WARNING *****" +echo "" +echo "Running pload test will kill your cluster and all corosync daemons will exit" +echo "at the end of the load test" +echo "" +echo "***** END OF WARNING *****" +echo "" +echo "YOU HAVE BEEN WARNED" +echo "" +echo "If you agree, and want to proceed, please type:" +echo "Yes, I fully understand the risks of what I am doing" +echo "" +read -p "type here: " ans + +[ "$ans" = "Yes, I fully understand the risks of what I am doing" ] || { + echo "Wise choice.. or you simply didn't type it right" + exit 0 +} + +corosync-cmapctl -s pload.start str i_totally_understand_pload_will_crash_my_cluster_and_kill_corosync_on_exit + +echo "PLOAD started, please see corosync.log for final results" diff --git a/test/stress_cpgcontext.c b/test/stress_cpgcontext.c new file mode 100644 index 0000000..ba14f63 --- /dev/null +++ b/test/stress_cpgcontext.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 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 <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <string.h> +#include <corosync/corotypes.h> +#include <corosync/cpg.h> +#include <signal.h> + +struct my_msg { + unsigned int msg_size; + unsigned char sha1[20]; + unsigned char buffer[0]; +}; + +static void cpg_deliver_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *m, + size_t msg_len) +{ +} + +static void cpg_confchg_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ +} + +static cpg_callbacks_t callbacks = { + cpg_deliver_fn, + cpg_confchg_fn +}; + +static void sigintr_handler (int num) +{ + exit (1); +} + +#define ITERATIONS (1000000) + +#define INSTANCES 100 + +int main (void) +{ + cpg_handle_t handle[INSTANCES]; + cs_error_t res; + void *context[INSTANCES]; + int i, j; + void *ctx; + + signal (SIGINT, sigintr_handler); + for (i = 0; i < INSTANCES; i++) { + res = cpg_initialize (&handle[i], &callbacks); + if (res != CS_OK) { + printf ("FAIL %d\n", res); + exit (-1); + } + } + + for (j = 0; j < ITERATIONS; j++) { + for (i = 0; i < INSTANCES; i++) { + context[i] = malloc (20); + res = cpg_context_set (handle[i], context[i]); + if (res != CS_OK) { + printf ("FAIL %d\n", res); + exit (-1); + } + } + + for (i = 0; i < INSTANCES; i++) { + res = cpg_context_get (handle[i], &ctx); + if (res != CS_OK) { + printf ("FAIL %d\n", res); + exit (-1); + } + if (ctx != context[i]) { + printf ("FAIL\n"); + exit (-1); + } + free (ctx); + } + } + + for (i = 0; i < INSTANCES; i++) { + cpg_finalize (handle[i]); + } + + printf ("PASS\n"); + return (0); +} diff --git a/test/stress_cpgfdget.c b/test/stress_cpgfdget.c new file mode 100644 index 0000000..af1357e --- /dev/null +++ b/test/stress_cpgfdget.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 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 <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <string.h> +#include <corosync/corotypes.h> +#include <corosync/cpg.h> +#include <signal.h> + +struct my_msg { + unsigned int msg_size; + unsigned char sha1[20]; + unsigned char buffer[0]; +}; + +static void cpg_deliver_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *m, + size_t msg_len) +{ +} + +static void cpg_confchg_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ +} + +static cpg_callbacks_t callbacks = { + cpg_deliver_fn, + cpg_confchg_fn +}; + +static void sigintr_handler (int num) +{ + exit (1); +} + + +#define ITERATIONS (1000*2000) + +int main (void) +{ + cpg_handle_t handle; + cs_error_t res; + int original_fd; + int i; + int fd; + + signal (SIGINT, sigintr_handler); + res = cpg_initialize (&handle, &callbacks); + if (res != CS_OK) { + printf ("FAIL %d\n", res); + exit (-1); + } + + res = cpg_fd_get (handle, &original_fd); + if (res != CS_OK) { + printf ("FAIL %d\n", res); + } + for (i = 0; i < ITERATIONS; i++) { + res = cpg_fd_get (handle, &fd); + if (original_fd != fd) { + printf ("FAIL\n"); + exit (-1); + } + } + + cpg_finalize (handle); + + printf ("PASS\n"); + return (0); +} diff --git a/test/stress_cpgzc.c b/test/stress_cpgzc.c new file mode 100644 index 0000000..ba9499b --- /dev/null +++ b/test/stress_cpgzc.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 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 <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <string.h> +#include <corosync/corotypes.h> +#include <corosync/cpg.h> +#include <signal.h> +#include <assert.h> + +struct my_msg { + unsigned int msg_size; + unsigned char sha1[20]; + unsigned char buffer[0]; +}; + +static int deliveries = 0; +static void cpg_deliver_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *m, + size_t msg_len) +{ + deliveries++; +} + +static void cpg_confchg_fn ( + cpg_handle_t handle, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ +} + +static cpg_callbacks_t callbacks = { + cpg_deliver_fn, + cpg_confchg_fn +}; + +static void sigintr_handler (int num) +{ + exit (1); +} + +#define ITERATIONS 100 +#define ALLOCATIONS 2000 +#define MAX_SIZE 100000 +int main (void) +{ + cs_error_t res; + cpg_handle_t handle; + size_t buffer_lens[ALLOCATIONS]; + void *buffers[ALLOCATIONS]; + int i, j; + + printf ("stress cpgzc running %d allocations for %d iterations\n", + ALLOCATIONS, ITERATIONS); + + signal (SIGINT, sigintr_handler); + + res = cpg_initialize (&handle, &callbacks); + if (res != CS_OK) { + printf ("FAIL %d\n", res); + exit (-1); + } + + for (j = 0; j < ITERATIONS; j++) { + for (i = 0; i < ALLOCATIONS; i++) { + buffer_lens[i] = (random() % MAX_SIZE) + 1; + res = cpg_zcb_alloc ( + handle, + buffer_lens[i], + &buffers[i]); + if (res != CS_OK) { + printf ("FAIL %d\n", res); + exit (-1); + } + } + + for (i = 0; i < ALLOCATIONS; i++) { + res = cpg_zcb_free ( + handle, + buffers[i]); + if (res != CS_OK) { + printf ("FAIL %d\n", res); + exit (-1); + } + } + + if ((j != 0) && + (j % 20) == 0) { + printf ("iteration %d\n", j); + } + } + + cpg_finalize (handle); + + printf ("PASS\n"); + exit (0); +} diff --git a/test/testcfg.c b/test/testcfg.c new file mode 100644 index 0000000..fa98cc2 --- /dev/null +++ b/test/testcfg.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021 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. + */ + +#include <config.h> + +#include <inttypes.h> +#include <stdio.h> +#include <errno.h> +#include <pthread.h> + +#include <corosync/corotypes.h> +#include <corosync/cfg.h> + +static void shutdown_callback(corosync_cfg_handle_t handle, corosync_cfg_shutdown_flags_t flags) +{ + /* Prevent shutdown */ + printf("In shutdown callback - denying corosync shutdown\n"); + corosync_cfg_replyto_shutdown(handle, COROSYNC_CFG_SHUTDOWN_FLAG_NO); +} + +static void *dispatch_thread(void *arg) +{ + corosync_cfg_handle_t handle = (corosync_cfg_handle_t) arg; + int res = CS_OK; + while (res == CS_OK) { + res = corosync_cfg_dispatch(handle, CS_DISPATCH_ONE); + } + fprintf(stderr, "ERROR: Corosync shut down\n"); + return (void*)0; +} + + +int main (int argc, char *argv[]) { + corosync_cfg_handle_t cfg_handle; + corosync_cfg_handle_t cfg_handle1; + unsigned int local_nodeid; + int i; + int res; + struct corosync_cfg_node_status_v1 ns; + pthread_t thread; + corosync_cfg_callbacks_t callbacks = { + .corosync_cfg_shutdown_callback = shutdown_callback + }; + + res = corosync_cfg_initialize(&cfg_handle, &callbacks); + if (res != CS_OK) { + fprintf(stderr, "corosync_Cfg_initialize(0) failed: %d\n", res); + return 1; + } + + /* Start a new handle & thread to prevent the shutdown we request later on */ + res = corosync_cfg_initialize(&cfg_handle1, &callbacks); + if (res != CS_OK) { + fprintf(stderr, "corosync_cfg_initialize(1) failed: %d\n", res); + return 1; + } + res = corosync_cfg_trackstart(cfg_handle1, 0); + if (res != CS_OK) { + fprintf(stderr, "corosync_cfg_initialize(1) failed: %d\n", res); + return 1; + } + res = pthread_create(&thread, NULL, dispatch_thread, (void*)cfg_handle1); + if (res != 0) { + perror("pthread_create failed"); + return 1; + } + + /* Exercise a few functions */ + res = corosync_cfg_local_get(cfg_handle, &local_nodeid); + if (res != CS_OK) { + fprintf(stderr, "corosync_cfg_local_get failed: %d\n", res); + return 1; + } + + printf("Local nodeid is %d\n", local_nodeid); + + /* + * Test node_status_get. + * node status for the local node looks odd (cos it's the loopback connection), so + * we try for a node ID one less or more than us just to get output that looks + * sensible to the user. + */ + res = corosync_cfg_node_status_get(cfg_handle, local_nodeid-1, CFG_NODE_STATUS_V1, &ns); + if (res != CS_OK) { + res = corosync_cfg_node_status_get(cfg_handle, local_nodeid+1, CFG_NODE_STATUS_V1, &ns); + } + if (res != CS_OK) { + fprintf(stderr, "corosync_cfg_node_status_get failed: %d\n", res); + return 1; + } + printf("Node Status for nodeid %d\n", ns.nodeid); + printf(" reachable: %d\n", ns.reachable); + printf(" remote: %d\n", ns.remote); + printf(" onwire_min: %d\n", ns.onwire_min); + printf(" onwire_max: %d\n", ns.onwire_max); + printf(" onwire_ver: %d\n", ns.onwire_ver); + for (i = 0; i<CFG_MAX_LINKS; i++) { + if (ns.link_status[i].enabled) { + printf(" Link %d\n", i); + printf(" connected: %d\n", ns.link_status[i].connected); + printf(" mtu: %d\n", ns.link_status[i].mtu); + printf(" src: %s\n", ns.link_status[i].src_ipaddr); + printf(" dst: %s\n", ns.link_status[i].dst_ipaddr); + } + } + + /* This shutdown request should be denied by the thread */ + res = corosync_cfg_try_shutdown(cfg_handle, COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST); + + if (res == CS_OK) { + fprintf(stderr, "ERROR: corosync_cfg_try_shutdown suceeded. should have been prevented\n"); + } + if (res != CS_ERR_BUSY && res != CS_OK) { + fprintf(stderr, "corosync_cfg_try_shutdown failed: %d\n", res); + return 1; + } + + /* + * Test bug presented in 3.1.1 and 3.1.2 that makes trackstop blocks forever + */ + res = corosync_cfg_trackstop(cfg_handle1); + if (res != CS_OK) { + fprintf(stderr, "corosync_cfg_trackstop failed: %d\n", res); + return 1; + } + + return 0; +} diff --git a/test/testcpg.c b/test/testcpg.c new file mode 100644 index 0000000..68c2929 --- /dev/null +++ b/test/testcpg.c @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2006-2009 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. + */ + +#include <config.h> + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <time.h> +#include <sys/time.h> +#include <assert.h> +#include <limits.h> + +#include <corosync/corotypes.h> +#include <corosync/cpg.h> +#include <corosync/swab.h> + +#ifdef QBLOG +#include <qb/qblog.h> +#endif + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX +#endif + +static int quit = 0; +static int show_ip = 0; +static int restart = 0; +static uint32_t nodeidStart = 0; + +static void print_localnodeid(cpg_handle_t handle); + +static void print_cpgname (const struct cpg_name *name) +{ + unsigned int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +static char * node_pid_format(unsigned int nodeid, unsigned int pid) { + static char buffer[100]; + if (show_ip) { + struct in_addr saddr; +#if __BYTE_ORDER == __LITTLE_ENDIAN + saddr.s_addr = swab32(nodeid); +#else + saddr.s_addr = nodeid; +#endif + sprintf(buffer, "node/pid %s/%d", inet_ntoa(saddr),pid); + } + else { + sprintf(buffer, "node/pid " CS_PRI_NODE_ID "/%d", nodeid, pid); + } + return buffer; +} + +static void +print_time(void) +{ +#define MAXLEN (256) + char buf[MAXLEN]; + char hostname[HOST_NAME_MAX]; + struct timeval tnow; + time_t t; + size_t len; + char *s = buf; + + len = sizeof(hostname); + if(gethostname(hostname, len) == 0) { + char *longName; + hostname[len-1] = '\0'; + longName = hostname; + if( (longName = strstr( hostname, "." )) != NULL ) + *longName = '\0'; + } + + strcpy(s, hostname); + s += strlen(hostname); + s += snprintf(s, sizeof(buf)-(s-buf), ":%d", getpid()); + t = time(0); + gettimeofday( &tnow, 0 ); + s += strftime(s, sizeof(buf)-(s-buf) , " %Y-%m-%d %T", localtime(&t)); + s += snprintf(s, sizeof(buf)-(s-buf), ".%03ld", tnow.tv_usec/1000); + assert(s-buf < (int)sizeof(buf)); + printf("%s\n", buf); +} + + +static void DeliverCallback ( + cpg_handle_t handle, + const struct cpg_name *groupName, + uint32_t nodeid, + uint32_t pid, + void *msg, + size_t msg_len) +{ + print_time(); + printf("DeliverCallback: message (len=%lu)from %s: '%s'\n", + (unsigned long int) msg_len, node_pid_format(nodeid, pid), + (const char *)msg); +} + +static void ConfchgCallback ( + cpg_handle_t handle, + const struct cpg_name *groupName, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ + unsigned int i; + int result; + uint32_t nodeid; + + print_time(); + printf("ConfchgCallback: group '"); + print_cpgname(groupName); + printf("'\n"); + print_localnodeid(handle); + + for (i=0; i<joined_list_entries; i++) { + printf("joined %s reason: %d\n", + node_pid_format(joined_list[i].nodeid, joined_list[i].pid), + joined_list[i].reason); + } + + for (i=0; i<left_list_entries; i++) { + printf("left %s reason: %d\n", + node_pid_format(left_list[i].nodeid, left_list[i].pid), + left_list[i].reason); + } + + printf("nodes in group now %lu\n", + (unsigned long int) member_list_entries); + for (i=0; i<member_list_entries; i++) { + printf("%s\n", + node_pid_format(member_list[i].nodeid, member_list[i].pid)); + } + + result = cpg_local_get(handle, &nodeid); + if(result != CS_OK) { + printf("failed to get local nodeid %d\n", result); + nodeid = 0; + } + /* Is it us?? + NOTE: in reality we should also check the nodeid */ + if (left_list_entries && (pid_t)left_list[0].pid == getpid()) { + printf("We might have left the building pid %d\n", left_list[0].pid); + /* can only use nodeidStart as a reliable check (version <= 1.4.2) */ + if(nodeidStart) { + /* report dynamic nature of nodeid returned from local_get */ + /* local get of nodeid might change identity from original! */ + if(htonl((uint32_t)nodeid) == INADDR_LOOPBACK) { + printf("We probably left the building switched identity? start nodeid " CS_PRI_NODE_ID " nodeid " CS_PRI_NODE_ID " current nodeid " CS_PRI_NODE_ID " pid %d\n", nodeidStart, left_list[0].nodeid, nodeid, left_list[0].pid); + } else if(htonl((uint32_t)left_list[0].nodeid) == INADDR_LOOPBACK) { + printf("We probably left the building started alone? start nodeid " CS_PRI_NODE_ID " nodeid " CS_PRI_NODE_ID " current nodeid " CS_PRI_NODE_ID " pid %d\n", nodeidStart, left_list[0].nodeid, nodeid, left_list[0].pid); + } + /* a possibly reliable way to check is based on original address */ + if(left_list[0].nodeid == nodeidStart) { + printf("We have left the building direct match start nodeid " CS_PRI_NODE_ID " nodeid " CS_PRI_NODE_ID " local get current nodeid " CS_PRI_NODE_ID " pid %d\n", nodeidStart, left_list[0].nodeid, nodeid, left_list[0].pid); + // quit = 1; + restart = 1; + } else { + printf("Probably another node with matching pid start nodeid " CS_PRI_NODE_ID " nodeid " CS_PRI_NODE_ID " current nodeid " CS_PRI_NODE_ID " pid %d\n", nodeidStart, left_list[0].nodeid, nodeid, left_list[0].pid); + } + } + } +} + +static void TotemConfchgCallback ( + cpg_handle_t handle, + struct cpg_ring_id ring_id, + uint32_t member_list_entries, + const uint32_t *member_list) +{ + unsigned int i; + + printf("\n"); + print_time(); + printf ("TotemConfchgCallback: ringid (" CS_PRI_RING_ID ")\n", + ring_id.nodeid, ring_id.seq); + + printf("active processors %lu: ", + (unsigned long int) member_list_entries); + for (i=0; i<member_list_entries; i++) { + printf(CS_PRI_NODE_ID " ", member_list[i]); + } + printf ("\n"); +} + +static cpg_model_v1_data_t model_data = { + .cpg_deliver_fn = DeliverCallback, + .cpg_confchg_fn = ConfchgCallback, + .cpg_totem_confchg_fn = TotemConfchgCallback, + .flags = CPG_MODEL_V1_DELIVER_INITIAL_TOTEM_CONF, +}; + +static struct cpg_name group_name; + +#define retrybackoff(counter) { \ + counter++; \ + printf("Restart operation after %ds\n", counter); \ + sleep((unsigned int)counter); \ + restart = 1; \ + continue; \ +} + +#define cs_repeat_init(counter, max, code) do { \ + code; \ + if (result == CS_ERR_TRY_AGAIN || result == CS_ERR_QUEUE_FULL || result == CS_ERR_LIBRARY) { \ + counter++; \ + printf("Retrying operation after %ds\n", counter); \ + sleep((unsigned int)counter); \ + } else { \ + break; \ + } \ +} while (counter < max) + +#define cs_repeat(counter, max, code) do { \ + code; \ + if (result == CS_ERR_TRY_AGAIN || result == CS_ERR_QUEUE_FULL) { \ + counter++; \ + printf("Retrying operation after %ds\n", counter); \ + sleep((unsigned int)counter); \ + } else { \ + break; \ + } \ +} while (counter < max) + +static void print_localnodeid(cpg_handle_t handle) +{ + char addrStr[128]; + unsigned int retries; + unsigned int nodeid; + struct sockaddr_storage addr; + struct sockaddr_in *v4addr = (struct sockaddr_in *)&addr; + int result; + + retries = 0; + + cs_repeat(retries, 30, result = cpg_local_get(handle, &nodeid)); + if (result != CS_OK) { + printf ("Could not get local node id\n"); + } else { + v4addr->sin_addr.s_addr = nodeid; + if(inet_ntop(AF_INET, (const void *)&v4addr->sin_addr.s_addr, + addrStr, (socklen_t)sizeof(addrStr)) == NULL) { + addrStr[0] = 0; + } + printf ("Local node id is %s/" CS_PRI_NODE_ID " result %d\n", addrStr, nodeid, result); + } +} + +int main (int argc, char *argv[]) { + cpg_handle_t handle; + fd_set read_fds; + int select_fd; + int result; + int retries; + const char *options = "i"; + int opt; + unsigned int nodeid; + char *fgets_res; + struct cpg_address member_list[CPG_MEMBERS_MAX]; + int member_list_entries; + int i; + int recnt; + int doexit; + const char *exitStr = "EXIT"; + + doexit = 0; + +#ifdef QBLOG + qb_log_init("testcpg", LOG_USER, LOG_ERR); + qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE); + qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD, + QB_LOG_FILTER_FILE, "*", LOG_TRACE); + qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); + qb_log_format_set(QB_LOG_STDERR, "[%p] %f %b"); +#endif + + while ( (opt = getopt(argc, argv, options)) != -1 ) { + switch (opt) { + case 'i': + show_ip = 1; + break; + } + } + + if (argc > optind) { + if (strlen(argv[optind]) >= CPG_MAX_NAME_LENGTH) { + fprintf(stderr, "Invalid name for cpg group\n"); + return (1); + } + + strcpy(group_name.value, argv[optind]); + group_name.length = strlen(argv[optind]); + } + else { + strcpy(group_name.value, "GROUP"); + group_name.length = 6; + } + recnt = 0; + + printf ("Type %s to finish\n", exitStr); + restart = 1; + + do { + if(restart) { + restart = 0; + retries = 0; + cs_repeat_init(retries, 30, result = cpg_model_initialize (&handle, CPG_MODEL_V1, (cpg_model_data_t *)&model_data, NULL)); + if (result != CS_OK) { + printf ("Could not initialize Cluster Process Group API instance error %d\n", result); + retrybackoff(recnt); + } + retries = 0; + cs_repeat(retries, 30, result = cpg_local_get(handle, &nodeid)); + if (result != CS_OK) { + printf ("Could not get local node id\n"); + retrybackoff(recnt); + } + printf ("Local node id is " CS_PRI_NODE_ID "\n", nodeid); + nodeidStart = nodeid; + + retries = 0; + cs_repeat(retries, 30, result = cpg_join(handle, &group_name)); + if (result != CS_OK) { + printf ("Could not join process group, error %d\n", result); + retrybackoff(recnt); + } + + retries = 0; + cs_repeat(retries, 30, result = cpg_membership_get (handle, &group_name, + (struct cpg_address *)&member_list, &member_list_entries)); + if (result != CS_OK) { + printf ("Could not get current membership list %d\n", result); + retrybackoff(recnt); + } + recnt = 0; + + printf ("membership list\n"); + for (i = 0; i < member_list_entries; i++) { + printf ("node id " CS_PRI_NODE_ID " pid %d\n", member_list[i].nodeid, + member_list[i].pid); + } + + FD_ZERO (&read_fds); + cpg_fd_get(handle, &select_fd); + } + FD_SET (select_fd, &read_fds); + FD_SET (STDIN_FILENO, &read_fds); + result = select (select_fd + 1, &read_fds, 0, 0, 0); + if (result == -1) { + perror ("select\n"); + } + if (FD_ISSET (STDIN_FILENO, &read_fds)) { + char inbuf[132]; + struct iovec iov; + + fgets_res = fgets(inbuf, (int)sizeof(inbuf), stdin); + if (fgets_res == NULL) { + doexit = 1; + cpg_leave(handle, &group_name); + } + if (strncmp(inbuf, exitStr, strlen(exitStr)) == 0) { + doexit = 1; + cpg_leave(handle, &group_name); + } + else { + iov.iov_base = inbuf; + iov.iov_len = strlen(inbuf)+1; + cpg_mcast_joined(handle, CPG_TYPE_AGREED, &iov, 1); + } + } + if (FD_ISSET (select_fd, &read_fds)) { + if (cpg_dispatch (handle, CS_DISPATCH_ALL) != CS_OK) { + if(doexit) { + exit(1); + } + restart = 1; + } + } + if(restart) { + if(!doexit) { + result = cpg_finalize (handle); + printf ("Finalize+restart result is %d (should be 1)\n", result); + continue; + } + } + } while (result && !quit && !doexit); + + result = cpg_finalize (handle); + printf ("Finalize result is %d (should be 1)\n", result); + return (0); +} diff --git a/test/testcpg2.c b/test/testcpg2.c new file mode 100644 index 0000000..d779cf3 --- /dev/null +++ b/test/testcpg2.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2007, 2009 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Alan Conway <aconway@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 <config.h> + +#include <assert.h> +#include <stdio.h> +#include <poll.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> + +#include <corosync/corotypes.h> +#include <corosync/cpg.h> + +static void deliver( + cpg_handle_t handle, + const struct cpg_name *group_name, + uint32_t nodeid, + uint32_t pid, + void *msg, + size_t msg_len) +{ + printf("self delivered nodeid: " CS_PRI_NODE_ID "\n", nodeid); +} + +static void confch( + cpg_handle_t handle, + const struct cpg_name *group_name, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ + printf("confchg nodeid " CS_PRI_NODE_ID "\n", member_list[0].nodeid); +} + +int main(int argc, char** argv) { + cpg_handle_t handle=0; + cpg_callbacks_t cb={&deliver,&confch}; + unsigned int nodeid=0; + struct cpg_name group={3,"foo"}; + struct iovec msg={(void *)"hello", 5}; /* discard const */ + + struct pollfd pfd; + int fd; + + printf ("All of the nodeids should match on a single node configuration\n for the test to pass."); + assert(CS_OK==cpg_initialize(&handle, &cb)); + assert(CS_OK==cpg_local_get(handle,&nodeid)); + printf("local_get: " CS_PRI_NODE_ID "\n", nodeid); + assert(CS_OK==cpg_join(handle, &group)); + assert(CS_OK==cpg_mcast_joined(handle,CPG_TYPE_AGREED,&msg,1)); + cpg_fd_get (handle, &fd); + pfd.fd = fd; + pfd.events = POLLIN; + + assert(poll (&pfd, 1, 1000) == 1); + assert(cpg_dispatch(handle, CS_DISPATCH_ALL) == CS_OK); + return (0); +} diff --git a/test/testcpgzc.c b/test/testcpgzc.c new file mode 100644 index 0000000..6da36a1 --- /dev/null +++ b/test/testcpgzc.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2006-2009 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. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <corosync/corotypes.h> +#include <corosync/cpg.h> + +#define BUFFER_SIZE 8192 +#define DEFAULT_GROUP_NAME "GROUP" + +static int quit = 0; +static int show_ip = 0; + +static void print_cpgname (const struct cpg_name *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +static void DeliverCallback ( + cpg_handle_t handle, + const struct cpg_name *groupName, + uint32_t nodeid, + uint32_t pid, + void *msg, + size_t msg_len) +{ + if (show_ip) { + struct in_addr saddr; + saddr.s_addr = nodeid; + printf("DeliverCallback: message (len=%lu)from node/pid %s/%d: '%s'\n", + (unsigned long int) msg_len, + inet_ntoa(saddr), pid, (const char *)msg); + } + else { + printf("DeliverCallback: message (len=%lu)from node/pid " CS_PRI_NODE_ID "/%d: '%s'\n", + (unsigned long int) msg_len, nodeid, pid, + (const char *)msg); + } +} + +static void ConfchgCallback ( + cpg_handle_t handle, + const struct cpg_name *groupName, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ + int i; + struct in_addr saddr; + + printf("\nConfchgCallback: group '"); + print_cpgname(groupName); + printf("'\n"); + for (i=0; i<joined_list_entries; i++) { + if (show_ip) { + saddr.s_addr = joined_list[i].nodeid; + printf("joined node/pid: %s/%d reason: %d\n", + inet_ntoa (saddr), joined_list[i].pid, + joined_list[i].reason); + } + else { + printf("joined node/pid: " CS_PRI_NODE_ID "/%d reason: %d\n", + joined_list[i].nodeid, joined_list[i].pid, + joined_list[i].reason); + } + } + + for (i=0; i<left_list_entries; i++) { + if (show_ip) { + saddr.s_addr = left_list[i].nodeid; + printf("left node/pid: %s/%d reason: %d\n", + inet_ntoa (saddr), left_list[i].pid, + left_list[i].reason); + } + else { + printf("left node/pid: " CS_PRI_NODE_ID "/%d reason: %d\n", + left_list[i].nodeid, left_list[i].pid, + left_list[i].reason); + } + } + + printf("nodes in group now %lu\n", + (unsigned long int) member_list_entries); + for (i=0; i<member_list_entries; i++) { + if (show_ip) { + saddr.s_addr = member_list[i].nodeid; + printf("node/pid: %s/%d\n", + inet_ntoa (saddr), member_list[i].pid); + } + else { + printf("node/pid: " CS_PRI_NODE_ID "/%d\n", + member_list[i].nodeid, member_list[i].pid); + } + } + + /* Is it us?? + NOTE: in reality we should also check the nodeid */ + if (left_list_entries && left_list[0].pid == getpid()) { + printf("We have left the building\n"); + quit = 1; + } +} + +static cpg_callbacks_t callbacks = { + .cpg_deliver_fn = DeliverCallback, + .cpg_confchg_fn = ConfchgCallback, +}; + +static struct cpg_name group_name; + +int main (int argc, char *argv[]) { + cpg_handle_t handle; + fd_set read_fds; + int select_fd; + int result; + const char *options = "i"; + int opt; + unsigned int nodeid; + char *fgets_res; + void *buffer; + + while ( (opt = getopt(argc, argv, options)) != -1 ) { + switch (opt) { + case 'i': + show_ip = 1; + break; + } + } + + if (argc > optind) { + if (strlen(argv[optind]) >= CPG_MAX_NAME_LENGTH) { + fprintf(stderr, "Invalid name for cpg group\n"); + return (1); + } + + strcpy(group_name.value, argv[optind]); + group_name.length = strlen(argv[optind])+1; + } + else { + strcpy(group_name.value, DEFAULT_GROUP_NAME); + group_name.length = strlen(DEFAULT_GROUP_NAME) + 1; + } + + result = cpg_initialize (&handle, &callbacks); + if (result != CS_OK) { + printf ("Could not initialize Cluster Process Group API instance error %d\n", result); + exit (1); + } + cpg_zcb_alloc (handle, BUFFER_SIZE, &buffer); + cpg_zcb_free (handle, buffer); + cpg_zcb_alloc (handle, BUFFER_SIZE, &buffer); + + result = cpg_local_get (handle, &nodeid); + if (result != CS_OK) { + printf ("Could not get local node id\n"); + exit (1); + } + + printf ("Local node id is " CS_PRI_NODE_ID "\n", nodeid); + result = cpg_join(handle, &group_name); + if (result != CS_OK) { + printf ("Could not join process group, error %d\n", result); + exit (1); + } + + FD_ZERO (&read_fds); + cpg_fd_get(handle, &select_fd); + printf ("Type EXIT to finish\n"); + do { + FD_SET (select_fd, &read_fds); + FD_SET (STDIN_FILENO, &read_fds); + result = select (select_fd + 1, &read_fds, 0, 0, 0); + if (result == -1) { + perror ("select\n"); + } + if (FD_ISSET (STDIN_FILENO, &read_fds)) { + fgets_res = fgets(buffer, BUFFER_SIZE, stdin); + if (fgets_res == NULL) { + cpg_leave(handle, &group_name); + } + if (strncmp(buffer, "EXIT", 4) == 0) { + cpg_leave(handle, &group_name); + } + else { + cpg_zcb_mcast_joined (handle, CPG_TYPE_AGREED, + buffer, strlen (buffer) + 1); + } + } + if (FD_ISSET (select_fd, &read_fds)) { + if (cpg_dispatch (handle, CS_DISPATCH_ALL) != CS_OK) + exit(1); + } + } while (result && !quit); + + + result = cpg_finalize (handle); + printf ("Finalize result is %d (should be 1)\n", result); + return (0); +} diff --git a/test/testquorum.c b/test/testquorum.c new file mode 100644 index 0000000..1323b25 --- /dev/null +++ b/test/testquorum.c @@ -0,0 +1,64 @@ +#include <config.h> + +#include <sys/types.h> +#include <stdio.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <corosync/corotypes.h> +#include <corosync/quorum.h> + +static quorum_handle_t g_handle; + +static void quorum_notification_fn( + quorum_handle_t handle, + uint32_t quorate, + uint64_t ring_id, + uint32_t view_list_entries, + uint32_t *view_list) +{ + int i; + + printf("quorum notification called \n"); + printf(" quorate = %lu\n", (long unsigned int) quorate); + printf(" ring id = " CS_PRI_RING_ID_SEQ "\n", ring_id); + printf(" num nodes = %lu ", (long unsigned int) view_list_entries); + + for (i=0; i<view_list_entries; i++) { + printf(" " CS_PRI_NODE_ID, view_list[i]); + } + printf("\n"); +} + + +int main(int argc, char *argv[]) +{ + int quorate; + quorum_callbacks_t callbacks; + uint32_t quorum_type; + int err; + + callbacks.quorum_notify_fn = quorum_notification_fn; + if ( (err=quorum_initialize(&g_handle, &callbacks, &quorum_type)) != CS_OK) + fprintf(stderr, "quorum_initialize FAILED: %d\n", err); + + if ( (err=quorum_trackstart(g_handle, CS_TRACK_CHANGES)) != CS_OK) + fprintf(stderr, "quorum_trackstart FAILED: %d\n", err); + + if ( (err=quorum_getquorate(g_handle, &quorate)) != CS_OK) + fprintf(stderr, "quorum_getquorate FAILED: %d\n", err); + else { + printf("quorate %d\n", quorate); + } + + printf("Waiting for quorum events, press ^C to finish\n"); + printf("-------------------\n"); + + if (quorum_dispatch(g_handle, CS_DISPATCH_BLOCKING) != CS_OK) { + fprintf(stderr, "Error from quorum_dispatch\n"); + return -1; + } + + return 0; +} diff --git a/test/testquorummodel.c b/test/testquorummodel.c new file mode 100644 index 0000000..94ff869 --- /dev/null +++ b/test/testquorummodel.c @@ -0,0 +1,102 @@ +#include <config.h> + +#include <sys/types.h> +#include <stdio.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <corosync/corotypes.h> +#include <corosync/quorum.h> + +static quorum_handle_t g_handle; + +static void quorum_notification_fn( + quorum_handle_t handle, + uint32_t quorate, + struct quorum_ring_id ring_id, + uint32_t view_list_entries, + const uint32_t *view_list) +{ + int i; + + printf("quorum notification called \n"); + printf(" quorate = %lu\n", (long unsigned int) quorate); + printf(" ring id = " CS_PRI_RING_ID "\n", ring_id.nodeid, ring_id.seq); + printf(" num nodes = %lu ", (long unsigned int) view_list_entries); + + for (i=0; i<view_list_entries; i++) { + printf(" " CS_PRI_NODE_ID, view_list[i]); + } + printf("\n"); +} + +static void nodelist_notification_fn( + quorum_handle_t handle, + struct quorum_ring_id ring_id, + uint32_t member_list_entries, const uint32_t *member_list, + uint32_t joined_list_entries, const uint32_t *joined_list, + uint32_t left_list_entries, const uint32_t *left_list) +{ + int i; + + printf("nodelist notification called \n"); + printf(" ring id = " CS_PRI_RING_ID "\n", ring_id.nodeid, ring_id.seq); + printf(" num members = %" PRIu32 " ", member_list_entries); + + for (i=0; i<member_list_entries; i++) { + printf(" " CS_PRI_NODE_ID, member_list[i]); + } + printf("\n"); + + printf(" num joined members = %" PRIu32 " ", joined_list_entries); + for (i=0; i<joined_list_entries; i++) { + printf(" " CS_PRI_NODE_ID, joined_list[i]); + } + printf("\n"); + + printf(" num left members = %" PRIu32 " ", left_list_entries); + for (i=0; i<left_list_entries; i++) { + printf(" " CS_PRI_NODE_ID, left_list[i]); + } + printf("\n"); + +} + +int main(int argc, char *argv[]) +{ + int quorate; + quorum_model_v1_data_t model_data; + uint32_t quorum_type; + int err; + + memset(&model_data, 0, sizeof(model_data)); + model_data.quorum_notify_fn = quorum_notification_fn; + model_data.nodelist_notify_fn = nodelist_notification_fn; + + if ( (err=quorum_model_initialize (&g_handle, QUORUM_MODEL_V1, + (quorum_model_data_t *)&model_data, &quorum_type, NULL)) != CS_OK) { + fprintf(stderr, "quorum_initialize FAILED: %d\n", err); + exit(1); + } + + if ( (err=quorum_trackstart(g_handle, CS_TRACK_CHANGES)) != CS_OK) + fprintf(stderr, "quorum_trackstart FAILED: %d\n", err); + + if ( (err=quorum_getquorate(g_handle, &quorate)) != CS_OK) + fprintf(stderr, "quorum_getquorate FAILED: %d\n", err); + else { + printf("quorate %d\n", quorate); + } + + printf("Waiting for quorum events, press ^C to finish\n"); + printf("-------------------\n"); + + if (quorum_dispatch(g_handle, CS_DISPATCH_BLOCKING) != CS_OK) { + fprintf(stderr, "Error from quorum_dispatch\n"); + return -1; + } + + return 0; +} diff --git a/test/testsam.c b/test/testsam.c new file mode 100644 index 0000000..d31262a --- /dev/null +++ b/test/testsam.c @@ -0,0 +1,1476 @@ +/* + * Copyright (c) 2009-2011 Red Hat, Inc. + * + * All rights reserved. + * + * 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 Red Hat, 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 test of SAM API + */ + +#include <config.h> + +#include <limits.h> +#include <pthread.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <corosync/corotypes.h> +#include <corosync/sam.h> +#include <signal.h> +#include <string.h> +#include <sys/wait.h> +#include <corosync/cmap.h> +extern const char *__progname; + +static int test2_sig_delivered = 0; +static int test5_hc_cb_count = 0; +static int test6_sig_delivered = 0; + +/* + * First test will just register SAM, with policy restart. First instance will + * sleep one second, send hc and sleep another 3 seconds. This should force restart. + * Second instance will sleep one second, send hc, stop hc and sleep 3 seconds. + * Then start hc again and sleep 3 seconds. This should force restart again. + * Last instance just calls initialize again. This should end with error. + * Then call start, followed by stop and start again. Finally, we will call finalize + * twice. One should succeed, second should fail. After this, we will call every function + * (none should succeed). + */ +static int test1 (void) +{ + cs_error_t error; + unsigned int instance_id; + int i; + + printf ("%s: initialize\n", __FUNCTION__); + error = sam_initialize (2000, SAM_RECOVERY_POLICY_RESTART); + if (error != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", error); + return 1; + } + printf ("%s: register\n", __FUNCTION__); + error = sam_register (&instance_id); + if (error != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", error); + return 1; + } + + if (instance_id == 1 || instance_id == 2) { + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + error = sam_start (); + if (error != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", error); + return 1; + } + + for (i = 0; i < 10; i++) { + printf ("%s iid %d: sleep 1\n", __FUNCTION__, instance_id); + sleep (1); + + printf ("%s iid %d: hc send\n", __FUNCTION__, instance_id); + error = sam_hc_send (); + if (error != CS_OK) { + fprintf (stderr, "Can't send hc. Error %d\n", error); + return 1; + } + } + + if (instance_id == 2) { + printf ("%s iid %d: stop\n", __FUNCTION__, instance_id); + error = sam_stop (); + + if (error != CS_OK) { + fprintf (stderr, "Can't send hc. Error %d\n", error); + return 1; + } + } + + printf ("%s iid %d: sleep 3\n", __FUNCTION__, instance_id); + sleep (3); + + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + error = sam_start (); + if (error != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", error); + return 1; + } + + printf ("%s iid %d: sleep 3\n", __FUNCTION__, instance_id); + sleep (3); + return 0; + } + + if (instance_id == 3) { + error = sam_initialize (2000, SAM_RECOVERY_POLICY_RESTART); + if (error == CS_OK) { + fprintf (stderr, "Can initialize SAM API after initialization"); + return 1; + } + + error = sam_start (); + if (error != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", error); + return 1; + } + error = sam_stop (); + if (error != CS_OK) { + fprintf (stderr, "Can't stop hc. Error %d\n", error); + return 1; + } + error = sam_finalize (); + if (error != CS_OK) { + fprintf (stderr, "Can't finalize sam. Error %d\n", error); + return 1; + } + error = sam_finalize (); + if (error == CS_OK) { + fprintf (stderr, "Can finalize sam after finalization!\n"); + return 1; + } + + if (sam_initialize (2, SAM_RECOVERY_POLICY_RESTART) == CS_OK || + sam_start () == CS_OK || sam_stop () == CS_OK || + sam_register (NULL) == CS_OK || sam_hc_send () == CS_OK || + sam_hc_callback_register (NULL) == CS_OK) { + + fprintf (stderr, "Can call one of function after finalization!\n"); + + return 1; + } + + return 0; + } + + return 1; +} + + +static void test2_signal (int sig) { + printf ("%s\n", __FUNCTION__); + + test2_sig_delivered = 1; +} + +/* + * This tests recovery policy quit and callback. + */ +static int test2 (void) { + cs_error_t error; + unsigned int instance_id; + + printf ("%s: initialize\n", __FUNCTION__); + error = sam_initialize (2000, SAM_RECOVERY_POLICY_QUIT); + if (error != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", error); + return 1; + } + printf ("%s: register\n", __FUNCTION__); + error = sam_register (&instance_id); + if (error != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", error); + return 1; + } + + if (instance_id == 1) { + signal (SIGTERM, test2_signal); + + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + error = sam_start (); + if (error != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", error); + return 1; + } + + printf ("%s iid %d: sleep 1\n", __FUNCTION__, instance_id); + sleep (1); + + printf ("%s iid %d: hc send\n", __FUNCTION__, instance_id); + error = sam_hc_send (); + if (error != CS_OK) { + fprintf (stderr, "Can't send hc. Error %d\n", error); + return 1; + } + + + printf ("%s iid %d: wait for delivery of signal\n", __FUNCTION__, instance_id); + while (!test2_sig_delivered) { + sleep (1); + } + + printf ("%s iid %d: wait for real kill\n", __FUNCTION__, instance_id); + + sleep (3); + } + + return 1; + +} + +/* + * Smoke test. Better to turn off coredump ;) This has no time limit, just restart process + * when it dies. + */ +static int test3 (void) { + cs_error_t error; + unsigned int instance_id; + + printf ("%s: initialize\n", __FUNCTION__); + error = sam_initialize (0, SAM_RECOVERY_POLICY_RESTART); + if (error != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", error); + return 1; + } + printf ("%s: register\n", __FUNCTION__); + error = sam_register (&instance_id); + if (error != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", error); + return 1; + } + + if (instance_id < 100) { + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + error = sam_start (); + if (error != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", error); + return 1; + } + + printf ("%s iid %d: Sending signal\n", __FUNCTION__, instance_id); + kill(getpid(), SIGSEGV); + return 1; + } + + return 0; + +} + +/* + * Test sam_data_store, sam_data_restore and sam_data_getsize + */ +static int test4 (void) +{ + size_t size; + cs_error_t err; + int i; + unsigned int instance_id; + char saved_data[128]; + char saved_data2[128]; + + printf ("%s: sam_data_getsize 1\n", __FUNCTION__); + err = sam_data_getsize (&size); + if (err != CS_ERR_BAD_HANDLE) { + fprintf (stderr, "Test should return CS_ERR_BAD_HANDLE. Error returned %d\n", err); + return 1; + } + + printf ("%s: sam_data_getsize 2\n", __FUNCTION__); + err = sam_data_getsize (NULL); + if (err != CS_ERR_INVALID_PARAM) { + fprintf (stderr, "Test should return CS_ERR_INVALID_PARAM. Error returned %d\n", err); + return 1; + } + + printf ("%s: sam_data_store 1\n", __FUNCTION__); + err = sam_data_store (NULL, 0); + if (err != CS_ERR_BAD_HANDLE) { + fprintf (stderr, "Test should return CS_ERR_BAD_HANDLE. Error returned %d\n", err); + return 1; + } + + printf ("%s: sam_data_restore 1\n", __FUNCTION__); + err = sam_data_restore (saved_data, sizeof (saved_data)); + if (err != CS_ERR_BAD_HANDLE) { + fprintf (stderr, "Test should return CS_ERR_BAD_HANDLE. Error returned %d\n", err); + return 1; + } + + printf ("%s: sam_initialize\n", __FUNCTION__); + err = sam_initialize (0, SAM_RECOVERY_POLICY_RESTART); + if (err != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", err); + return 1; + } + + printf ("%s: sam_data_getsize 3\n", __FUNCTION__); + err = sam_data_getsize (&size); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_ERR_BAD_HANDLE. Error returned %d\n", err); + return 1; + } + if (size != 0) { + fprintf (stderr, "Test should return size of 0. Returned %zx\n", size); + return 1; + } + + printf ("%s: sam_data_restore 2\n", __FUNCTION__); + err = sam_data_restore (NULL, sizeof (saved_data)); + if (err != CS_ERR_INVALID_PARAM) { + fprintf (stderr, "Test should return CS_ERR_INVALID_PARAM. Error returned %d\n", err); + return 1; + } + + /* + * Store some real data + */ + for (i = 0; i < sizeof (saved_data); i++) { + saved_data[i] = (char)(i + 5); + } + + printf ("%s: sam_data_store 2\n", __FUNCTION__); + err = sam_data_store (saved_data, sizeof (saved_data)); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + + printf ("%s: sam_data_getsize 4\n", __FUNCTION__); + err = sam_data_getsize (&size); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + if (size != sizeof (saved_data)) { + fprintf (stderr, "Test should return size of 0. Returned %zx\n", size); + return 1; + } + + printf ("%s: sam_data_restore 3\n", __FUNCTION__); + err = sam_data_restore (saved_data2, sizeof (saved_data2) - 1); + if (err != CS_ERR_INVALID_PARAM) { + fprintf (stderr, "Test should return CS_ERR_INVALID_PARAM. Error returned %d\n", err); + return 1; + } + + printf ("%s: sam_data_restore 4\n", __FUNCTION__); + err = sam_data_restore (saved_data2, sizeof (saved_data2)); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + + if (memcmp (saved_data, saved_data2, sizeof (saved_data2)) != 0) { + fprintf (stderr, "Retored data are not same\n"); + return 1; + } + + memset (saved_data2, 0, sizeof (saved_data2)); + + printf ("%s: sam_data_store 3\n", __FUNCTION__); + err = sam_data_store (NULL, 1); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + + printf ("%s: sam_data_getsize 5\n", __FUNCTION__); + err = sam_data_getsize (&size); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + if (size != 0) { + fprintf (stderr, "Test should return size of 0. Returned %zx\n", size); + return 1; + } + + printf ("%s: sam_data_store 4\n", __FUNCTION__); + err = sam_data_store (saved_data, sizeof (saved_data)); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + + printf ("%s: register\n", __FUNCTION__); + err = sam_register (&instance_id); + if (err != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", err); + return 1; + } + + if (instance_id == 1) { + printf ("%s iid %d: sam_start\n", __FUNCTION__, instance_id); + err = sam_start (); + if (err != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", err); + return 1; + } + + printf ("%s iid %d: sam_data_getsize 6\n", __FUNCTION__, instance_id); + err = sam_data_getsize (&size); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + if (size != sizeof (saved_data2)) { + fprintf (stderr, "Test should return size of 0. Returned %zx\n", size); + return 1; + } + + printf ("%s iid %d: sam_data_restore 5\n", __FUNCTION__, instance_id); + err = sam_data_restore (saved_data2, sizeof (saved_data2)); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + + if (memcmp (saved_data, saved_data2, sizeof (saved_data2)) != 0) { + fprintf (stderr, "Retored data are not same\n"); + return 1; + } + + for (i = 0; i < sizeof (saved_data); i++) { + saved_data[i] = (char)(i - 5); + } + + printf ("%s iid %d: sam_data_store 5\n", __FUNCTION__, instance_id); + err = sam_data_store (saved_data, sizeof (saved_data) - 7); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + + exit (1); + } + + if (instance_id == 2) { + printf ("%s iid %d: sam_start\n", __FUNCTION__, instance_id); + err = sam_start (); + if (err != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", err); + return 1; + } + + printf ("%s iid %d: sam_data_getsize 7\n", __FUNCTION__, instance_id); + err = sam_data_getsize (&size); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + if (size != sizeof (saved_data2) - 7) { + fprintf (stderr, "Test should return size of 0. Returned %zx\n", size); + return 1; + } + + printf ("%s iid %d: sam_data_restore 6\n", __FUNCTION__, instance_id); + err = sam_data_restore (saved_data2, sizeof (saved_data2)); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + + for (i = 0; i < sizeof (saved_data); i++) { + saved_data[i] = (char)(i - 5); + } + + if (memcmp (saved_data, saved_data2, sizeof (saved_data2) - 7) != 0) { + fprintf (stderr, "Retored data are not same\n"); + return 1; + } + + printf ("%s iid %d: sam_data_store 6\n", __FUNCTION__, instance_id); + err = sam_data_store (NULL, 0); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + + exit (1); + } + + if (instance_id == 3) { + printf ("%s iid %d: sam_data_getsize 8\n", __FUNCTION__, instance_id); + err = sam_data_getsize (&size); + if (err != CS_OK) { + fprintf (stderr, "Test should return CS_OK. Error returned %d\n", err); + return 1; + } + if (size != 0) { + fprintf (stderr, "Test should return size of 0. Returned %zx\n", size); + return 1; + } + } + + return (0); +} + +static int test5_hc_cb (void) +{ + cs_error_t res; + printf ("%s %d\n", __FUNCTION__, ++test5_hc_cb_count); + + res = sam_data_store (&test5_hc_cb_count, sizeof (test5_hc_cb_count)); + if (res != CS_OK) + return 1; + + if (test5_hc_cb_count > 10) + return 1; + + return 0; +} +/* + * Test event driven healtchecking. + */ +static int test5 (void) +{ + cs_error_t error; + unsigned int instance_id; + int hc_cb_count; + + printf ("%s: initialize\n", __FUNCTION__); + error = sam_initialize (100, SAM_RECOVERY_POLICY_RESTART); + if (error != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", error); + return 1; + } + printf ("%s: register\n", __FUNCTION__); + error = sam_register (&instance_id); + if (error != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", error); + return 1; + } + + if (instance_id == 1) { + printf ("%s iid %d: hc callback register\n", __FUNCTION__, instance_id); + error = sam_hc_callback_register (test5_hc_cb); + if (error != CS_OK) { + fprintf (stderr, "Can't register hc cb. Error %d\n", error); + return 1; + } + + + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + error = sam_start (); + if (error != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", error); + return 1; + } + + sleep (2); + + printf ("%s iid %d: Failed. Wasn't killed.\n", __FUNCTION__, instance_id); + return 1; + } + + if (instance_id == 2) { + error = sam_data_restore (&hc_cb_count, sizeof (hc_cb_count)); + if (error != CS_OK) { + fprintf (stderr, "sam_data_restore should return CS_OK. Error returned %d\n", error); + return 1; + } + + if (hc_cb_count != 11) { + fprintf (stderr, "%s iid %d: Premature killed. hc_cb_count should be 11 and it is %d\n", + __FUNCTION__, instance_id - 1, hc_cb_count); + return 1; + + } + return 0; + } + + return 1; +} + +static void test6_signal (int sig) { + cs_error_t error; + + printf ("%s\n", __FUNCTION__); + test6_sig_delivered++; + + if ((error = sam_data_store (&test6_sig_delivered, sizeof (test6_sig_delivered))) != CS_OK) { + fprintf (stderr, "Can't store data! Error : %d\n", error); + } +} + +/* + * Test warn signal set. + */ +static int test6 (void) { + cs_error_t error; + unsigned int instance_id; + int test6_sig_del; + + printf ("%s: initialize\n", __FUNCTION__); + error = sam_initialize (2000, SAM_RECOVERY_POLICY_RESTART); + if (error != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", error); + return 1; + } + printf ("%s: register\n", __FUNCTION__); + error = sam_register (&instance_id); + if (error != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", error); + return 1; + } + + if (instance_id == 1) { + error = sam_warn_signal_set (SIGUSR1); + if (error != CS_OK) { + fprintf (stderr, "Can't set warn signal. Error %d\n", error); + return 1; + } + + signal (SIGUSR1, test6_signal); + + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + error = sam_start (); + if (error != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", error); + return 1; + } + + printf ("%s iid %d: sleep 1\n", __FUNCTION__, instance_id); + sleep (1); + + printf ("%s iid %d: hc send\n", __FUNCTION__, instance_id); + error = sam_hc_send (); + if (error != CS_OK) { + fprintf (stderr, "Can't send hc. Error %d\n", error); + return 1; + } + + + printf ("%s iid %d: wait for delivery of signal\n", __FUNCTION__, instance_id); + while (!test6_sig_delivered) { + sleep (1); + } + + printf ("%s iid %d: wait for real kill\n", __FUNCTION__, instance_id); + + sleep (3); + + printf ("%s iid %d: wasn't killed\n", __FUNCTION__, instance_id); + return (1); + } + + if (instance_id == 2) { + error = sam_data_restore (&test6_sig_del, sizeof (test6_sig_del)); + if (error != CS_OK) { + fprintf (stderr, "Can't restore data. Error %d\n", error); + return 1; + } + + if (test6_sig_del != 1) { + fprintf (stderr, "Previous test failed. Signal was not delivered\n"); + return 1; + } + + error = sam_warn_signal_set (SIGKILL); + if (error != CS_OK) { + fprintf (stderr, "Can't set warn signal. Error %d\n", error); + return 1; + } + + signal (SIGUSR1, test6_signal); + + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + error = sam_start (); + if (error != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", error); + return 1; + } + + printf ("%s iid %d: sleep 1\n", __FUNCTION__, instance_id); + sleep (1); + + printf ("%s iid %d: hc send\n", __FUNCTION__, instance_id); + error = sam_hc_send (); + if (error != CS_OK) { + fprintf (stderr, "Can't send hc. Error %d\n", error); + return 1; + } + + + printf ("%s iid %d: wait for delivery of signal\n", __FUNCTION__, instance_id); + while (!test6_sig_delivered) { + sleep (1); + } + + printf ("%s iid %d: wasn't killed\n", __FUNCTION__, instance_id); + return (1); + } + + if (instance_id == 3) { + error = sam_data_restore (&test6_sig_del, sizeof (test6_sig_del)); + if (error != CS_OK) { + fprintf (stderr, "Can't restore data. Error %d\n", error); + return 1; + } + + if (test6_sig_del != 1) { + fprintf (stderr, "Previous test failed. Signal WAS delivered\n"); + return 1; + } + + return (0); + } + + return 1; +} + +static void *test7_thread (void *arg) +{ + /* Wait 5s */ + sleep (5); + exit (0); +} + +/* + * Test quorum + */ +static int test7 (void) { + cmap_handle_t cmap_handle; + cs_error_t err; + unsigned int instance_id; + pthread_t kill_thread; + char *str; + + err = cmap_initialize (&cmap_handle); + if (err != CS_OK) { + printf ("Could not initialize Cluster Map API instance error %d. Test skipped\n", err); + return (1); + } + + + if (cmap_get_string(cmap_handle, "quorum.provider", &str) != CS_OK) { + printf ("Could not get \"provider\" key: %d. Test skipped\n", err); + return (1); + } + if (strcmp(str, "testquorum") != 0) { + printf ("Provider is not testquorum. Test skipped\n"); + free(str); + return (1); + } + free(str); + + /* + * Set to not quorate + */ + err = cmap_set_uint8(cmap_handle, "quorum.quorate", 0); + if (err != CS_OK) { + printf ("Can't set map key. Error %d\n", err); + return (2); + } + + printf ("%s: initialize\n", __FUNCTION__); + err = sam_initialize (2000, SAM_RECOVERY_POLICY_QUORUM_RESTART); + if (err != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", err); + return 2; + } + + printf ("%s: register\n", __FUNCTION__); + err = sam_register (&instance_id); + if (err != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", err); + return 2; + } + + if (instance_id == 1) { + /* + * Sam start should block forever, but 10s for us should be enough + */ + pthread_create (&kill_thread, NULL, test7_thread, NULL); + + printf ("%s iid %d: start - should block forever (waiting 5s)\n", __FUNCTION__, instance_id); + err = sam_start (); + if (err != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", err); + return 2; + } + + printf ("%s iid %d: wasn't killed\n", __FUNCTION__, instance_id); + return (2); + } + + if (instance_id == 2) { + /* + * Set to quorate + */ + err = cmap_set_uint8(cmap_handle, "quorum.quorate", 1); + if (err != CS_OK) { + printf ("Can't set map key. Error %d\n", err); + return (2); + } + + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + err = sam_start (); + if (err != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", err); + return 2; + } + + /* + * Set corosync unquorate + */ + err = cmap_set_uint8(cmap_handle, "quorum.quorate", 0); + if (err != CS_OK) { + printf ("Can't set map key. Error %d\n", err); + return (2); + } + + printf ("%s iid %d: sleep 3\n", __FUNCTION__, instance_id); + sleep (3); + + printf ("%s iid %d: wasn't killed\n", __FUNCTION__, instance_id); + return (2); + } + + if (instance_id == 3) { + return (0); + } + + return (2); +} + +/* + * Test cmap integration + quit policy + */ +static int test8 (pid_t pid, pid_t old_pid, int test_n) { + cmap_handle_t cmap_handle; + cs_error_t err; + uint64_t tstamp1, tstamp2; + int32_t msec_diff; + unsigned int instance_id; + char key_name[CMAP_KEYNAME_MAXLEN]; + char *str; + + err = cmap_initialize (&cmap_handle); + if (err != CS_OK) { + printf ("Could not initialize Cluster Map API instance error %d. Test skipped\n", err); + return (1); + } + + printf ("%s test %d\n", __FUNCTION__, test_n); + + if (test_n == 2) { + /* + * Object should not exist + */ + printf ("%s Testing if object exists (it shouldn't)\n", __FUNCTION__); + + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.state", pid); + err = cmap_get_string(cmap_handle, key_name, &str); + if (err == CS_OK) { + printf ("Could find key \"%s\": %d.\n", key_name, err); + free(str); + return (2); + } + } + + if (test_n == 1 || test_n == 2) { + printf ("%s: initialize\n", __FUNCTION__); + err = sam_initialize (2000, SAM_RECOVERY_POLICY_QUIT | SAM_RECOVERY_POLICY_CMAP); + if (err != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", err); + return 2; + } + + printf ("%s: register\n", __FUNCTION__); + err = sam_register (&instance_id); + if (err != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", err); + return 2; + } + + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.recovery", pid); + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"recovery\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "quit") != 0) { + printf ("Recovery key \"%s\" is not \"quit\".\n", key_name); + free(str); + return (2); + } + free(str); + + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.state", pid); + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "stopped") != 0) { + printf ("State key is not \"stopped\".\n"); + free(str); + return (2); + } + free(str); + + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + err = sam_start (); + if (err != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", err); + return 2; + } + + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "running") != 0) { + printf ("State key is not \"running\".\n"); + free(str); + return (2); + } + free(str); + + printf ("%s iid %d: stop\n", __FUNCTION__, instance_id); + err = sam_stop (); + if (err != CS_OK) { + fprintf (stderr, "Can't stop hc. Error %d\n", err); + return 2; + } + + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "stopped") != 0) { + printf ("State key is not \"stopped\".\n"); + free(str); + return (2); + } + free(str); + + printf ("%s iid %d: sleeping 5\n", __FUNCTION__, instance_id); + sleep (5); + + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "stopped") != 0) { + printf ("State key is not \"stopped\".\n"); + free(str); + return (2); + } + free(str); + + printf ("%s iid %d: start 2\n", __FUNCTION__, instance_id); + err = sam_start (); + if (err != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", err); + return 2; + } + + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "running") != 0) { + printf ("State key is not \"running\".\n"); + free(str); + return (2); + } + free(str); + + if (test_n == 2) { + printf ("%s iid %d: sleeping 5. Should be killed\n", __FUNCTION__, instance_id); + sleep (5); + + return (2); + } else { + printf ("%s iid %d: Test HC\n", __FUNCTION__, instance_id); + err = sam_hc_send (); + if (err != CS_OK) { + fprintf (stderr, "Can't send hc. Error %d\n", err); + return 2; + } + + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.last_updated", pid); + err = cmap_get_uint64(cmap_handle, key_name, &tstamp1); + if (err != CS_OK) { + printf ("Could not get \"last_updated\" key: %d.\n", err); + return (2); + } + printf ("%s iid %d: Sleep 1\n", __FUNCTION__, instance_id); + sleep (1); + err = sam_hc_send (); + if (err != CS_OK) { + fprintf (stderr, "Can't send hc. Error %d\n", err); + return 2; + } + sleep (1); + err = cmap_get_uint64(cmap_handle, key_name, &tstamp2); + if (err != CS_OK) { + printf ("Could not get \"last_updated\" key: %d.\n", err); + return (2); + } + msec_diff = (tstamp2 - tstamp1)/CS_TIME_NS_IN_MSEC; + + if (msec_diff < 500 || msec_diff > 2000) { + printf ("Difference %d is not within <500, 2000> interval.\n", msec_diff); + return (2); + } + + printf ("%s iid %d: stop 2\n", __FUNCTION__, instance_id); + err = sam_stop (); + if (err != CS_OK) { + fprintf (stderr, "Can't stop hc. Error %d\n", err); + return 2; + } + + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.state", pid); + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "stopped") != 0) { + printf ("State key is not \"stopped\".\n"); + free(str); + return (2); + } + free(str); + + printf ("%s iid %d: exiting\n", __FUNCTION__, instance_id); + return (0); + } + } + + if (test_n == 3) { + printf ("%s Testing if status is failed\n", __FUNCTION__); + + /* + * Previous should be FAILED + */ + + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.state", pid); + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "failed") != 0) { + printf ("State key is not \"failed\".\n"); + free(str); + return (2); + } + free(str); + + return (0); + } + + return (2); +} + +/* + * Test cmap integration + restart policy + */ +static int test9 (pid_t pid, pid_t old_pid, int test_n) { + cs_error_t err; + cmap_handle_t cmap_handle; + unsigned int instance_id; + char *str; + char key_name[CMAP_KEYNAME_MAXLEN]; + + err = cmap_initialize (&cmap_handle); + if (err != CS_OK) { + printf ("Could not initialize Cluster Map API instance error %d. Test skipped\n", err); + return (1); + } + + printf ("%s test %d\n", __FUNCTION__, test_n); + + if (test_n == 1) { + printf ("%s: initialize\n", __FUNCTION__); + err = sam_initialize (2000, SAM_RECOVERY_POLICY_RESTART | SAM_RECOVERY_POLICY_CMAP); + if (err != CS_OK) { + fprintf (stderr, "Can't initialize SAM API. Error %d\n", err); + return 2; + } + + printf ("%s: register\n", __FUNCTION__); + err = sam_register (&instance_id); + if (err != CS_OK) { + fprintf (stderr, "Can't register. Error %d\n", err); + return 2; + } + printf ("%s: iid %d\n", __FUNCTION__, instance_id); + + if (instance_id < 3) { + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.recovery", pid); + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"recovery\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "restart") != 0) { + printf ("Recovery key \"%s\" is not \"restart\".\n", str); + free(str); + return (2); + } + free(str); + + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.state", pid); + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "stopped") != 0) { + printf ("State key is not \"stopped\".\n"); + free(str); + return (2); + } + free(str); + + printf ("%s iid %d: start\n", __FUNCTION__, instance_id); + err = sam_start (); + if (err != CS_OK) { + fprintf (stderr, "Can't start hc. Error %d\n", err); + return 2; + } + + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "running") != 0) { + printf ("State key is not \"running\".\n"); + free(str); + return (2); + } + free(str); + + printf ("%s iid %d: waiting for kill\n", __FUNCTION__, instance_id); + sleep (10); + + return (2); + } + + if (instance_id == 3) { + printf ("%s iid %d: mark failed\n", __FUNCTION__, instance_id); + + err = sam_mark_failed (); + if (err != CS_OK) { + fprintf (stderr, "Can't mark failed. Error %d\n", err); + return 2; + } + + sleep (10); + + return (2); + } + + return (2); + } + + if (test_n == 2) { + printf ("%s Testing if status is failed\n", __FUNCTION__); + + /* + * Previous should be FAILED + */ + snprintf(key_name, CMAP_KEYNAME_MAXLEN, "resources.process.%d.state", pid); + err = cmap_get_string(cmap_handle, key_name, &str); + if (err != CS_OK) { + printf ("Could not get \"state\" key: %d.\n", err); + return (2); + } + + if (strcmp(str, "failed") != 0) { + printf ("State key is not \"failed\".\n"); + free(str); + return (2); + } + free(str); + + return (0); + } + + return (2); +} + +int main(int argc, char *argv[]) +{ + pid_t pid, old_pid; + int err; + int stat; + int all_passed = 1; + int no_skipped = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 1; + } + + if (pid == 0) { + err = test1 (); + sam_finalize (); + return err; + } + + waitpid (pid, &stat, 0); + + fprintf (stderr, "test1 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : "failed")); + if (WEXITSTATUS (stat) != 0) + all_passed = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 1; + } + + if (pid == 0) { + err = test2 (); + + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + + fprintf (stderr, "test2 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : "failed")); + if (WEXITSTATUS (stat) != 0) + all_passed = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 1; + } + + if (pid == 0) { + err = test3 (); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + + fprintf (stderr, "test3 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : "failed")); + if (WEXITSTATUS (stat) != 0) + all_passed = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 1; + } + + if (pid == 0) { + err = test4 (); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + + fprintf (stderr, "test4 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : "failed")); + if (WEXITSTATUS (stat) != 0) + all_passed = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 1; + } + + if (pid == 0) { + err = test5 (); + + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + fprintf (stderr, "test5 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : "failed")); + if (WEXITSTATUS (stat) != 0) + all_passed = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 1; + } + + if (pid == 0) { + err = test6 (); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + fprintf (stderr, "test6 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : "failed")); + if (WEXITSTATUS (stat) != 0) + all_passed = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 2; + } + + if (pid == 0) { + err = test7 (); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + fprintf (stderr, "test7 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : (WEXITSTATUS (stat) == 1 ? "skipped" : "failed"))); + if (WEXITSTATUS (stat) == 1) + no_skipped++; + if (WEXITSTATUS (stat) > 1) + all_passed = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 2; + } + + if (pid == 0) { + err = test8 (getpid (), 0, 1); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + old_pid = pid; + + if (WEXITSTATUS (stat) == 0) { + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 2; + } + + if (pid == 0) { + err = test8 (getpid (), old_pid, 2); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + old_pid = pid; + + if (WEXITSTATUS (stat) == 0) { + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 2; + } + + if (pid == 0) { + err = test8 (old_pid, 0, 3); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + } + } + + fprintf (stderr, "test8 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : (WEXITSTATUS (stat) == 1 ? "skipped" : "failed"))); + if (WEXITSTATUS (stat) == 1) + no_skipped++; + if (WEXITSTATUS (stat) > 1) + all_passed = 0; + + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 2; + } + + if (pid == 0) { + err = test9 (getpid (), 0, 1); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + old_pid = pid; + + if (WEXITSTATUS (stat) == 0) { + pid = fork (); + + if (pid == -1) { + fprintf (stderr, "Can't fork\n"); + return 2; + } + + if (pid == 0) { + err = test9 (old_pid, 0, 2); + sam_finalize (); + return (err); + } + + waitpid (pid, &stat, 0); + } + fprintf (stderr, "test9 %s\n", (WEXITSTATUS (stat) == 0 ? "passed" : (WEXITSTATUS (stat) == 1 ? "skipped" : "failed"))); + if (WEXITSTATUS (stat) == 1) + no_skipped++; + + if (WEXITSTATUS (stat) > 1) + all_passed = 0; + + if (all_passed) + fprintf (stderr, "All tests passed (%d skipped)\n", no_skipped); + + return (all_passed ? 0 : 1); +} diff --git a/test/testvotequorum1.c b/test/testvotequorum1.c new file mode 100644 index 0000000..70fea50 --- /dev/null +++ b/test/testvotequorum1.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2009 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 <config.h> + +#include <sys/types.h> +#include <inttypes.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <corosync/corotypes.h> +#include <corosync/votequorum.h> + +static votequorum_handle_t g_handle; + +static const char *node_state(int state) +{ + switch (state) { + case VOTEQUORUM_NODESTATE_MEMBER: + return "Member"; + break; + case VOTEQUORUM_NODESTATE_DEAD: + return "Dead"; + break; + case VOTEQUORUM_NODESTATE_LEAVING: + return "Leaving"; + break; + default: + return "UNKNOWN"; + break; + } +} + + +static void votequorum_expectedvotes_notification_fn( + votequorum_handle_t handle, + uint64_t context, + uint32_t expected_votes + ) +{ + printf("votequorum expectedvotes notification called \n"); + printf(" expected_votes = %d\n", expected_votes); +} + + +static void votequorum_quorum_notification_fn( + votequorum_handle_t handle, + uint64_t context, + uint32_t quorate, + uint32_t node_list_entries, + votequorum_node_t node_list[] + ) +{ + int i; + + printf("votequorum quorum notification called \n"); + printf(" number of nodes = %d\n", node_list_entries); + printf(" quorate = %d\n", quorate); + + for (i = 0; i< node_list_entries; i++) { + printf(" " CS_PRI_NODE_ID ": %s\n", node_list[i].nodeid, node_state(node_list[i].state)); + } + +} + +static void votequorum_nodelist_notification_fn( + votequorum_handle_t handle, + uint64_t context, + votequorum_ring_id_t ring_id, + uint32_t node_list_entries, + uint32_t node_list[] + ) +{ + int i; + + printf("votequorum nodelist notification called \n"); + printf(" number of nodes = %d\n", node_list_entries); + printf(" current ringid = (" CS_PRI_RING_ID ")\n", ring_id.nodeid, ring_id.seq); + printf(" nodes: "); + + for (i = 0; i< node_list_entries; i++) { + printf(CS_PRI_NODE_ID " ", node_list[i]); + } + printf("\n\n"); +} + + +int main(int argc, char *argv[]) +{ + struct votequorum_info info; + votequorum_callbacks_t callbacks; + int err; + + if (argc > 1 && strcmp(argv[1], "-h")==0) { + fprintf(stderr, "usage: %s [new-expected] [new-votes]\n", argv[0]); + return 0; + } + + callbacks.votequorum_quorum_notify_fn = votequorum_quorum_notification_fn; + callbacks.votequorum_nodelist_notify_fn = votequorum_nodelist_notification_fn; + callbacks.votequorum_expectedvotes_notify_fn = votequorum_expectedvotes_notification_fn; + + if ( (err=votequorum_initialize(&g_handle, &callbacks)) != CS_OK) + fprintf(stderr, "votequorum_initialize FAILED: %d\n", err); + + if ( (err = votequorum_trackstart(g_handle, g_handle, CS_TRACK_CHANGES)) != CS_OK) + fprintf(stderr, "votequorum_trackstart FAILED: %d\n", err); + + if ( (err=votequorum_getinfo(g_handle, 0, &info)) != CS_OK) + fprintf(stderr, "votequorum_getinfo FAILED: %d\n", err); + else { + printf("node votes %d\n", info.node_votes); + printf("expected votes %d\n", info.node_expected_votes); + printf("highest expected %d\n", info.highest_expected); + printf("total votes %d\n", info.total_votes); + printf("quorum %d\n", info.quorum); + printf("flags "); + if (info.flags & VOTEQUORUM_INFO_TWONODE) printf("2Node "); + if (info.flags & VOTEQUORUM_INFO_QUORATE) printf("Quorate "); + if (info.flags & VOTEQUORUM_INFO_WAIT_FOR_ALL) printf("WaitForAll "); + if (info.flags & VOTEQUORUM_INFO_LAST_MAN_STANDING) printf("LastManStanding "); + if (info.flags & VOTEQUORUM_INFO_AUTO_TIE_BREAKER) printf("AutoTieBreaker "); + if (info.flags & VOTEQUORUM_INFO_ALLOW_DOWNSCALE) printf("AllowDownscale "); + + printf("\n"); + } + + if (argc >= 2 && atoi(argv[1])) { + if ( (err=votequorum_setexpected(g_handle, atoi(argv[1]))) != CS_OK) + fprintf(stderr, "set expected votes FAILED: %d\n", err); + } + if (argc >= 3 && atoi(argv[2])) { + if ( (err=votequorum_setvotes(g_handle, 0, atoi(argv[2]))) != CS_OK) + fprintf(stderr, "set votes FAILED: %d\n", err); + } + + if (argc >= 2) { + if ( (err=votequorum_getinfo(g_handle, 0, &info)) != CS_OK) + fprintf(stderr, "votequorum_getinfo2 FAILED: %d\n", err); + else { + printf("-------------------\n"); + printf("node votes %d\n", info.node_votes); + printf("expected votes %d\n", info.node_expected_votes); + printf("highest expected %d\n", info.highest_expected); + printf("total votes %d\n", info.total_votes); + printf("votequorum %d\n", info.quorum); + printf("flags "); + if (info.flags & VOTEQUORUM_INFO_TWONODE) printf("2Node "); + if (info.flags & VOTEQUORUM_INFO_QUORATE) printf("Quorate "); + if (info.flags & VOTEQUORUM_INFO_WAIT_FOR_ALL) printf("WaitForAll "); + if (info.flags & VOTEQUORUM_INFO_LAST_MAN_STANDING) printf("LastManStanding "); + if (info.flags & VOTEQUORUM_INFO_AUTO_TIE_BREAKER) printf("AutoTieBreaker "); + if (info.flags & VOTEQUORUM_INFO_ALLOW_DOWNSCALE) printf("AllowDownscale "); + printf("\n"); + } + } + + printf("Waiting for votequorum events, press ^C to finish\n"); + printf("-------------------\n"); + + if (votequorum_dispatch(g_handle, CS_DISPATCH_BLOCKING) != CS_OK) { + fprintf(stderr, "votequorum_dispatch error\n"); + return -1; + } + + return 0; +} diff --git a/test/testvotequorum2.c b/test/testvotequorum2.c new file mode 100644 index 0000000..1e8c13f --- /dev/null +++ b/test/testvotequorum2.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2009-2014 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 <config.h> + +#include <sys/types.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <corosync/corotypes.h> +#include <corosync/votequorum.h> + +static votequorum_handle_t handle; + +static votequorum_ring_id_t last_received_ring_id; +static votequorum_ring_id_t ring_id_to_send; +static int no_sent_old_ringid = 0; + +static int print_info(int ok_to_fail) +{ + struct votequorum_info info; + int err; + + if ( (err=votequorum_getinfo(handle, VOTEQUORUM_QDEVICE_NODEID, &info)) != CS_OK) { + fprintf(stderr, "votequorum_getinfo error %d: %s\n", err, ok_to_fail?"OK":"FAILED"); + return -1; + } + else { + printf("name %s\n", info.qdevice_name); + printf("qdevice votes %d\n", info.qdevice_votes); + if (info.flags & VOTEQUORUM_INFO_QDEVICE_ALIVE) { + printf("alive "); + } + if (info.flags & VOTEQUORUM_INFO_QDEVICE_CAST_VOTE) { + printf("cast-vote "); + } + if (info.flags & VOTEQUORUM_INFO_QDEVICE_MASTER_WINS) { + printf("master-wins"); + } + printf("\n\n"); + } + return 0; +} + +static void votequorum_nodelist_notification_fn( + votequorum_handle_t vq_handle, + uint64_t context, + votequorum_ring_id_t ring_id, + uint32_t node_list_entries, + uint32_t node_list[]) +{ + + printf("votequorum nodelist notification called \n"); + printf(" current ringid = (" CS_PRI_RING_ID ")\n", ring_id.nodeid, ring_id.seq); + printf("\n"); + + memcpy(&last_received_ring_id, &ring_id, sizeof(ring_id)); + no_sent_old_ringid = 0; +} + +static void usage(const char *command) +{ + printf("%s [-F <num>] [-p <num>] [-t <time>] [-n <name>] [-c] [-m]\n", command); + printf(" -F <num> Number of times to send old ringid before actual ringid is sent (for testing, default = 0)\n"); + printf(" -p <num> Number of times to poll qdevice (default 0=infinte)\n"); + printf(" -t <secs> Time (in seconds) to wait between polls (default=1)\n"); + printf(" -n <name> Name of quorum device (default QDEVICE)\n"); + printf(" -c Don't cast vote (default is to cast vote)\n"); + printf(" -q Don't print device status every poll time (default=will print)\n"); + printf(" -m Master wins (default no)\n"); + printf(" -1 Print status once and exit\n"); +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + int cast_vote = 1, master_wins = 0; + int pollcount=0, polltime=1, quiet=0, once=0; + int send_old_ringid = 0; + int err; + int opt; + votequorum_callbacks_t callbacks; + const char *devicename = "QDEVICE"; + const char *options = "F:n:p:t:cmq1h"; + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.votequorum_nodelist_notify_fn = votequorum_nodelist_notification_fn; + + while ((opt = getopt(argc, argv, options)) != -1) { + switch (opt) { + case 'm': + master_wins = 1; + break; + case 'c': + cast_vote = 0; + break; + case '1': + once = 1; + break; + case 'q': + quiet = 1; + break; + case 'F': + send_old_ringid = atoi(optarg)+1; + break; + case 'p': + pollcount = atoi(optarg)+1; + break; + case 'n': + devicename = strdup(optarg); + break; + case 't': + polltime = atoi(optarg); + break; + case 'h': + usage(argv[0]); + exit(0); + } + } + + if ( (err=votequorum_initialize(&handle, &callbacks)) != CS_OK) { + fprintf(stderr, "votequorum_initialize FAILED: %d\n", err); + return -1; + } + + if (quiet && once) { + fprintf(stderr, "setting both -q (quet) and -1 (once) makes no sense\n"); + usage(argv[0]); + exit(1); + } + + if (!quiet) { + print_info(1); + } + if (once) { + exit(0); + } + + if (argc >= 2) { + if ( (err = votequorum_trackstart(handle, handle, CS_TRACK_CHANGES)) != CS_OK) { + fprintf(stderr, "votequorum_trackstart FAILED: %d\n", err); + ret = -1; + goto out; + } + + if ( (err=votequorum_qdevice_register(handle, devicename)) != CS_OK) { + fprintf(stderr, "qdevice_register FAILED: %d\n", err); + ret = -1; + goto out; + } + + if ( (err=votequorum_qdevice_master_wins(handle, devicename, master_wins)) != CS_OK) { + fprintf(stderr, "qdevice_master_wins FAILED: %d\n", err); + ret = -1; + goto out; + } + + + while (--pollcount) { + if (votequorum_dispatch(handle, CS_DISPATCH_ALL) != CS_OK) { + fprintf(stderr, "votequorum_dispatch error\n"); + ret = -1; + goto out; + } + + if (!quiet) print_info(0); + + if (no_sent_old_ringid + 1 >= send_old_ringid) { + /* + * Finally send correct ringid + */ + memcpy(&ring_id_to_send, &last_received_ring_id, sizeof(ring_id_to_send)); + } else { + no_sent_old_ringid++; + } + + if ((err=votequorum_qdevice_poll(handle, devicename, cast_vote, ring_id_to_send)) != CS_OK && + err != CS_ERR_MESSAGE_ERROR) { + fprintf(stderr, "qdevice poll FAILED: %d\n", err); + ret = -1; + goto out; + } + if (err == CS_ERR_MESSAGE_ERROR) { + fprintf(stderr, "qdevice poll passed OLD ring_id\n"); + } + + if (!quiet) print_info(0); + sleep(polltime); + } + if ((err= votequorum_qdevice_unregister(handle, devicename)) != CS_OK) { + fprintf(stderr, "qdevice unregister FAILED: %d\n", err); + ret = -1; + goto out; + } + } + + if (!quiet) print_info(1); + +out: + votequorum_finalize(handle); + return ret; +} diff --git a/test/testzcgc.c b/test/testzcgc.c new file mode 100644 index 0000000..ca177f4 --- /dev/null +++ b/test/testzcgc.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2006-2009 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. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <corosync/corotypes.h> +#include <corosync/cpg.h> + +static int quit = 0; +static int show_ip = 0; + +static void print_cpgname (const struct cpg_name *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +static void DeliverCallback ( + cpg_handle_t handle, + const struct cpg_name *groupName, + uint32_t nodeid, + uint32_t pid, + void *msg, + size_t msg_len) +{ + if (show_ip) { + struct in_addr saddr; + saddr.s_addr = nodeid; + printf("DeliverCallback: message (len=%lu)from node/pid %s/%d: '%s'\n", + (unsigned long int) msg_len, + inet_ntoa(saddr), pid, (const char *)msg); + } + else { + printf("DeliverCallback: message (len=%lu)from node/pid " CS_PRI_NODE_ID "/%d: '%s'\n", + (unsigned long int) msg_len, nodeid, pid, + (const char *)msg); + } +} + +static void ConfchgCallback ( + cpg_handle_t handle, + const struct cpg_name *groupName, + const struct cpg_address *member_list, size_t member_list_entries, + const struct cpg_address *left_list, size_t left_list_entries, + const struct cpg_address *joined_list, size_t joined_list_entries) +{ + int i; + struct in_addr saddr; + + printf("\nConfchgCallback: group '"); + print_cpgname(groupName); + printf("'\n"); + for (i=0; i<joined_list_entries; i++) { + if (show_ip) { + saddr.s_addr = joined_list[i].nodeid; + printf("joined node/pid: %s/%d reason: %d\n", + inet_ntoa (saddr), joined_list[i].pid, + joined_list[i].reason); + } + else { + printf("joined node/pid: " CS_PRI_NODE_ID "/%d reason: %d\n", + joined_list[i].nodeid, joined_list[i].pid, + joined_list[i].reason); + } + } + + for (i=0; i<left_list_entries; i++) { + if (show_ip) { + saddr.s_addr = left_list[i].nodeid; + printf("left node/pid: %s/%d reason: %d\n", + inet_ntoa (saddr), left_list[i].pid, + left_list[i].reason); + } + else { + printf("left node/pid: " CS_PRI_NODE_ID "/%d reason: %d\n", + left_list[i].nodeid, left_list[i].pid, + left_list[i].reason); + } + } + + printf("nodes in group now %lu\n", + (unsigned long int) member_list_entries); + for (i=0; i<member_list_entries; i++) { + if (show_ip) { + saddr.s_addr = member_list[i].nodeid; + printf("node/pid: %s/%d\n", + inet_ntoa (saddr), member_list[i].pid); + } + else { + printf("node/pid: " CS_PRI_NODE_ID "/%d\n", + member_list[i].nodeid, member_list[i].pid); + } + } + + /* Is it us?? + NOTE: in reality we should also check the nodeid */ + if (left_list_entries && left_list[0].pid == getpid()) { + printf("We have left the building\n"); + quit = 1; + } +} + +static cpg_callbacks_t callbacks = { + .cpg_deliver_fn = DeliverCallback, + .cpg_confchg_fn = ConfchgCallback, +}; + +static struct cpg_name group_name; + +int main (int argc, char *argv[]) { + cpg_handle_t handle; + int result; + void *buffer; + unsigned int i; + + strcpy(group_name.value, "GROUP"); + group_name.length = 6; + + result = cpg_initialize (&handle, &callbacks); + if (result != CS_OK) { + printf ("Could not initialize Cluster Process Group API instance error %d\n", result); + exit (1); + } + for (i = 0; i < 100; i++) { + cpg_zcb_alloc (handle, 1024*1024, &buffer); + } + return (0); +} |