summaryrefslogtreecommitdiffstats
path: root/vqsim
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 17:01:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 17:01:24 +0000
commit6dd3dfb79125cd02d02efbce435a6c82e5af92ef (patch)
tree45084fc83278586f6bbafcb935f92d53f71a6b03 /vqsim
parentInitial commit. (diff)
downloadcorosync-6dd3dfb79125cd02d02efbce435a6c82e5af92ef.tar.xz
corosync-6dd3dfb79125cd02d02efbce435a6c82e5af92ef.zip
Adding upstream version 3.1.8.upstream/3.1.8upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vqsim')
-rw-r--r--vqsim/Makefile.am57
-rw-r--r--vqsim/Makefile.in787
-rw-r--r--vqsim/parser.c418
-rw-r--r--vqsim/vq_object.c121
-rw-r--r--vqsim/vqmain.c854
-rw-r--r--vqsim/vqsim.h82
-rw-r--r--vqsim/vqsim_vq_engine.c479
7 files changed, 2798 insertions, 0 deletions
diff --git a/vqsim/Makefile.am b/vqsim/Makefile.am
new file mode 100644
index 0000000..7639fcf
--- /dev/null
+++ b/vqsim/Makefile.am
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 2009 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
+
+if BUILD_VQSIM
+
+noinst_HEADERS = vqsim.h
+
+bin_PROGRAMS = corosync-vqsim
+
+corosync_vqsim_CFLAGS = $(knet_CFLAGS)
+
+corosync_vqsim_LDADD = $(top_builddir)/common_lib/libcorosync_common.la \
+ ../exec/corosync-votequorum.o ../exec/corosync-icmap.o \
+ ../exec/corosync-coroparse.o ../exec/corosync-logconfig.o \
+ ../exec/corosync-util.o ../exec/corosync-logsys.o \
+ $(LIBQB_LIBS) $(knet_LIBS)
+
+if VQSIM_READLINE
+corosync_vqsim_LDADD += -lreadline
+endif
+
+corosync_vqsim_DEPENDENCIES = $(top_builddir)/common_lib/libcorosync_common.la
+
+corosync_vqsim_SOURCES = vqmain.c parser.c vq_object.c vqsim_vq_engine.c
+
+endif
diff --git a/vqsim/Makefile.in b/vqsim/Makefile.in
new file mode 100644
index 0000000..df8ab19
--- /dev/null
+++ b/vqsim/Makefile.in
@@ -0,0 +1,787 @@
+# 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 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@
+@BUILD_VQSIM_TRUE@bin_PROGRAMS = corosync-vqsim$(EXEEXT)
+@BUILD_VQSIM_TRUE@@VQSIM_READLINE_TRUE@am__append_1 = -lreadline
+subdir = vqsim
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp $(am__noinst_HEADERS_DIST)
+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 =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am__corosync_vqsim_SOURCES_DIST = vqmain.c parser.c vq_object.c \
+ vqsim_vq_engine.c
+@BUILD_VQSIM_TRUE@am_corosync_vqsim_OBJECTS = \
+@BUILD_VQSIM_TRUE@ corosync_vqsim-vqmain.$(OBJEXT) \
+@BUILD_VQSIM_TRUE@ corosync_vqsim-parser.$(OBJEXT) \
+@BUILD_VQSIM_TRUE@ corosync_vqsim-vq_object.$(OBJEXT) \
+@BUILD_VQSIM_TRUE@ corosync_vqsim-vqsim_vq_engine.$(OBJEXT)
+corosync_vqsim_OBJECTS = $(am_corosync_vqsim_OBJECTS)
+am__DEPENDENCIES_1 =
+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 =
+corosync_vqsim_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(corosync_vqsim_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \
+ $@
+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 = $(corosync_vqsim_SOURCES)
+DIST_SOURCES = $(am__corosync_vqsim_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__noinst_HEADERS_DIST = vqsim.h
+HEADERS = $(noinst_HEADERS)
+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
+@BUILD_VQSIM_TRUE@noinst_HEADERS = vqsim.h
+@BUILD_VQSIM_TRUE@corosync_vqsim_CFLAGS = $(knet_CFLAGS)
+@BUILD_VQSIM_TRUE@corosync_vqsim_LDADD = $(top_builddir)/common_lib/libcorosync_common.la \
+@BUILD_VQSIM_TRUE@ ../exec/corosync-votequorum.o \
+@BUILD_VQSIM_TRUE@ ../exec/corosync-icmap.o \
+@BUILD_VQSIM_TRUE@ ../exec/corosync-coroparse.o \
+@BUILD_VQSIM_TRUE@ ../exec/corosync-logconfig.o \
+@BUILD_VQSIM_TRUE@ ../exec/corosync-util.o \
+@BUILD_VQSIM_TRUE@ ../exec/corosync-logsys.o $(LIBQB_LIBS) \
+@BUILD_VQSIM_TRUE@ $(knet_LIBS) $(am__append_1)
+@BUILD_VQSIM_TRUE@corosync_vqsim_DEPENDENCIES = $(top_builddir)/common_lib/libcorosync_common.la
+@BUILD_VQSIM_TRUE@corosync_vqsim_SOURCES = vqmain.c parser.c vq_object.c vqsim_vq_engine.c
+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 vqsim/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign vqsim/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):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_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
+
+corosync-vqsim$(EXEEXT): $(corosync_vqsim_OBJECTS) $(corosync_vqsim_DEPENDENCIES) $(EXTRA_corosync_vqsim_DEPENDENCIES)
+ @rm -f corosync-vqsim$(EXEEXT)
+ $(AM_V_CCLD)$(corosync_vqsim_LINK) $(corosync_vqsim_OBJECTS) $(corosync_vqsim_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/corosync_vqsim-parser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/corosync_vqsim-vq_object.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/corosync_vqsim-vqmain.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/corosync_vqsim-vqsim_vq_engine.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 $@ $<
+
+corosync_vqsim-vqmain.o: vqmain.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -MT corosync_vqsim-vqmain.o -MD -MP -MF $(DEPDIR)/corosync_vqsim-vqmain.Tpo -c -o corosync_vqsim-vqmain.o `test -f 'vqmain.c' || echo '$(srcdir)/'`vqmain.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/corosync_vqsim-vqmain.Tpo $(DEPDIR)/corosync_vqsim-vqmain.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vqmain.c' object='corosync_vqsim-vqmain.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -c -o corosync_vqsim-vqmain.o `test -f 'vqmain.c' || echo '$(srcdir)/'`vqmain.c
+
+corosync_vqsim-vqmain.obj: vqmain.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -MT corosync_vqsim-vqmain.obj -MD -MP -MF $(DEPDIR)/corosync_vqsim-vqmain.Tpo -c -o corosync_vqsim-vqmain.obj `if test -f 'vqmain.c'; then $(CYGPATH_W) 'vqmain.c'; else $(CYGPATH_W) '$(srcdir)/vqmain.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/corosync_vqsim-vqmain.Tpo $(DEPDIR)/corosync_vqsim-vqmain.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vqmain.c' object='corosync_vqsim-vqmain.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -c -o corosync_vqsim-vqmain.obj `if test -f 'vqmain.c'; then $(CYGPATH_W) 'vqmain.c'; else $(CYGPATH_W) '$(srcdir)/vqmain.c'; fi`
+
+corosync_vqsim-parser.o: parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -MT corosync_vqsim-parser.o -MD -MP -MF $(DEPDIR)/corosync_vqsim-parser.Tpo -c -o corosync_vqsim-parser.o `test -f 'parser.c' || echo '$(srcdir)/'`parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/corosync_vqsim-parser.Tpo $(DEPDIR)/corosync_vqsim-parser.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser.c' object='corosync_vqsim-parser.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -c -o corosync_vqsim-parser.o `test -f 'parser.c' || echo '$(srcdir)/'`parser.c
+
+corosync_vqsim-parser.obj: parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -MT corosync_vqsim-parser.obj -MD -MP -MF $(DEPDIR)/corosync_vqsim-parser.Tpo -c -o corosync_vqsim-parser.obj `if test -f 'parser.c'; then $(CYGPATH_W) 'parser.c'; else $(CYGPATH_W) '$(srcdir)/parser.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/corosync_vqsim-parser.Tpo $(DEPDIR)/corosync_vqsim-parser.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser.c' object='corosync_vqsim-parser.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -c -o corosync_vqsim-parser.obj `if test -f 'parser.c'; then $(CYGPATH_W) 'parser.c'; else $(CYGPATH_W) '$(srcdir)/parser.c'; fi`
+
+corosync_vqsim-vq_object.o: vq_object.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -MT corosync_vqsim-vq_object.o -MD -MP -MF $(DEPDIR)/corosync_vqsim-vq_object.Tpo -c -o corosync_vqsim-vq_object.o `test -f 'vq_object.c' || echo '$(srcdir)/'`vq_object.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/corosync_vqsim-vq_object.Tpo $(DEPDIR)/corosync_vqsim-vq_object.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vq_object.c' object='corosync_vqsim-vq_object.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -c -o corosync_vqsim-vq_object.o `test -f 'vq_object.c' || echo '$(srcdir)/'`vq_object.c
+
+corosync_vqsim-vq_object.obj: vq_object.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -MT corosync_vqsim-vq_object.obj -MD -MP -MF $(DEPDIR)/corosync_vqsim-vq_object.Tpo -c -o corosync_vqsim-vq_object.obj `if test -f 'vq_object.c'; then $(CYGPATH_W) 'vq_object.c'; else $(CYGPATH_W) '$(srcdir)/vq_object.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/corosync_vqsim-vq_object.Tpo $(DEPDIR)/corosync_vqsim-vq_object.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vq_object.c' object='corosync_vqsim-vq_object.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -c -o corosync_vqsim-vq_object.obj `if test -f 'vq_object.c'; then $(CYGPATH_W) 'vq_object.c'; else $(CYGPATH_W) '$(srcdir)/vq_object.c'; fi`
+
+corosync_vqsim-vqsim_vq_engine.o: vqsim_vq_engine.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -MT corosync_vqsim-vqsim_vq_engine.o -MD -MP -MF $(DEPDIR)/corosync_vqsim-vqsim_vq_engine.Tpo -c -o corosync_vqsim-vqsim_vq_engine.o `test -f 'vqsim_vq_engine.c' || echo '$(srcdir)/'`vqsim_vq_engine.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/corosync_vqsim-vqsim_vq_engine.Tpo $(DEPDIR)/corosync_vqsim-vqsim_vq_engine.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vqsim_vq_engine.c' object='corosync_vqsim-vqsim_vq_engine.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -c -o corosync_vqsim-vqsim_vq_engine.o `test -f 'vqsim_vq_engine.c' || echo '$(srcdir)/'`vqsim_vq_engine.c
+
+corosync_vqsim-vqsim_vq_engine.obj: vqsim_vq_engine.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -MT corosync_vqsim-vqsim_vq_engine.obj -MD -MP -MF $(DEPDIR)/corosync_vqsim-vqsim_vq_engine.Tpo -c -o corosync_vqsim-vqsim_vq_engine.obj `if test -f 'vqsim_vq_engine.c'; then $(CYGPATH_W) 'vqsim_vq_engine.c'; else $(CYGPATH_W) '$(srcdir)/vqsim_vq_engine.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/corosync_vqsim-vqsim_vq_engine.Tpo $(DEPDIR)/corosync_vqsim-vqsim_vq_engine.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vqsim_vq_engine.c' object='corosync_vqsim-vqsim_vq_engine.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(corosync_vqsim_CFLAGS) $(CFLAGS) -c -o corosync_vqsim-vqsim_vq_engine.obj `if test -f 'vqsim_vq_engine.c'; then $(CYGPATH_W) 'vqsim_vq_engine.c'; else $(CYGPATH_W) '$(srcdir)/vqsim_vq_engine.c'; fi`
+
+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) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+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-binPROGRAMS clean-generic clean-libtool 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-binPROGRAMS
+
+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: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libtool 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-binPROGRAMS \
+ 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 uninstall-binPROGRAMS
+
+
+# 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/vqsim/parser.c b/vqsim/parser.c
new file mode 100644
index 0000000..2857184
--- /dev/null
+++ b/vqsim/parser.c
@@ -0,0 +1,418 @@
+/* Parses the interactive commands */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#ifdef HAVE_READLINE_HISTORY_H
+#include <readline/history.h>
+#endif
+
+#include <corosync/coroapi.h>
+#include "vqsim.h"
+
+static void do_usage(void)
+{
+ printf(" All node IDs in the cluster are unique and belong to a numbered 'partition' (default=0)\n");
+ printf("\n");
+ printf("up [<partition>:][<nodeid>[,<nodeid>] ...] [[<partition>:][<nodeid>...]] [...]\n");
+ printf(" bring node(s) online in the specified partition(s)\n");
+ printf("down <nodeid>,[<nodeid>...]\n");
+ printf(" send nodes offline (shut them down)\n");
+ printf("move/split [<partition>:][<nodeid>[,<nodeid>] ...] [[<partition>:][<nodeid>...]] [...]\n");
+ printf(" Move nodes from one partition to another (netsplit)\n");
+ printf(" <partition> here is the partition to move the nodes to\n");
+ printf("join <partition> <partition> [<partition>] ... \n");
+ printf(" Join partitions together (reverse of a netsplit)\n");
+ printf("qdevice on|off [<partition>:][<nodeid>[,<nodeid>] ...] [[<partition>:][<nodeid>...]] [...]\n");
+ printf(" Enable quorum device in specified nodes\n");
+ printf("autofence on|off\n");
+ printf(" automatically 'down' nodes on inquorate side on netsplit\n");
+ printf("timeout <n> (default 250)\n");
+ printf(" Wait a maximum of <n> milli-seconds for the next command to complete.\n");
+ printf("sync on|off (default on)\n");
+ printf(" enable/disable synchronous execution of commands (wait for completion)\n");
+ printf("assert on|off (default off)\n");
+ printf(" Abort the simulation run if a timeout expires\n");
+ printf("show Show current nodes status\n");
+ printf("exit\n\n");
+}
+
+
+/* Commands return 0 if they return immediately, >1 if we are waiting for replies from nodes */
+typedef int (*cmd_routine_t)(int argc, char **argv);
+
+static int run_up_cmd(int argc, char **argv);
+static int run_down_cmd(int argc, char **argv);
+static int run_join_cmd(int argc, char **argv);
+static int run_move_cmd(int argc, char **argv);
+static int run_exit_cmd(int argc, char **argv);
+static int run_show_cmd(int argc, char **argv);
+static int run_timeout_cmd(int argc, char **argv);
+static int run_assert_cmd(int argc, char **argv);
+static int run_autofence_cmd(int argc, char **argv);
+static int run_qdevice_cmd(int argc, char **argv);
+static int run_sync_cmd(int argc, char **argv);
+
+static struct cmd_list_struct {
+ const char *cmd;
+ int min_args;
+ cmd_routine_t cmd_runner;
+} cmd_list[] = {
+ { "up", 1, run_up_cmd},
+ { "down", 1, run_down_cmd},
+ { "move", 2, run_move_cmd},
+ { "split", 2, run_move_cmd},
+ { "join", 2, run_join_cmd},
+ { "autofence", 1, run_autofence_cmd},
+ { "qdevice", 1, run_qdevice_cmd},
+ { "show", 0, run_show_cmd},
+ { "timeout", 1, run_timeout_cmd},
+ { "sync", 1, run_sync_cmd},
+ { "assert", 1, run_assert_cmd},
+ { "exit", 0, run_exit_cmd},
+ { "quit", 0, run_exit_cmd},
+ { "q", 0, run_exit_cmd},
+};
+static int num_cmds = (sizeof(cmd_list)) / sizeof(struct cmd_list_struct);
+#define MAX_ARGS 1024
+
+/* Takes a <partition>:[<node>[,<node>]...] list and return it
+ as a partition and a list of nodes.
+ Returns 0 if successful, -1 if not
+*/
+static int parse_partition_nodelist(char *string, int *partition, int *num_nodes, int **retnodes)
+{
+ int i;
+ int nodecount;
+ int len;
+ int last_comma;
+ char *nodeptr;
+ int *nodes;
+ char *colonptr = strchr(string, ':');
+
+ if (colonptr) {
+ *colonptr = '\0';
+ nodeptr = colonptr+1;
+ *partition = atoi(string);
+ }
+ else {
+ /* Default to partition 0 */
+ *partition = 0;
+ nodeptr = string;
+ }
+
+ /* Count the number of commas and allocate space for the nodes */
+ nodecount = 0;
+ for (i=0; i<strlen(nodeptr); i++) {
+ if (nodeptr[i] == ',') {
+ nodecount++;
+ }
+ }
+ nodecount++; /* The one between the last comma and the trailing NUL */
+ if (nodecount < 1 || nodecount > MAX_NODES) {
+ return -1;
+ }
+
+ nodes = malloc(sizeof(int) * nodecount);
+ if (!nodes) {
+ return -1;
+ }
+
+ nodecount = 0;
+ last_comma = 0;
+ len = strlen(nodeptr);
+ for (i=0; i<=len; i++) {
+ if (nodeptr[i] == ',' || nodeptr[i] == '\0') {
+
+ nodeptr[i] = '\0';
+ nodes[nodecount++] = atoi(&nodeptr[last_comma]);
+ last_comma = i+1;
+ }
+ }
+
+ *num_nodes = nodecount;
+ *retnodes = nodes;
+
+ return 0;
+}
+
+void parse_input_command(char *rl_cmd)
+{
+ int i;
+ int argc = 0;
+ int valid_cmd = 0;
+ char *argv[MAX_ARGS];
+ int last_arg_start = 0;
+ int last_was_space = 0;
+ int len;
+ int ret = 0;
+ char *cmd;
+
+ /* ^D quits */
+ if (rl_cmd == NULL) {
+ (void)run_exit_cmd(0, NULL);
+ }
+ /* '#' starts a comment */
+ if (rl_cmd[0] == '#') {
+ return;
+ }
+
+ cmd = strdup(rl_cmd);
+
+ /* Split cmd up into args
+ * destroying the original string mwahahahaha
+ */
+
+ len = strlen(cmd);
+
+ /* Span leading spaces */
+ for (i=0; cmd[i] == ' '; i++)
+ ;
+ last_arg_start = i;
+
+ for (; i<=len; i++) {
+ if (cmd[i] == ' ' || cmd[i] == '\0') {
+
+ /* Allow multiple spaces */
+ if (last_was_space) {
+ continue;
+ }
+
+ cmd[i] = '\0';
+ last_was_space = 1;
+
+ argv[argc] = &cmd[last_arg_start];
+ argc++;
+ }
+ else {
+ if (last_was_space) {
+ last_arg_start = i;
+ }
+ last_was_space = 0;
+ }
+ }
+
+ /* Ignore null commands */
+ if (argc < 1 || strlen(argv[0]) == 0) {
+ free(cmd);
+ resume_kb_input(0);
+ return;
+ }
+#ifdef HAVE_READLINE_HISTORY_H
+ add_history(rl_cmd);
+#endif
+
+ /* Dispatch command */
+ for (i=0; i<num_cmds; i++) {
+ if (strcasecmp(argv[0], cmd_list[i].cmd) == 0) {
+
+ if (argc < cmd_list[i].min_args) {
+ break;
+ }
+ ret = cmd_list[i].cmd_runner(argc, argv);
+ valid_cmd = 1;
+ }
+ }
+ if (!valid_cmd) {
+ do_usage();
+ }
+ free(cmd);
+
+ /* ret==0 means we can return immediately to command-line input */
+ if (ret == 0) {
+ resume_kb_input(ret);
+ }
+}
+
+
+
+static int run_up_cmd(int argc, char **argv)
+{
+ int partition;
+ int num_nodes;
+ int *nodelist;
+ int i,j;
+ int succeeded = 0;
+
+ if (argc <= 1) {
+ return 0;
+ }
+
+ cmd_start_sync_command();
+
+ for (i=1; i<argc; i++) {
+ if (parse_partition_nodelist(argv[i], &partition, &num_nodes, &nodelist) == 0) {
+ for (j=0; j<num_nodes; j++) {
+ if (!cmd_start_new_node(nodelist[j], partition)) {
+ succeeded++;
+ }
+ }
+ free(nodelist);
+ }
+ }
+ return succeeded;
+}
+
+static int run_down_cmd(int argc, char **argv)
+{
+ int nodeid;
+ int i;
+ int succeeded = 0;
+
+ cmd_start_sync_command();
+
+ for (i=1; i<argc; i++) {
+ nodeid = atoi(argv[1]);
+ if (!cmd_stop_node(nodeid)) {
+ succeeded++;
+ }
+ }
+ return succeeded;
+}
+
+static int run_join_cmd(int argc, char **argv)
+{
+ int i;
+
+ if (argc < 2) {
+ printf("join needs at least two partition numbers\n");
+ return 0;
+ }
+
+ cmd_start_sync_command();
+
+ for (i=2; i<argc; i++) {
+ cmd_join_partitions(atoi(argv[1]), atoi(argv[i]));
+ }
+ cmd_update_all_partitions(1);
+ return 1;
+}
+
+static int run_move_cmd(int argc, char **argv)
+{
+ int i;
+ int partition;
+ int num_nodes;
+ int *nodelist;
+
+ cmd_start_sync_command();
+
+ for (i=1; i<argc; i++) {
+ if (parse_partition_nodelist(argv[i], &partition, &num_nodes, &nodelist) == 0) {
+ cmd_move_nodes(partition, num_nodes, nodelist);
+ free(nodelist);
+ }
+ }
+ cmd_update_all_partitions(1);
+ return 1;
+}
+
+static int run_autofence_cmd(int argc, char **argv)
+{
+ int onoff = -1;
+
+ if (strcasecmp(argv[1], "on") == 0) {
+ onoff = 1;
+ }
+ if (strcasecmp(argv[1], "off") == 0) {
+ onoff = 0;
+ }
+ if (onoff == -1) {
+ fprintf(stderr, "ERR: autofence value must be 'on' or 'off'\n");
+ }
+ else {
+ cmd_set_autofence(onoff);
+ }
+ return 0;
+}
+
+static int run_qdevice_cmd(int argc, char **argv)
+{
+ int i,j;
+ int partition;
+ int num_nodes;
+ int *nodelist;
+ int onoff = -1;
+
+ if (strcasecmp(argv[1], "on") == 0) {
+ onoff = 1;
+ }
+ if (strcasecmp(argv[1], "off") == 0) {
+ onoff = 0;
+ }
+
+ if (onoff == -1) {
+ fprintf(stderr, "ERR: qdevice should be 'on' or 'off'\n");
+ return 0;
+ }
+
+ for (i=2; i<argc; i++) {
+ if (parse_partition_nodelist(argv[i], &partition, &num_nodes, &nodelist) == 0) {
+ for (j=0; j<num_nodes; j++) {
+ cmd_qdevice_poll(nodelist[j], onoff);
+ }
+ free(nodelist);
+ }
+ }
+ cmd_update_all_partitions(0);
+ return 0;
+}
+
+static int run_show_cmd(int argc, char **argv)
+{
+ cmd_show_node_states();
+ return 0;
+}
+
+static int run_timeout_cmd(int argc, char **argv)
+{
+ cmd_set_timeout(atol(argv[1]));
+ return 0;
+}
+
+static int run_sync_cmd(int argc, char **argv)
+{
+ int onoff = -1;
+
+ if (strcasecmp(argv[1], "on") == 0) {
+ onoff = 1;
+ }
+ if (strcasecmp(argv[1], "off") == 0) {
+ onoff = 0;
+ }
+ if (onoff == -1) {
+ fprintf(stderr, "ERR: sync value must be 'on' or 'off'\n");
+ }
+ else {
+ cmd_set_sync(onoff);
+ }
+ return 0;
+}
+
+static int run_assert_cmd(int argc, char **argv)
+{
+ int onoff = -1;
+
+ if (strcasecmp(argv[1], "on") == 0) {
+ onoff = 1;
+ }
+ if (strcasecmp(argv[1], "off") == 0) {
+ onoff = 0;
+ }
+ if (onoff == -1) {
+ fprintf(stderr, "ERR: assert value must be 'on' or 'off'\n");
+ }
+ else {
+ cmd_set_assert(onoff);
+ }
+ return 0;
+}
+
+static int run_exit_cmd(int argc, char **argv)
+{
+ cmd_stop_all_nodes();
+ exit(0);
+}
diff --git a/vqsim/vq_object.c b/vqsim/vq_object.c
new file mode 100644
index 0000000..d832e10
--- /dev/null
+++ b/vqsim/vq_object.c
@@ -0,0 +1,121 @@
+/*
+ This is a Votequorum object in the parent process. it's really just a conduit for the forked
+ votequorum entity
+*/
+
+#include <qb/qblog.h>
+#include <qb/qbloop.h>
+#include <qb/qbipcc.h>
+#include <netinet/in.h>
+
+#include "../exec/votequorum.h"
+#include "vqsim.h"
+
+struct vq_instance
+{
+ int nodeid;
+ int vq_socket;
+ pid_t pid;
+};
+
+vq_object_t vq_create_instance(qb_loop_t *poll_loop, int nodeid)
+{
+ struct vq_instance *instance = malloc(sizeof(struct vq_instance));
+ if (!instance) {
+ return NULL;
+ }
+
+ instance->nodeid = nodeid;
+
+ if (fork_new_instance(nodeid, &instance->vq_socket, &instance->pid)) {
+ free(instance);
+ return NULL;
+ }
+
+ return instance;
+}
+
+pid_t vq_get_pid(vq_object_t instance)
+{
+ struct vq_instance *vqi = instance;
+ return vqi->pid;
+}
+
+void vq_quit(vq_object_t instance)
+{
+ struct vq_instance *vqi = instance;
+ struct vqsim_msg_header msg;
+ int res;
+
+ msg.type = VQMSG_QUIT;
+ msg.from_nodeid = 0;
+ msg.param = 0;
+
+ res = write(vqi->vq_socket, &msg, sizeof(msg));
+ if (res <= 0) {
+ perror("Quit write failed");
+ }
+}
+
+int vq_quit_if_inquorate(vq_object_t instance)
+{
+ struct vq_instance *vqi = instance;
+ struct vqsim_msg_header msg;
+ int res;
+
+ msg.type = VQMSG_QUORUMQUIT;
+ msg.from_nodeid = 0;
+ msg.param = 0;
+
+ res = write(vqi->vq_socket, &msg, sizeof(msg));
+ if (res <= 0) {
+ perror("Quit write failed");
+ }
+ return 0;
+}
+
+int vq_set_nodelist(vq_object_t instance, struct memb_ring_id *ring_id, int *nodeids, int nodeids_entries)
+{
+ struct vq_instance *vqi = instance;
+ char msgbuf[sizeof(int)*nodeids_entries + sizeof(struct vqsim_sync_msg)];
+ struct vqsim_sync_msg *msg = (void*)msgbuf;
+ int res;
+
+ msg->header.type = VQMSG_SYNC;
+ msg->header.from_nodeid = 0;
+ msg->header.param = 0;
+ msg->view_list_entries = nodeids_entries;
+ memcpy(&msg->view_list, nodeids, nodeids_entries*sizeof(int));
+ memcpy(&msg->ring_id, ring_id, sizeof(struct memb_ring_id));
+
+ res = write(vqi->vq_socket, msgbuf, sizeof(msgbuf));
+ if (res <= 0) {
+ perror("Sync write failed");
+ return -1;
+ }
+ return 0;
+}
+
+int vq_set_qdevice(vq_object_t instance, struct memb_ring_id *ring_id, int onoff)
+{
+ struct vq_instance *vqi = instance;
+ struct vqsim_msg_header msg;
+ int res;
+
+ msg.type = VQMSG_QDEVICE;
+ msg.from_nodeid = 0;
+ msg.param = onoff;
+ res = write(vqi->vq_socket, &msg, sizeof(msg));
+ if (res <= 0) {
+ perror("qdevice register write failed");
+ return -1;
+ }
+ return 0;
+}
+
+int vq_get_parent_fd(vq_object_t instance)
+{
+ struct vq_instance *vqi = instance;
+
+ return vqi->vq_socket;
+}
diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
new file mode 100644
index 0000000..8e5f0e3
--- /dev/null
+++ b/vqsim/vqmain.c
@@ -0,0 +1,854 @@
+#include <config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <qb/qblog.h>
+#include <qb/qbloop.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <sys/queue.h>
+#ifdef HAVE_READLINE_READLINE_H
+#include <readline/readline.h>
+#else
+#include <unistd.h> /* isatty */
+#endif
+
+#include "../exec/votequorum.h"
+#include "../exec/service.h"
+#include <corosync/logsys.h>
+#include <corosync/coroapi.h>
+
+#include "icmap.h"
+#include "vqsim.h"
+
+/* Easier than including the config file with a ton of conflicting dependencies */
+extern int coroparse_configparse (icmap_map_t config_map, const char **error_string);
+extern int corosync_log_config_read (const char **error_string);
+static int stdin_read_fn(int32_t fd, int32_t revents, void *data);
+void totemknet_configure_log_level(void);
+
+/* 'Keep the compiler happy' time */
+const char *corosync_get_config_file(void);
+
+/* One of these per partition */
+struct vq_partition {
+ TAILQ_HEAD(, vq_node) nodelist;
+ struct memb_ring_id ring_id;
+ int num;
+};
+
+/* One of these per node */
+struct vq_node {
+ vq_object_t instance;
+ unsigned int nodeid;
+ int fd;
+ struct vq_partition *partition;
+ TAILQ_ENTRY(vq_node) entries;
+
+ /* Last status */
+ int last_quorate;
+ struct memb_ring_id last_ring_id;
+ int last_view_list[MAX_NODES];
+ int last_view_list_entries;
+};
+
+static struct vq_partition partitions[MAX_PARTITIONS];
+static qb_loop_t *poll_loop;
+static int autofence;
+static int check_for_quorum;
+static FILE *output_file;
+static int sync_cmds = 1;
+static qb_loop_timer_handle kb_timer;
+static int waiting_for_sync = 0;
+static int is_tty;
+static int assert_on_timeout;
+static uint64_t command_timeout = 250000000L;
+
+static struct vq_node *find_by_pid(pid_t pid);
+static void send_partition_to_nodes(struct vq_partition *partition, int newring);
+static void start_kb_input_timeout(void *data);
+static void finish_wait_timeout(void *data);
+
+#ifndef HAVE_READLINE_READLINE_H
+#define INPUT_BUF_SIZE 1024
+static char input_buf[INPUT_BUF_SIZE];
+static size_t input_buf_term = 0;
+#endif
+
+/* 'Keep the compiler happy' time */
+static char corosync_config_file[PATH_MAX + 1] = COROSYSCONFDIR "/corosync.conf";
+
+const char *corosync_get_config_file(void)
+{
+ return (corosync_config_file);
+}
+
+/* Tell all non-quorate nodes to quit */
+static void force_fence(void)
+{
+ int i;
+ struct vq_node *vqn;
+
+ for (i=0; i<MAX_PARTITIONS; i++) {
+ TAILQ_FOREACH(vqn, &partitions[i].nodelist, entries) {
+ vq_quit_if_inquorate(vqn->instance);
+ }
+ }
+}
+
+/* Save quorum state from the incoming message */
+static void save_quorum_state(struct vq_node *node, struct vqsim_quorum_msg *qmsg)
+{
+ node->last_quorate = qmsg->quorate;
+ memcpy(&node->last_ring_id, &qmsg->ring_id, sizeof(struct memb_ring_id));
+ memcpy(node->last_view_list, qmsg->view_list, sizeof(int) * qmsg->view_list_entries);
+ node->last_view_list_entries = qmsg->view_list_entries;
+
+ /* If at least one node is quorate and autofence is enabled, then fence everyone who is not quorate */
+ if (check_for_quorum && qmsg->quorate & autofence) {
+ check_for_quorum = 0;
+ force_fence();
+ }
+}
+
+/* Print current node state */
+static void print_quorum_state(struct vq_node *node)
+{
+ int i;
+
+ if (node->last_quorate < 0) {
+ fprintf(output_file, "%d:" CS_PRI_NODE_ID ": q=UNINITIALIZED\n",
+ node->partition->num, node->nodeid);
+ return;
+ }
+
+ fprintf(output_file, "%d:" CS_PRI_NODE_ID ": q=%d ring=[" CS_PRI_RING_ID "] ", node->partition->num, node->nodeid, node->last_quorate,
+ node->last_ring_id.nodeid, (uint64_t)node->last_ring_id.seq);
+ fprintf(output_file, "nodes=[");
+ for (i = 0; i < node->last_view_list_entries; i++) {
+ if (i) {
+ fprintf(output_file, " ");
+ }
+ fprintf(output_file, CS_PRI_NODE_ID, node->last_view_list[i]);
+ }
+ fprintf(output_file, "]\n");
+
+}
+
+static void propogate_vq_message(struct vq_node *vqn, const char *msg, int len)
+{
+ struct vq_node *other_vqn;
+ ssize_t write_res;
+
+ /* Send it to everyone in that node's partition (including itself) */
+ TAILQ_FOREACH(other_vqn, &vqn->partition->nodelist, entries) {
+ write_res = write(other_vqn->fd, msg, len);
+ /*
+ * Read counterpart is not ready for receiving non-complete message so
+ * ensure all required information was send.
+ */
+ assert(write_res == len);
+ }
+}
+
+
+static void cmd_show_prompt_if_needed(void)
+{
+ qb_loop_timer_del(poll_loop, kb_timer);
+ if (is_tty) {
+ printf("vqsim> ");
+ fflush(stdout);
+ } else {
+ printf("#vqsim> ");
+ fflush(stdout);
+ }
+
+}
+
+void resume_kb_input(int show_status)
+{
+ /* If running synchronously, we don't display
+ the quorum messages as they come in. So run 'show' commamnd
+ */
+ if (show_status && waiting_for_sync) {
+ cmd_show_node_states();
+ }
+
+ waiting_for_sync = 0;
+
+ if (qb_loop_poll_add(poll_loop,
+ QB_LOOP_MED,
+ STDIN_FILENO,
+ POLLIN | POLLERR,
+ NULL,
+ stdin_read_fn)) {
+ if (errno != EEXIST) {
+ perror("qb_loop_poll_add1 returned error");
+ }
+ }
+ /* Always shows the prompt here, cos we cleared waiting_for_sync */
+ cmd_show_prompt_if_needed();
+}
+
+/* Return true (1) if all nodes in each partition have the same ring id, false(0) otherwise */
+static int all_nodes_consistent(void)
+{
+ int i;
+ struct vq_node *vqn;
+ struct memb_ring_id last_ring_id;
+
+ for (i=0; i<MAX_PARTITIONS; i++) {
+ memset(&last_ring_id, 0, sizeof(last_ring_id));
+ TAILQ_FOREACH(vqn, &partitions[i].nodelist, entries) {
+ if (last_ring_id.seq &&
+ last_ring_id.seq != vqn->last_ring_id.seq) {
+ return 0;
+ }
+ last_ring_id.seq = vqn->last_ring_id.seq;
+ }
+ }
+ return 1;
+}
+
+static int vq_parent_read_fn(int32_t fd, int32_t revents, void *data)
+{
+ char msgbuf[8192];
+ int msglen;
+ struct vqsim_msg_header *msg;
+ struct vqsim_quorum_msg *qmsg;
+ struct vq_node *vqn = data;
+
+ if (revents == POLLIN) {
+ msglen = read(fd, msgbuf, sizeof(msgbuf));
+ if (msglen < 0) {
+ perror("read failed");
+ } else if (msglen < sizeof(*msg)) {
+ fprintf(stderr, "Received message is too short\n");
+ } else {
+ msg = (void*)msgbuf;
+ switch (msg->type) {
+ case VQMSG_QUORUM:
+ qmsg = (void*)msgbuf;
+ /*
+ * Check length of message.
+ * SOCK_SEQPACKET is used so this check is not strictly needed.
+ */
+ if (msglen < sizeof(*qmsg) ||
+ qmsg->view_list_entries > MAX_NODES ||
+ msglen < sizeof(*qmsg) + sizeof(qmsg->view_list[0]) * qmsg->view_list_entries) {
+ fprintf(stderr, "Received quorum message is too short or corrupted\n");
+ return (0);
+ }
+ save_quorum_state(vqn, qmsg);
+ if (!sync_cmds) {
+ print_quorum_state(vqn);
+ }
+
+ /* Have the partitions stabilised? */
+ if (sync_cmds && waiting_for_sync &&
+ all_nodes_consistent()) {
+ qb_loop_timer_del(poll_loop, kb_timer);
+ resume_kb_input(sync_cmds);
+ }
+ break;
+ case VQMSG_EXEC:
+ /* Message from votequorum, pass around the partition */
+ propogate_vq_message(vqn, msgbuf, msglen);
+ break;
+ case VQMSG_QUIT:
+ case VQMSG_SYNC:
+ case VQMSG_QDEVICE:
+ case VQMSG_QUORUMQUIT:
+ /* not used here */
+ break;
+ }
+ }
+ }
+ if (revents == POLLERR) {
+ fprintf(stderr, "pollerr on " CS_PRI_NODE_ID "\n", vqn->nodeid);
+ }
+ return 0;
+}
+
+/* Dummy routine to keep the linker happy */
+void totemknet_configure_log_level(void)
+{
+
+}
+
+static int read_corosync_conf(void)
+{
+ int res;
+ const char *error_string;
+
+ int err = icmap_init();
+ if (!err) {
+ fprintf(stderr, "icmap_init failed\n");
+ }
+
+ /* Load corosync.conf */
+ logsys_format_set(NULL);
+ res = coroparse_configparse(icmap_get_global_map(), &error_string);
+ if (res == -1) {
+ log_printf (LOGSYS_LEVEL_INFO, "Error loading corosync.conf %s", error_string);
+ return -1;
+ }
+ else {
+ res = corosync_log_config_read (&error_string);
+ if (res < 0) {
+ log_printf (LOGSYS_LEVEL_INFO, "error reading log config %s", error_string);
+ syslog (LOGSYS_LEVEL_INFO, "error reading log config %s", error_string);
+ }
+ else {
+ logsys_config_apply();
+ }
+ }
+ if (logsys_thread_start() != 0) {
+ log_printf (LOGSYS_LEVEL_ERROR, "Can't initialize log thread");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void remove_node(struct vq_node *node)
+{
+ struct vq_partition *part;
+ part = node->partition;
+
+ /* Remove from partition list */
+ TAILQ_REMOVE(&part->nodelist, node, entries);
+ free(node);
+
+ /* Rebuild quorum */
+ send_partition_to_nodes(part, 1);
+}
+
+static int32_t sigchld_handler(int32_t sig, void *data)
+{
+ pid_t pid;
+ int status;
+ struct vq_node *vqn;
+ const char *exit_status="";
+ char text[132];
+
+ pid = wait(&status);
+ if (WIFEXITED(status)) {
+ vqn = find_by_pid(pid);
+ if (vqn) {
+ switch (WEXITSTATUS(status)) {
+ case 0:
+ exit_status = "(on request)";
+ break;
+ case 1:
+ exit_status = "(autofenced)";
+ break;
+ default:
+ sprintf(text, "(exit code %d)", WEXITSTATUS(status));
+ break;
+ }
+ printf("%d:" CS_PRI_NODE_ID ": Quit %s\n", vqn->partition->num, vqn->nodeid, exit_status);
+
+ remove_node(vqn);
+ }
+ else {
+ fprintf(stderr, "Unknown child %d exited with status %d\n", pid, WEXITSTATUS(status));
+ }
+ }
+ if (WIFSIGNALED(status)) {
+ vqn = find_by_pid(pid);
+ if (vqn) {
+ printf("%d:" CS_PRI_NODE_ID " exited on signal %d%s\n", vqn->partition->num, vqn->nodeid, WTERMSIG(status), WCOREDUMP(status)?" (core dumped)":"");
+ remove_node(vqn);
+ }
+ else {
+ fprintf(stderr, "Unknown child %d exited with status %d%s\n", pid, WTERMSIG(status), WCOREDUMP(status)?" (core dumped)":"");
+ }
+ }
+ return 0;
+}
+
+static void send_partition_to_nodes(struct vq_partition *partition, int newring)
+{
+ struct vq_node *vqn;
+ int nodelist[MAX_NODES];
+ int nodes = 0;
+ int first = 1;
+
+ if (newring) {
+ /* Simulate corosync incrementing the seq by 4 for added authenticity */
+ partition->ring_id.seq += 4;
+ }
+
+ /* Build the node list */
+ TAILQ_FOREACH(vqn, &partition->nodelist, entries) {
+ nodelist[nodes++] = vqn->nodeid;
+ if (first) {
+ partition->ring_id.nodeid = vqn->nodeid;
+ first = 0;
+ }
+ }
+
+ TAILQ_FOREACH(vqn, &partition->nodelist, entries) {
+ vq_set_nodelist(vqn->instance, &partition->ring_id, nodelist, nodes);
+ }
+}
+
+static void init_partitions(void)
+{
+ int i;
+
+ for (i=0; i<MAX_PARTITIONS; i++) {
+ TAILQ_INIT(&partitions[i].nodelist);
+ partitions[i].ring_id.nodeid = 1000+i;
+ partitions[i].ring_id.seq = 0;
+ partitions[i].num = i;
+ }
+}
+
+static pid_t create_node(int nodeid, int partno)
+{
+ struct vq_node *newvq;
+
+ newvq = malloc(sizeof(struct vq_node));
+ if (newvq) {
+ newvq->last_quorate = -1; /* mark "uninitialized" */
+ newvq->instance = vq_create_instance(poll_loop, nodeid);
+ if (!newvq->instance) {
+ fprintf(stderr,
+ "ERR: could not create vq instance nodeid " CS_PRI_NODE_ID "\n",
+ nodeid);
+ free(newvq);
+ return (pid_t) -1;
+ }
+ newvq->partition = &partitions[partno];
+ newvq->nodeid = nodeid;
+ newvq->fd = vq_get_parent_fd(newvq->instance);
+ TAILQ_INSERT_TAIL(&partitions[partno].nodelist, newvq, entries);
+
+ if (qb_loop_poll_add(poll_loop,
+ QB_LOOP_MED,
+ newvq->fd,
+ POLLIN | POLLERR,
+ newvq,
+ vq_parent_read_fn)) {
+ perror("qb_loop_poll_add returned error");
+ return (pid_t) -1;
+ }
+
+ /* Send sync with all the nodes so far in it. */
+ send_partition_to_nodes(&partitions[partno], 1);
+ return vq_get_pid(newvq->instance);
+ }
+ return (pid_t) -1;
+}
+
+static size_t create_nodes_from_config(void)
+{
+ icmap_iter_t iter;
+ char tmp_key[ICMAP_KEYNAME_MAXLEN];
+ uint32_t node_pos;
+ uint32_t nodeid;
+ const char *iter_key;
+ int res;
+ pid_t pid;
+ size_t ret = 0;
+
+ init_partitions();
+
+ iter = icmap_iter_init("nodelist.node.");
+ while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
+ res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, tmp_key);
+ if (res != 2) {
+ continue;
+ }
+
+ if (strcmp(tmp_key, "ring0_addr") != 0) {
+ continue;
+ }
+
+ snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", node_pos);
+ if (icmap_get_uint32(tmp_key, &nodeid) == CS_OK) {
+ pid = create_node(nodeid, 0);
+ if (pid == (pid_t) -1) {
+ fprintf(stderr,
+ "ERR: nodeid " CS_PRI_NODE_ID " could not be spawned\n",
+ nodeid);
+ exit(1);
+ }
+ ret++;
+ }
+
+ }
+ icmap_iter_finalize(iter);
+
+ return ret;
+}
+
+static struct vq_node *find_node(int nodeid)
+{
+ int i;
+ struct vq_node *vqn;
+
+ for (i=0; i<MAX_PARTITIONS; i++) {
+ TAILQ_FOREACH(vqn, &partitions[i].nodelist, entries) {
+ if (vqn->nodeid == nodeid) {
+ return vqn;
+ }
+ }
+ }
+ return NULL;
+}
+
+static struct vq_node *find_by_pid(pid_t pid)
+{
+ int i;
+ struct vq_node *vqn;
+
+ for (i=0; i<MAX_PARTITIONS; i++) {
+ TAILQ_FOREACH(vqn, &partitions[i].nodelist, entries) {
+ if (vq_get_pid(vqn->instance) == pid) {
+ return vqn;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* Routines called from the parser */
+
+
+/*
+ * The parser calls this before running a command where
+ * we might have to wait for a result to come back.
+ */
+void cmd_start_sync_command()
+{
+ if (sync_cmds) {
+ qb_loop_poll_del(poll_loop, STDIN_FILENO);
+ qb_loop_timer_add(poll_loop,
+ QB_LOOP_MED,
+ command_timeout,
+ NULL,
+ finish_wait_timeout,
+ &kb_timer);
+ waiting_for_sync = 1;
+ }
+}
+
+int cmd_start_new_node(int nodeid, int partition)
+{
+ struct vq_node *node;
+
+ node = find_node(nodeid);
+ if (node) {
+ fprintf(stderr, "ERR: nodeid " CS_PRI_NODE_ID " already exists in partition %d\n", nodeid, node->partition->num);
+ return -1;
+ }
+ if (create_node(nodeid, partition) == -1) {
+ return -1;
+ }
+ return 0;
+}
+
+void cmd_stop_all_nodes()
+{
+ int i;
+ struct vq_node *vqn;
+
+ for (i=0; i<MAX_PARTITIONS; i++) {
+ TAILQ_FOREACH(vqn, &partitions[i].nodelist, entries) {
+ vq_quit(vqn->instance);
+ }
+ }
+}
+
+void cmd_show_node_states()
+{
+ int i;
+ struct vq_node *vqn;
+
+ for (i=0; i<MAX_PARTITIONS; i++) {
+ TAILQ_FOREACH(vqn, &partitions[i].nodelist, entries) {
+ print_quorum_state(vqn);
+ }
+ }
+ fprintf(output_file, "#autofence: %s\n", autofence?"on":"off");
+}
+
+int cmd_stop_node(int nodeid)
+{
+ struct vq_node *node;
+
+ node = find_node(nodeid);
+ if (!node) {
+ fprintf(stderr, "ERR: nodeid " CS_PRI_NODE_ID " is not up\n", nodeid);
+ return -1;
+ }
+
+ /* Remove processor */
+ vq_quit(node->instance);
+
+ /* Node will be removed when the child process exits */
+ return 0;
+}
+
+/* Move all nodes in 'nodelist' into partition 'partition' */
+void cmd_move_nodes(int partition, int num_nodes, int *nodelist)
+{
+ int i;
+ struct vq_node *node;
+ struct vq_node *vqn;
+ int total_nodes = num_nodes;
+
+ /* Work out the number of nodes affected */
+ TAILQ_FOREACH(vqn, &partitions[partition].nodelist, entries) {
+ total_nodes++;
+ }
+
+ for (i=0; i<num_nodes; i++) {
+ node = find_node(nodelist[i]);
+ if (node) {
+
+ /* Remove it from the current partition */
+ TAILQ_REMOVE(&node->partition->nodelist, node, entries);
+
+ /* Add it to the new partition */
+ TAILQ_INSERT_TAIL(&partitions[partition].nodelist, node, entries);
+ node->partition = &partitions[partition];
+ }
+ else {
+ printf("ERR: node " CS_PRI_NODE_ID " does not exist\n", nodelist[i]);
+ }
+ }
+}
+
+/* Take all the nodes in part2 and join them to part1 */
+void cmd_join_partitions(int part1, int part2)
+{
+ struct vq_node *vqn;
+
+ while (!TAILQ_EMPTY(&partitions[part2].nodelist)) {
+ vqn = TAILQ_FIRST(&partitions[part2].nodelist);
+ TAILQ_REMOVE(&vqn->partition->nodelist, vqn, entries);
+ TAILQ_INSERT_TAIL(&partitions[part1].nodelist, vqn, entries);
+ vqn->partition = &partitions[part1];
+ }
+}
+
+void cmd_set_autofence(int onoff)
+{
+ autofence = onoff;
+ fprintf(output_file, "#autofence: %s\n", onoff?"on":"off");
+}
+
+void cmd_set_sync(int onoff)
+{
+ autofence = onoff;
+ fprintf(output_file, "#sync: %s\n", onoff?"on":"off");
+ sync_cmds = onoff;
+}
+
+void cmd_set_assert(int onoff)
+{
+ assert_on_timeout = onoff;
+}
+
+void cmd_update_all_partitions(int newring)
+{
+ int i;
+
+ check_for_quorum = 1;
+ for (i=0; i<MAX_PARTITIONS; i++) {
+ send_partition_to_nodes(&partitions[i], newring);
+ }
+}
+
+void cmd_qdevice_poll(int nodeid, int onoff)
+{
+ struct vq_node *node;
+
+ node = find_node(nodeid);
+ if (node) {
+ vq_set_qdevice(node->instance, &node->partition->ring_id, onoff);
+ }
+}
+
+/* If we get called then a command has timed-out */
+static void finish_wait_timeout(void *data)
+{
+ if (command_timeout) {
+ fprintf(stderr, "ERR: Partition(s) not stable within timeout\n");
+ if (assert_on_timeout) {
+ exit(2);
+ }
+ }
+
+ resume_kb_input(sync_cmds);
+}
+
+void cmd_set_timeout(uint64_t seconds)
+{
+ command_timeout = seconds * QB_TIME_NS_IN_MSEC;
+}
+
+/* ---------------------------------- */
+
+#ifndef HAVE_READLINE_READLINE_H
+static void dummy_read_char(void);
+
+static void dummy_read_char()
+{
+ int c, flush = 0;
+
+ while (!flush) {
+ c = getchar();
+ if (++input_buf_term >= INPUT_BUF_SIZE) {
+ if (c != '\n' && c != EOF)
+ fprintf(stderr, "User input overflows the limit: %zu\n",
+ (size_t) INPUT_BUF_SIZE);
+ input_buf[INPUT_BUF_SIZE - 1] = '\0';
+ flush = 1;
+ } else if (c == '\n' || c == EOF) {
+ input_buf[input_buf_term - 1] = '\0';
+ flush = 1;
+ } else {
+ input_buf[input_buf_term - 1] = c;
+ }
+ }
+
+ parse_input_command((c == EOF) ? NULL : input_buf);
+ input_buf_term = 0;
+}
+#endif
+
+static int stdin_read_fn(int32_t fd, int32_t revents, void *data)
+{
+#ifdef HAVE_READLINE_READLINE_H
+ /* Send it to readline */
+ rl_callback_read_char();
+#else
+ dummy_read_char();
+#endif
+ return 0;
+}
+
+
+static void start_kb_input_timeout(void *data)
+{
+ resume_kb_input(1);
+}
+
+static void usage(char *program)
+{
+ printf("Usage:\n");
+ printf("\n");
+ printf("%s [-c <config-file>] [-o <output-file>]\n", program);
+ printf("\n");
+ printf(" -c config file. defaults to /etc/corosync/corosync.conf\n");
+ printf(" -o output file. defaults to stdout\n");
+ printf(" -n no synchronization (on adding a node)\n");
+ printf(" -h display this help text\n");
+ printf("\n");
+ printf("%s always takes input from STDIN, but cannot use a file.\n", program);
+ printf("If you want to script it then use\n cat | %s\n", program);
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ qb_loop_signal_handle sigchld_qb_handle;
+ int ch;
+ char *output_file_name = NULL;
+
+ while ((ch = getopt (argc, argv, "c:o:nh")) != EOF) {
+ switch (ch) {
+ case 'c':
+ if (strlen(optarg) >= sizeof(sizeof(corosync_config_file) - 1)) {
+ fprintf(stderr, "Corosync config file path too long\n");
+ exit(1);
+ }
+ strncpy(corosync_config_file, optarg, sizeof(corosync_config_file) - 1);
+ break;
+ case 'o':
+ output_file_name = optarg;
+ break;
+ case 'n':
+ sync_cmds = 0;
+ break;
+ default:
+ usage(argv[0]);
+ exit(0);
+ }
+ }
+
+ if (output_file_name) {
+ output_file = fopen(output_file_name, "w");
+ if (!output_file) {
+ fprintf(stderr, "Unable to open %s for output: %s\n", output_file_name, strerror(errno));
+ exit(3);
+ }
+ }
+ else {
+ output_file = stdout;
+ }
+
+ is_tty = isatty(STDIN_FILENO);
+
+ qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
+ QB_LOG_FILTER_FUNCTION, "*", LOG_DEBUG);
+
+ qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
+ qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
+ QB_LOG_FILTER_FUNCTION, "*", LOG_DEBUG);
+
+ poll_loop = qb_loop_create();
+
+ /* SIGCHLD handler to reap sub-processes and reconfigure the cluster */
+ qb_loop_signal_add(poll_loop,
+ QB_LOOP_MED,
+ SIGCHLD,
+ NULL,
+ sigchld_handler,
+ &sigchld_qb_handle);
+
+
+#ifdef HAVE_READLINE_READLINE_H
+ /* Readline will deal with completed lines when they arrive */
+ /*
+ * For scripting add '#' to the start of the prompt so that
+ * parsers can ignore input lines
+ */
+ rl_already_prompted = 1;
+ if (is_tty) {
+ rl_callback_handler_install("vqsim> ", parse_input_command);
+ } else {
+ rl_callback_handler_install("#vqsim> ", parse_input_command);
+ }
+#endif
+
+
+
+/* Create a full cluster of nodes from corosync.conf */
+ read_corosync_conf();
+ if (create_nodes_from_config() && sync_cmds) {
+ /* Delay kb input handling by 1 second when we've just
+ added the nodes from corosync.conf; expect that
+ the delay will be cancelled substantially earlier
+ once they all have reported their quorum info
+ (the delay is in fact a failsafe input enabler here) */
+ qb_loop_timer_add(poll_loop,
+ QB_LOOP_MED,
+ 1000000000,
+ NULL,
+ start_kb_input_timeout,
+ &kb_timer);
+ waiting_for_sync = 1;
+ } else {
+ resume_kb_input(0);
+ }
+
+ qb_loop_run(poll_loop);
+ return 0;
+}
diff --git a/vqsim/vqsim.h b/vqsim/vqsim.h
new file mode 100644
index 0000000..0c4c973
--- /dev/null
+++ b/vqsim/vqsim.h
@@ -0,0 +1,82 @@
+
+typedef enum {VQMSG_QUIT=1,
+ VQMSG_SYNC, /* set nodelist */
+ VQMSG_QUORUM, /* quorum state of this 'node' */
+ VQMSG_EXEC, /* message for exec_handler */
+ VQMSG_QDEVICE, /* quorum device enable/disable */
+ VQMSG_QUORUMQUIT, /* quit if you don't have quorum */
+} vqsim_msg_type_t;
+
+typedef struct vq_instance *vq_object_t;
+
+struct vqsim_msg_header
+{
+ vqsim_msg_type_t type;
+ int from_nodeid;
+ int param;
+};
+
+/* This is the sync sent from the controller process */
+struct vqsim_sync_msg
+{
+ struct vqsim_msg_header header;
+ struct memb_ring_id ring_id;
+ size_t view_list_entries;
+ unsigned int view_list[];
+};
+
+/* This is just info sent from each VQ instance */
+struct vqsim_quorum_msg
+{
+ struct vqsim_msg_header header;
+ int quorate;
+ struct memb_ring_id ring_id;
+ size_t view_list_entries;
+ unsigned int view_list[];
+};
+
+struct vqsim_exec_msg
+{
+ struct vqsim_msg_header header;
+ char execmsg[];
+};
+
+struct vqsim_lib_msg
+{
+ struct vqsim_msg_header header;
+ char libmsg[];
+};
+
+#define MAX_NODES 1024
+#define MAX_PARTITIONS 16
+
+/* In vq_object.c */
+vq_object_t vq_create_instance(qb_loop_t *poll_loop, int nodeid);
+void vq_quit(vq_object_t instance);
+int vq_set_nodelist(vq_object_t instance, struct memb_ring_id *ring_id, int *nodeids, int nodeids_entries);
+int vq_get_parent_fd(vq_object_t instance);
+int vq_set_qdevice(vq_object_t instance, struct memb_ring_id *ring_id, int onoff);
+int vq_quit_if_inquorate(vq_object_t instance);
+pid_t vq_get_pid(vq_object_t instance);
+
+/* in vqsim_vq_engine.c - effectively the constructor */
+int fork_new_instance(int nodeid, int *vq_sock, pid_t *child_pid);
+
+/* In parser.c */
+void parse_input_command(char *cmd);
+
+/* These are in vqmain.c */
+int cmd_stop_node(int nodeid);
+void cmd_stop_all_nodes(void);
+int cmd_start_new_node(int nodeid, int partition);
+void cmd_set_autofence(int onoff);
+void cmd_set_sync(int onoff);
+void cmd_set_assert(int onoff);
+void cmd_move_nodes(int partition, int num_nodes, int *nodelist);
+void cmd_join_partitions(int part1, int part2);
+void cmd_update_all_partitions(int newring);
+void cmd_qdevice_poll(int nodeid, int onoff);
+void cmd_show_node_states(void);
+void cmd_set_timeout(uint64_t seconds);
+void cmd_start_sync_command(void);
+void resume_kb_input(int show_state);
diff --git a/vqsim/vqsim_vq_engine.c b/vqsim/vqsim_vq_engine.c
new file mode 100644
index 0000000..e0bb0bd
--- /dev/null
+++ b/vqsim/vqsim_vq_engine.c
@@ -0,0 +1,479 @@
+
+/* This is the bit of VQSIM that runs in the forked process.
+ It represents a single votequorum instance or, if you like,
+ a 'node' in the cluster.
+*/
+
+#include <sys/types.h>
+#include <qb/qblog.h>
+#include <qb/qbloop.h>
+#include <qb/qbipc_common.h>
+#include <netinet/in.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <stdio.h>
+
+#include "../exec/votequorum.h"
+#include "../exec/service.h"
+#include "../include/corosync/corotypes.h"
+#include "../include/corosync/votequorum.h"
+#include "../include/corosync/ipc_votequorum.h"
+#include <corosync/logsys.h>
+#include <corosync/coroapi.h>
+
+#include "icmap.h"
+#include "vqsim.h"
+
+#define QDEVICE_NAME "VQsim_qdevice"
+
+/* Static variables here are per-instance because we are forked */
+static struct corosync_service_engine *engine;
+static int parent_socket; /* Our end of the socket */
+static char buffer[8192];
+static int our_nodeid;
+static char *private_data;
+static qb_loop_t *poll_loop;
+static qb_loop_timer_handle sync_timer;
+static qb_loop_timer_handle qdevice_timer;
+static int we_are_quorate;
+static void *fake_conn = (void*)1;
+static cs_error_t last_lib_error;
+static struct memb_ring_id current_ring_id;
+static int qdevice_registered;
+static unsigned int qdevice_timeout = VOTEQUORUM_QDEVICE_DEFAULT_TIMEOUT;
+
+/* 'Keep the compiler happy' time */
+char *get_run_dir(void);
+
+int api_timer_add_duration (
+ unsigned long long nanosec_duration,
+ void *data,
+ void (*timer_fn) (void *data),
+ corosync_timer_handle_t *handle);
+
+static void api_error_memory_failure(void) __attribute__((noreturn));
+static void api_error_memory_failure()
+{
+ fprintf(stderr, "Out of memory error\n");
+ exit(-1);
+}
+static void api_timer_delete(corosync_timer_handle_t th)
+{
+ qb_loop_timer_del(poll_loop, th);
+}
+
+int api_timer_add_duration (
+ unsigned long long nanosec_duration,
+ void *data,
+ void (*timer_fn) (void *data),
+ corosync_timer_handle_t *handle)
+{
+ return qb_loop_timer_add(poll_loop,
+ QB_LOOP_MED,
+ nanosec_duration,
+ data,
+ timer_fn,
+ handle);
+}
+
+static unsigned int api_totem_nodeid_get(void)
+{
+ return our_nodeid;
+}
+
+static int api_totem_mcast(const struct iovec *iov, unsigned int iovlen, unsigned int type)
+{
+ struct vqsim_msg_header header;
+ struct iovec iovec[iovlen+1];
+ int total = sizeof(header);
+ int res;
+ int i;
+
+ header.type = VQMSG_EXEC;
+ header.from_nodeid = our_nodeid;
+ header.param = 0;
+
+ iovec[0].iov_base = &header;
+ iovec[0].iov_len = sizeof(header);
+ for (i=0; i<iovlen; i++) {
+ iovec[i+1].iov_base = iov[i].iov_base;
+ iovec[i+1].iov_len = iov[i].iov_len;
+ total += iov[i].iov_len;
+ }
+
+ res = writev(parent_socket, iovec, iovlen+1);
+ if (res != total) {
+ fprintf(stderr, "writev wrote only %d of %d bytes\n", res, total);
+ }
+ return 0;
+}
+static void *api_ipc_private_data_get(void *conn)
+{
+ return private_data;
+}
+static int api_ipc_response_send(void *conn, const void *msg, size_t len)
+{
+ struct qb_ipc_response_header *qb_header = (void*)msg;
+
+ /* Save the error so we can return it */
+ last_lib_error = qb_header->error;
+ return 0;
+}
+
+static struct corosync_api_v1 corosync_api = {
+ .error_memory_failure = api_error_memory_failure,
+ .timer_delete = api_timer_delete,
+ .timer_add_duration = api_timer_add_duration,
+ .totem_nodeid_get = api_totem_nodeid_get,
+ .totem_mcast = api_totem_mcast,
+ .ipc_private_data_get = api_ipc_private_data_get,
+ .ipc_response_send = api_ipc_response_send,
+};
+
+/* -------------------- Above is all for providing the corosync_api support routines --------------------------------------------*/
+/* They need to be in the same file as the engine as they use the local 'poll_loop' variable which is per-process */
+
+static void start_qdevice_poll(int longwait);
+static void start_sync_timer(void);
+
+/* Callback from Votequorum to tell us about the quorum state */
+static void quorum_fn(const unsigned int *view_list,
+ size_t view_list_entries,
+ int quorate, struct memb_ring_id *ring_id)
+{
+ char msgbuf[8192];
+ int len;
+ struct vqsim_quorum_msg *quorum_msg = (void*) msgbuf;
+
+ we_are_quorate = quorate;
+
+ /* Send back to parent */
+ quorum_msg->header.type = VQMSG_QUORUM;
+ quorum_msg->header.from_nodeid = our_nodeid;
+ quorum_msg->header.param = 0;
+ quorum_msg->quorate = quorate;
+ memcpy(&quorum_msg->ring_id, ring_id, sizeof(*ring_id));
+ quorum_msg->view_list_entries = view_list_entries;
+
+ memcpy(quorum_msg->view_list, view_list, sizeof(unsigned int)*view_list_entries);
+
+ if ( (len=write(parent_socket, msgbuf, sizeof(*quorum_msg) + sizeof(unsigned int)*view_list_entries)) <= 0) {
+ perror("write (view list to parent) failed");
+ }
+ memcpy(&current_ring_id, ring_id, sizeof(*ring_id));
+}
+
+char *corosync_service_link_and_init(struct corosync_api_v1 *api,
+ struct default_service *service_engine)
+{
+ /* dummy */
+ return NULL;
+}
+
+/* For votequorum */
+char *get_run_dir()
+{
+ static char cwd_buffer[PATH_MAX];
+
+ return getcwd(cwd_buffer, PATH_MAX);
+}
+
+/* This is different to the one in totemconfig.c in that we already
+ * know the 'local' node ID, so we can just search for that.
+ * It needs to be here rather than at main config read time as it's
+ * (obviously) going to be different for each instance.
+ */
+static void set_local_node_pos(struct corosync_api_v1 *api)
+{
+ icmap_iter_t iter;
+ uint32_t node_pos;
+ char name_str[ICMAP_KEYNAME_MAXLEN];
+ uint32_t nodeid;
+ const char *iter_key;
+ int res;
+ int found = 0;
+
+ iter = icmap_iter_init("nodelist.node.");
+ while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
+ res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, name_str);
+ if (res != 2) {
+ continue;
+ }
+ if (strcmp(name_str, "nodeid")) {
+ continue;
+ }
+
+ res = icmap_get_uint32(iter_key, &nodeid);
+ if (res == CS_OK) {
+ if (nodeid == our_nodeid) {
+ found = 1;
+ res = icmap_set_uint32("nodelist.local_node_pos", node_pos);
+ assert(res == CS_OK);
+ }
+ }
+ }
+ if (!found) {
+ /* This probably indicates a dynamically-added node
+ * set the pos to zero and use the votes of the
+ * first node in corosync.conf
+ */
+ res = icmap_set_uint32("nodelist.local_node_pos", 0);
+ assert(res == CS_OK);
+ }
+}
+
+static int load_quorum_instance(struct corosync_api_v1 *api)
+{
+ const char *error_string;
+ int res;
+
+ error_string = votequorum_init(api, quorum_fn);
+ if (error_string) {
+ fprintf(stderr, "Votequorum init failed: %s\n", error_string);
+ return -1;
+ }
+
+ engine = votequorum_get_service_engine_ver0();
+ error_string = engine->exec_init_fn(api);
+ if (error_string) {
+ fprintf(stderr, "votequorum exec init failed: %s\n", error_string);
+ return -1;
+ }
+
+ private_data = malloc(engine->private_data_size);
+ if (!private_data) {
+ perror("Malloc in child failed");
+ return -1;
+ }
+
+ res = engine->lib_init_fn(fake_conn);
+
+ return res;
+}
+
+static void sync_dispatch_fn(void *data)
+{
+ if (engine->sync_process()) {
+ start_sync_timer();
+ }
+ else {
+ engine->sync_activate();
+ }
+}
+
+static void start_sync_timer()
+{
+ qb_loop_timer_add(poll_loop,
+ QB_LOOP_MED,
+ 10000000,
+ NULL,
+ sync_dispatch_fn,
+ &sync_timer);
+}
+
+static void send_sync(char *buf, int len)
+{
+ struct vqsim_sync_msg *msg = (void*)buf;
+
+ /* Votequorum doesn't use the transitional node list :-) */
+ engine->sync_init(NULL, 0,
+ msg->view_list, msg->view_list_entries,
+ &msg->ring_id);
+
+ start_sync_timer();
+}
+
+static void send_exec_msg(char *buf, int len)
+{
+ struct vqsim_exec_msg *execmsg = (void*)buf;
+ struct qb_ipc_request_header *qb_header = (void*)execmsg->execmsg;
+
+ engine->exec_engine[qb_header->id & 0xFFFF].exec_handler_fn(execmsg->execmsg, execmsg->header.from_nodeid);
+}
+
+static int send_lib_msg(int type, void *msg)
+{
+ /* Clear this as not all lib functions return a response immediately */
+ last_lib_error = CS_OK;
+
+ engine->lib_engine[type].lib_handler_fn(fake_conn, msg);
+
+ return last_lib_error;
+}
+
+static int poll_qdevice(int onoff)
+{
+ struct req_lib_votequorum_qdevice_poll pollmsg;
+ int res;
+
+ pollmsg.cast_vote = onoff;
+ pollmsg.ring_id.nodeid = current_ring_id.nodeid;
+ pollmsg.ring_id.seq = current_ring_id.seq;
+ strcpy(pollmsg.name, QDEVICE_NAME);
+
+ res = send_lib_msg(MESSAGE_REQ_VOTEQUORUM_QDEVICE_POLL, &pollmsg);
+ if (res != CS_OK) {
+ fprintf(stderr, CS_PRI_NODE_ID ": qdevice poll failed: %d\n", our_nodeid, res);
+ }
+ return res;
+}
+
+static void qdevice_dispatch_fn(void *data)
+{
+ if (poll_qdevice(1) == CS_OK) {
+ start_qdevice_poll(0);
+ }
+}
+
+static void start_qdevice_poll(int longwait)
+{
+ unsigned long long timeout;
+
+ timeout = (unsigned long long)qdevice_timeout*500000; /* Half the corosync timeout */
+ if (longwait) {
+ timeout *= 2;
+ }
+
+ qb_loop_timer_add(poll_loop,
+ QB_LOOP_MED,
+ timeout,
+ NULL,
+ qdevice_dispatch_fn,
+ &qdevice_timer);
+}
+
+static void stop_qdevice_poll(void)
+{
+ qb_loop_timer_del(poll_loop, qdevice_timer);
+ qdevice_timer = 0;
+}
+
+static void do_qdevice(int onoff)
+{
+ int res;
+
+ if (onoff) {
+ if (!qdevice_registered) {
+ struct req_lib_votequorum_qdevice_register regmsg;
+
+ strcpy(regmsg.name, QDEVICE_NAME);
+ if ( (res=send_lib_msg(MESSAGE_REQ_VOTEQUORUM_QDEVICE_REGISTER, &regmsg)) == CS_OK) {
+ qdevice_registered = 1;
+ start_qdevice_poll(1);
+ }
+ else {
+ fprintf(stderr, CS_PRI_NODE_ID ": qdevice registration failed: %d\n", our_nodeid, res);
+ }
+ }
+ else {
+ if (!qdevice_timer) {
+ start_qdevice_poll(0);
+ }
+ }
+ }
+ else {
+ poll_qdevice(0);
+ stop_qdevice_poll();
+ }
+}
+
+
+/* From controller */
+static int parent_pipe_read_fn(int32_t fd, int32_t revents, void *data)
+{
+ struct vqsim_msg_header *header = (void*)buffer;
+ int len;
+
+ len = read(fd, buffer, sizeof(buffer));
+ if (len > 0) {
+ /* Check header and route */
+ switch (header->type) {
+ case VQMSG_QUIT:
+ exit(0);
+ break;
+ case VQMSG_EXEC: /* For votequorum exec messages */
+ send_exec_msg(buffer, len);
+ break;
+ case VQMSG_SYNC:
+ send_sync(buffer, len);
+ break;
+ case VQMSG_QDEVICE:
+ do_qdevice(header->param);
+ break;
+ case VQMSG_QUORUMQUIT:
+ if (!we_are_quorate) {
+ exit(1);
+ }
+ break;
+ case VQMSG_QUORUM:
+ /* not used here */
+ break;
+ }
+ }
+ return 0;
+}
+
+static void initial_sync(int nodeid)
+{
+ unsigned int trans_list[1] = {nodeid};
+ unsigned int member_list[1] = {nodeid};
+ struct memb_ring_id ring_id;
+
+ ring_id.nodeid = our_nodeid;
+ ring_id.seq = 1;
+
+ /* cluster with just us in it */
+ engine->sync_init(trans_list, 1,
+ member_list, 1,
+ &ring_id);
+ start_sync_timer();
+}
+
+/* Return pipe FDs & child PID if sucessful */
+int fork_new_instance(int nodeid, int *vq_sock, pid_t *childpid)
+{
+ int pipes[2];
+ pid_t pid;
+
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, pipes)) {
+ return -1;
+ }
+ parent_socket = pipes[0];
+
+ switch ( (pid=fork()) ) {
+ case -1:
+ perror("fork failed");
+ return -1;
+ case 0:
+ /* child process - continue below */
+ break;
+ default:
+ /* parent process */
+ *vq_sock = pipes[1];
+ *childpid = pid;
+ return 0;
+ }
+
+ our_nodeid = nodeid;
+ poll_loop = qb_loop_create();
+
+ if (icmap_get_uint32("quorum.device.timeout", &qdevice_timeout) != CS_OK) {
+ qdevice_timeout = VOTEQUORUM_QDEVICE_DEFAULT_TIMEOUT;
+ }
+
+ set_local_node_pos(&corosync_api);
+ load_quorum_instance(&corosync_api);
+
+ qb_loop_poll_add(poll_loop,
+ QB_LOOP_MED,
+ parent_socket,
+ POLLIN,
+ NULL,
+ parent_pipe_read_fn);
+
+ /* Start it up! */
+ initial_sync(nodeid);
+ qb_loop_run(poll_loop);
+
+ return 0;
+}