Hello community,

here is the log from the commit of package booth for openSUSE:Factory checked 
in at 2014-07-11 06:45:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/booth (Old)
 and      /work/SRC/openSUSE:Factory/.booth.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "booth"

Changes:
--------
--- /work/SRC/openSUSE:Factory/booth/booth.changes      2014-06-30 
21:50:27.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.booth.new/booth.changes 2014-07-11 
06:45:47.000000000 +0200
@@ -1,0 +2,11 @@
+Thu Jul  3 15:36:32 UTC 2014 - [email protected]
+
+- add git version info and GNUmakefile for easier rpm package building
+- raft: make sure that elections restart if the last candidate disappears 
+- use monotonic clock if available (bnc#884746) 
+- raft: reset election on rejects too 
+- raft: accept OP_UPDATE in candidate and init states too 
+- ticket: don't write to CIB if we're in elections 
+- upstream version: ff5b114
+
+-------------------------------------------------------------------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ booth.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/.git_info new/booth/.git_info
--- old/booth/.git_info 1970-01-01 01:00:00.000000000 +0100
+++ new/booth/.git_info 2014-07-03 17:36:56.000000000 +0200
@@ -0,0 +1 @@
+v0.1.7-262-gff5b114
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/.gitignore new/booth/.gitignore
--- old/booth/.gitignore        2014-06-26 19:31:25.000000000 +0200
+++ new/booth/.gitignore        2014-07-03 17:11:10.000000000 +0200
@@ -9,6 +9,9 @@
 depcomp
 install-sh
 missing
+booth.tar.bz2
+*.rpm
+Doxyfile
 src/.deps
 src/Makefile.in
 src/b_config.h.in
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/GNUmakefile new/booth/GNUmakefile
--- old/booth/GNUmakefile       1970-01-01 01:00:00.000000000 +0100
+++ new/booth/GNUmakefile       2014-07-03 17:11:10.000000000 +0200
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2008 Andrew Beekhof
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+
+-include Makefile
+
+PACKAGE                ?= booth
+TARFILE                = $(PACKAGE).tar.bz2
+
+RPM_ROOT       = $(shell pwd)
+RPM_OPTS       = --define "_sourcedir $(RPM_ROOT)"     \
+                 --define "_specdir $(RPM_ROOT)"       \
+                 --define "_srcrpmdir $(RPM_ROOT)"
+
+
+TAG    ?= HEAD
+
+gitarchive:
+       rm -f $(TARFILE)
+       git archive --format=tar --prefix $(PACKAGE)/ $(TAG) | tar xf -
+       git describe --tags --always > $(PACKAGE)/.git_info
+       tar -cjf $(TARFILE) $(PACKAGE)
+       rm -r $(PACKAGE)
+       echo `date`: Rebuilt $(TARFILE)
+
+srpm:  gitarchive
+       rm -f *.src.rpm
+       @echo To create custom builds, edit the flags and options in 
$(PACKAGE).spec first
+       rpmbuild -bs $(RPM_OPTS) $(PACKAGE).spec
+
+rpm:   srpm
+       rpmbuild $(RPM_OPTS) --rebuild $(RPM_ROOT)/*.src.rpm
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/booth-rpmlintrc new/booth/booth-rpmlintrc
--- old/booth/booth-rpmlintrc   1970-01-01 01:00:00.000000000 +0100
+++ new/booth/booth-rpmlintrc   2014-07-03 17:11:10.000000000 +0200
@@ -0,0 +1,3 @@
+addFilter("incoherent-init-script-name")
+addFilter("init-script-without-%insserv_cleanup-postun")
+addFilter("init-script-without-%stop_on_removal-preun")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/booth.spec new/booth/booth.spec
--- old/booth/booth.spec        1970-01-01 01:00:00.000000000 +0100
+++ new/booth/booth.spec        2014-07-03 17:11:10.000000000 +0200
@@ -0,0 +1,119 @@
+
+%global test_path      %{_datadir}/booth/tests
+
+%if 0%{?suse_version}
+%define _libexecdir %{_libdir}
+%endif
+%define with_extra_warnings    0
+%define with_debugging         0
+%define without_fatal_warnings         1
+%if 0%{?fedora_version} || 0%{?centos_version} || 0%{?rhel_version}
+%define pkg_group System Environment/Daemons
+%else
+%define pkg_group Productivity/Clustering/HA
+%endif
+
+Name:           booth
+Summary:        Ticket Manager for Multi-site Clusters
+License:        GPL-2.0+
+Group:          %{pkg_group}
+Version:        0.2.0
+Release:        0
+Source:         booth.tar.bz2
+Source1:        %name-rpmlintrc
+BuildRoot:      %{_tmppath}/%{name}-%{version}-build
+BuildRequires:  asciidoc
+BuildRequires:  autoconf
+BuildRequires:  automake
+BuildRequires:  glib2-devel
+BuildRequires:  libglue-devel
+BuildRequires:  libpacemaker-devel
+BuildRequires:  libxml2-devel
+BuildRequires:  pkgconfig
+# the following is probably SUSE specific
+Requires:       pacemaker-ticket-support >= 2.0
+
+%description
+Booth manages the ticket which authorizes one of the cluster sites located in
+geographically dispersed distances to run certain resources. It is designed to
+be an add-on of Pacemaker, which extends Pacemaker to support geographically
+distributed clustering.
+
+%prep
+%setup -q -n %{name}
+
+%build
+./autogen.sh
+%configure \
+       --with-initddir=%{_initrddir}
+
+make
+
+#except check
+#%check
+#make check
+
+%install
+make DESTDIR=$RPM_BUILD_ROOT install docdir=%{_defaultdocdir}/%{name}
+
+mkdir -p %{buildroot}/%{_mandir}/man8/
+gzip < docs/boothd.8 > %{buildroot}/%{_mandir}/man8/booth.8.gz
+ln %{buildroot}/%{_mandir}/man8/booth.8.gz 
%{buildroot}/%{_mandir}/man8/boothd.8.gz 
+
+# systemd
+mkdir -p %{buildroot}/usr/lib/systemd/system/
+cp -a conf/[email protected] %{buildroot}/usr/lib/systemd/system/[email protected]
+
+#install test-parts
+
+mkdir -p %{buildroot}/%{test_path}
+cp -a unit-tests/ script/unit-test.py test conf %{buildroot}/%{test_path}/
+chmod +x %{buildroot}/%{test_path}/booth_path
+chmod +x %{buildroot}/%{test_path}/live_test.sh
+
+mkdir -p %{buildroot}/%{test_path}/src/
+ln -s %{_sbindir}/boothd %{buildroot}/%{test_path}/src/
+rm -f %{buildroot}/%{test_path}/test/*.pyc
+
+%clean
+rm -rf %{buildroot}
+
+%files
+%defattr(-,root,root,-)
+%{_sbindir}/booth
+%{_sbindir}/boothd
+%{_initrddir}/booth-arbitrator
+%{_mandir}/man8/booth.8.gz
+%{_mandir}/man8/boothd.8.gz
+%dir /usr/lib/ocf
+%dir /usr/lib/ocf/resource.d
+%dir /usr/lib/ocf/resource.d/pacemaker
+%dir %{_sysconfdir}/booth
+/usr/lib/ocf/resource.d/pacemaker/booth-site
+%config %{_sysconfdir}/booth/booth.conf.example
+
+/usr/lib/systemd/system/[email protected]
+
+%dir %{_datadir}/booth
+%{_datadir}/booth/service-runnable
+
+%doc README COPYING
+
+
+%package test
+Summary:        Test scripts for Booth
+Group:          %{pkg_group}
+Requires:       booth
+Requires:       python
+
+%description test
+This package contains automated tests for Booth,
+the Cluster Ticket Manager for Pacemaker.
+
+%files test
+%defattr(-,root,root)
+
+%doc README-testing
+%{test_path}
+
+%changelog
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/booth.spec.in new/booth/booth.spec.in
--- old/booth/booth.spec.in     2014-06-26 19:31:25.000000000 +0200
+++ new/booth/booth.spec.in     1970-01-01 01:00:00.000000000 +0100
@@ -1,119 +0,0 @@
-
-%global test_path      %{_datadir}/booth/tests
-
-%if 0%{?suse_version}
-%define _libexecdir %{_libdir}
-%endif
-%define with_extra_warnings    0
-%define with_debugging         0
-%define without_fatal_warnings         1
-%if 0%{?fedora_version} || 0%{?centos_version} || 0%{?rhel_version}
-%define pkg_group System Environment/Daemons
-%else
-%define pkg_group Productivity/Clustering/HA
-%endif
-
-Name:           booth
-Summary:        Ticket Manager for Multi-site Clusters
-License:        GPL-2.0+
-Group:          %{pkg_group}
-Version:        @version@
-Release:        0
-Source:         booth.tar.bz2
-Source1:        %name-rpmlintrc
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-BuildRequires:  asciidoc
-BuildRequires:  autoconf
-BuildRequires:  automake
-BuildRequires:  glib2-devel
-BuildRequires:  libglue-devel
-BuildRequires:  libpacemaker-devel
-BuildRequires:  libxml2-devel
-BuildRequires:  pkgconfig
-# the following is probably SUSE specific
-Requires:       pacemaker-ticket-support >= 2.0
-
-%description
-Booth manages the ticket which authorizes one of the cluster sites located in
-geographically dispersed distances to run certain resources. It is designed to
-be an add-on of Pacemaker, which extends Pacemaker to support geographically
-distributed clustering.
-
-%prep
-%setup -q -n %{name}
-
-%build
-./autogen.sh
-%configure \
-       --with-initddir=%{_initrddir}
-
-make
-
-#except check
-#%check
-#make check
-
-%install
-make DESTDIR=$RPM_BUILD_ROOT install docdir=%{_defaultdocdir}/%{name}
-
-mkdir -p %{buildroot}/%{_mandir}/man8/
-gzip < docs/boothd.8 > %{buildroot}/%{_mandir}/man8/booth.8.gz
-ln %{buildroot}/%{_mandir}/man8/booth.8.gz 
%{buildroot}/%{_mandir}/man8/boothd.8.gz 
-
-# systemd
-mkdir -p %{buildroot}/usr/lib/systemd/system/
-cp -a conf/[email protected] %{buildroot}/usr/lib/systemd/system/[email protected]
-
-#install test-parts
-
-mkdir -p %{buildroot}/%{test_path}
-cp -a unit-tests/ script/unit-test.py test conf %{buildroot}/%{test_path}/
-chmod +x %{buildroot}/%{test_path}/booth_path
-chmod +x %{buildroot}/%{test_path}/live_test.sh
-
-mkdir -p %{buildroot}/%{test_path}/src/
-ln -s %{_sbindir}/boothd %{buildroot}/%{test_path}/src/
-rm -f %{buildroot}/%{test_path}/test/*.pyc
-
-%clean
-rm -rf %{buildroot}
-
-%files
-%defattr(-,root,root,-)
-%{_sbindir}/booth
-%{_sbindir}/boothd
-%{_initrddir}/booth-arbitrator
-%{_mandir}/man8/booth.8.gz
-%{_mandir}/man8/boothd.8.gz
-%dir /usr/lib/ocf
-%dir /usr/lib/ocf/resource.d
-%dir /usr/lib/ocf/resource.d/pacemaker
-%dir %{_sysconfdir}/booth
-/usr/lib/ocf/resource.d/pacemaker/booth-site
-%config %{_sysconfdir}/booth/booth.conf.example
-
-/usr/lib/systemd/system/[email protected]
-
-%dir %{_datadir}/booth
-%{_datadir}/booth/service-runnable
-
-%doc README COPYING
-
-
-%package test
-Summary:        Test scripts for Booth
-Group:          %{pkg_group}
-Requires:       booth
-Requires:       python
-
-%description test
-This package contains automated tests for Booth,
-the Cluster Ticket Manager for Pacemaker.
-
-%files test
-%defattr(-,root,root)
-
-%doc README-testing
-%{test_path}
-
-%changelog
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/configure.ac new/booth/configure.ac
--- old/booth/configure.ac      2014-06-26 19:31:25.000000000 +0200
+++ new/booth/configure.ac      2014-07-03 17:11:10.000000000 +0200
@@ -180,6 +180,14 @@
        [ INITDDIR="$withval" ],
        [ INITDDIR="$sysconfdir/init.d" ])
 
+test -s .git_info &&
+       BOOTH_BUILD_VERSION="`cat .git_info`"
+
+AC_ARG_WITH([build-version],
+       [  --with-build-version=STR     : build version ],
+       [ BOOTH_BUILD_VERSION="$withval" ],
+       [ ])
+
 AC_ARG_ENABLE([resource-monitor],
        [  --enable-resource-monitor       : Enabling Resource Monitor ],
        [ default="no" ])
@@ -281,6 +289,16 @@
        GDB_FLAGS="-g"
 fi
 
+dnl Check for POSIX clock_gettime
+dnl
+AC_CACHE_CHECK([have clock_gettime],ac_cv_HAVE_CLOCK_GETTIME,[
+AC_TRY_COMPILE([
+#include <time.h>
+],
+[ struct timespec tv; clock_gettime(CLOCK_REALTIME, &tv); return 0;],
+ac_cv_HAVE_CLOCK_GETTIME=yes,ac_cv_HAVE_CLOCK_GETTIME=no,ac_cv_HAVE_CLOCK_GETTIME=cross)])
+AM_CONDITIONAL(BUILD_TIMER_C, test x"$ac_cv_HAVE_CLOCK_GETTIME" = x"yes")
+
 # extra warnings
 EXTRA_WARNINGS=""
 
@@ -387,15 +405,18 @@
 AC_SUBST([HAVE_LOG_CIB_DIFF])
 AC_SUBST([HAVE_XML_LOG_PATCHSET])
 AC_SUBST([BOOTHSYSCONFDIR])
+AC_SUBST([BOOTH_BUILD_VERSION])
 AC_DEFINE_UNQUOTED([BOOTHSYSCONFDIR], "$(eval echo ${BOOTHSYSCONFDIR})", 
[booth config directory])
 
 AC_DEFINE_UNQUOTED([PACKAGE_FEATURES], "${PACKAGE_FEATURES}", [booth built-in 
features])
 
+AC_DEFINE_UNQUOTED([BOOTH_BUILD_VERSION], "${BOOTH_BUILD_VERSION}", [booth 
build version])
+
 AC_OUTPUT
 
 AC_MSG_RESULT([])
 AC_MSG_RESULT([$PACKAGE configuration:])
-AC_MSG_RESULT([  Version                  = ${VERSION}])
+AC_MSG_RESULT([  Version                  = ${VERSION} (Build: 
${BOOTH_BUILD_VERSION})])
 AC_MSG_RESULT([  Prefix                   = ${prefix}])
 AC_MSG_RESULT([  Executables              = ${sbindir}])
 AC_MSG_RESULT([  Man pages                = ${mandir}])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/Makefile.am new/booth/src/Makefile.am
--- old/booth/src/Makefile.am   2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/Makefile.am   2014-07-03 17:11:10.000000000 +0200
@@ -10,6 +10,10 @@
 boothd_SOURCES         = config.c main.c raft.c ticket.c  transport.c \
                          pacemaker.c handler.c
 
+if BUILD_TIMER_C
+boothd_SOURCES += timer.c
+endif
+
 boothd_LDFLAGS         = $(OS_DYFLAGS) -L./
 boothd_LDADD           = -lplumb -lplumbgpl -lz -lm
 boothd_CPPFLAGS                = $(GLIB_CFLAGS)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/config.h new/booth/src/config.h
--- old/booth/src/config.h      2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/config.h      2014-07-03 17:11:10.000000000 +0200
@@ -22,6 +22,7 @@
 
 #include <stdint.h>
 #include "booth.h"
+#include "timer.h"
 #include "raft.h"
 #include "transport.h"
 
@@ -73,7 +74,7 @@
        server_state_e next_state;
 
        /** When something has to be done */
-       struct timeval next_cron;
+       timetype next_cron;
 
        /** Current leader. This is effectively the log[] in Raft. */
        struct booth_site *leader;
@@ -231,12 +232,4 @@
 
 const char *type_to_string(int type);
 
-
-#include <stdio.h>
-#define R(tk_) do { if (ANYDEBUG) printf("## %12s:%3d state %s, %d, " \
-       "leader %s, exp %s", __FILE__, __LINE__, \
-       state_to_string(tk_->state), tk_->current_term, \
-       site_string(tk_->leader), ctime(&tk_->term_expires)); } while(0)
-
-
 #endif /* _CONFIG_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/handler.c new/booth/src/handler.c
--- old/booth/src/handler.c     2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/handler.c     2014-07-03 17:11:10.000000000 +0200
@@ -47,7 +47,7 @@
                return 0;
 
        assert(synchronous);
-       sprintf(expires, "%" PRId64, (int64_t)(tk->term_expires));
+       sprintf(expires, "%" PRId64, (int64_t)wall_ts(tk->term_expires));
 
        rv = setenv("BOOTH_TICKET", tk->name, 1) ||
                setenv("BOOTH_LOCAL", local->addr_string, 1) ||
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/inline-fn.h new/booth/src/inline-fn.h
--- old/booth/src/inline-fn.h   2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/inline-fn.h   2014-07-03 17:11:10.000000000 +0200
@@ -23,6 +23,7 @@
 #include <sys/time.h>
 #include <assert.h>
 #include <string.h>
+#include "timer.h"
 #include "config.h"
 #include "transport.h"
 
@@ -44,7 +45,7 @@
 {
        int left;
 
-       left = tk->term_expires - time(NULL);
+       left = tk->term_expires - get_secs(NULL);
        return (left < 0) ? 0 : left;
 }
 
@@ -140,12 +141,12 @@
 {
        tk->leader = NULL;
        tk->is_granted = 0;
-       time(&tk->term_expires);
+       get_secs(&tk->term_expires);
 }
 
 static inline int disown_if_expired(struct ticket_config *tk)
 {
-       if (time(NULL) >= tk->term_expires ||
+       if (get_secs(NULL) >= tk->term_expires ||
                        !tk->leader) {
                disown_ticket(tk);
                return 1;
@@ -212,36 +213,6 @@
 }
 
 
-static inline double timeval_to_float(struct timeval tv)
-{
-       return tv.tv_sec + tv.tv_usec*(double)1.0e-6;
-}
-
-static inline int timeval_msec(struct timeval tv)
-{
-       int m;
-
-       m = tv.tv_usec / 1000;
-       if (m >= 1000)
-               m = 999;
-       return m;
-}
-
-
-static inline int timeval_compare(struct timeval tv1, struct timeval tv2)
-{
-       if (tv1.tv_sec < tv2.tv_sec)
-               return -1;
-       if (tv1.tv_sec > tv2.tv_sec)
-               return +1;
-       if (tv1.tv_usec < tv2.tv_usec)
-               return -1;
-       if (tv1.tv_usec > tv2.tv_usec)
-               return +1;
-       return 0;
-}
-
-
 static inline time_t next_vote_starts_at(struct ticket_config *tk)
 {
        time_t half_exp, retries_needed, t;
@@ -272,7 +243,7 @@
        if (!when)
                return 0;
 
-       time(&now);
+       get_secs(&now);
        return when <= now;
 }
 
@@ -282,7 +253,7 @@
        tk->retry_number = 0;
        tk->acks_expected = reply_type;
        tk->acks_received = local->bitmask;
-       tk->req_sent_at  = time(NULL);
+       tk->req_sent_at  = get_secs(NULL);
        tk->ticket_updated = 0;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/main.c new/booth/src/main.c
--- old/booth/src/main.c        2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/main.c        2014-07-03 17:11:10.000000000 +0200
@@ -46,6 +46,7 @@
 #include <netdb.h>
 #include <arpa/inet.h>
 #include <sys/types.h>
+#include "b_config.h"
 #include "log.h"
 #include "booth.h"
 #include "config.h"
@@ -55,6 +56,7 @@
 #include "ticket.h"
 
 #define RELEASE_VERSION                "0.2.0"
+#define RELEASE_STR    RELEASE_VERSION " (build " BOOTH_BUILD_VERSION ")"
 
 #define CLIENT_NALLOC          32
 
@@ -456,10 +458,9 @@
                goto fail;
        }
 
-       if (cl.type == ARBITRATOR)
-               log_info("BOOTH arbitrator daemon started");
-       else if (cl.type == SITE)
-               log_info("BOOTH cluster site daemon started");
+       log_info("BOOTH %s daemon started, node id is 0x%08X (%d).",
+               type_to_string(local->type),
+                       local->site_id, local->site_id);
 
        while (1) {
                rv = poll(pollfds, client_maxi + 1, poll_timeout);
@@ -828,7 +829,6 @@
 
 #define OPTION_STRING          "c:Dl:t:s:FhS"
 
-
 void safe_copy(char *dest, char *value, size_t buflen, const char 
*description) {
        int content_len = buflen - 1;
 
@@ -881,8 +881,7 @@
 
        if (!strcmp(arg1, "version") || !strcmp(arg1, "--version") ||
                        !strcmp(arg1, "-V")) {
-               printf("%s %s (built %s %s)\n",
-                               argv[0], RELEASE_VERSION, __DATE__, __TIME__);
+               printf("%s %s\n", argv[0], RELEASE_STR);
                exit(EXIT_SUCCESS);
        }
 
@@ -1264,9 +1263,8 @@
        cl_log_set_facility(HA_LOG_FACILITY);
        cl_inherit_logging_environment(0);
 
-       log_info("BOOTH %s daemon is starting, node id is 0x%08X (%d).",
-                       type_to_string(local->type),
-                       local->site_id, local->site_id);
+       log_info("BOOTH %s %s daemon is starting",
+                       type_to_string(local->type), RELEASE_STR);
 
        signal(SIGUSR1, (__sighandler_t)tickets_log_info);
        signal(SIGTERM, (__sighandler_t)sig_exit_handler);
@@ -1328,7 +1326,7 @@
        int rv;
 
        init_set_proc_title(argc, argv, envp);
-       time(&start_time);
+       get_secs(&start_time);
 
        memset(&cl, 0, sizeof(cl));
        strncpy(cl.configfile,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/pacemaker.c new/booth/src/pacemaker.c
--- old/booth/src/pacemaker.c   2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/pacemaker.c   2014-07-03 17:11:10.000000000 +0200
@@ -134,7 +134,7 @@
                         grant < 0 ? "-r" :
                         ""),
                        (int32_t)get_node_id(tk->leader),
-                       (int64_t)tk->term_expires,
+                       (int64_t)wall_ts(tk->term_expires),
                        (int64_t)tk->current_term);
 
        rv = system(cmd);
@@ -225,7 +225,7 @@
        /* Always try to store *each* attribute, even if there's an error
         * for one of them. */
        rv = crm_ticket_set(tk, "owner", (int32_t)get_node_id(tk->leader));
-       rv = crm_ticket_set(tk, "expires", tk->term_expires)  || rv;
+       rv = crm_ticket_set(tk, "expires", wall_ts(tk->term_expires))  || rv;
        rv = crm_ticket_set(tk, "term", tk->current_term)     || rv;
 
        if (rv)
@@ -299,7 +299,7 @@
 
        rv = crm_ticket_get(tk, "expires", &v);
        if (!rv) {
-               tk->term_expires = v;
+               tk->term_expires = unwall_ts(v);
        }
 
        rv = crm_ticket_get(tk, "term", &v);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/raft.c new/booth/src/raft.c
--- old/booth/src/raft.c        2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/raft.c        2014-07-03 17:11:10.000000000 +0200
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <arpa/inet.h>
 #include "booth.h"
+#include "timer.h"
 #include "transport.h"
 #include "inline-fn.h"
 #include "config.h"
@@ -104,7 +105,7 @@
                site_string(sender),
                ntohl(msg->ticket.term), ntohl(msg->ticket.term_valid_for));
        duration = min(tk->term_duration, ntohl(msg->ticket.term_valid_for));
-       tk->term_expires = time(NULL) + duration;
+       tk->term_expires = get_secs(NULL) + duration;
        update_term_from_msg(tk, msg);
 }
 
@@ -112,7 +113,7 @@
 static void copy_ticket_from_msg(struct ticket_config *tk,
                struct boothc_ticket_msg *msg)
 {
-       tk->term_expires = time(NULL) + ntohl(msg->ticket.term_valid_for);
+       tk->term_expires = get_secs(NULL) + ntohl(msg->ticket.term_valid_for);
        tk->current_term = ntohl(msg->ticket.term);
 }
 
@@ -122,6 +123,7 @@
        copy_ticket_from_msg(tk, msg);
        tk->state = ST_FOLLOWER;
        tk->delay_commit = 0;
+       tk->in_election = 0;
        /* if we're following and the ticket was granted here
         * then commit to CIB right away (we're probably restarting)
         */
@@ -137,7 +139,7 @@
        tk->leader = local;
        tk->state = ST_LEADER;
 
-       tk->term_expires = time(NULL) + tk->term_duration;
+       tk->term_expires = get_secs(NULL) + tk->term_duration;
        tk->election_end = 0;
        tk->voted_for = NULL;
 
@@ -207,12 +209,13 @@
        time_t now;
        struct booth_site *new_leader;
 
-       now = time(NULL);
+       now = get_secs(NULL);
        if (now > tk->election_end) {
                /* This is previous election timed out */
-               tk_log_info("election timed out");
+               tk_log_info("elections finished");
        }
 
+       tk->in_election = 0;
        new_leader = majority_votes(tk);
        if (new_leader == local) {
                tk_log_info("granted successfully here");
@@ -222,7 +225,9 @@
                                site_string(new_leader));
        } else {
                tk_log_info("nobody won elections, new elections");
-               new_election(tk, NULL, is_tie(tk), OR_AGAIN);
+               if (!new_election(tk, NULL, is_tie(tk), OR_AGAIN)) {
+                       ticket_activate_timeout(tk);
+               }
        }
 }
 
@@ -316,9 +321,6 @@
        /* got heartbeat, no rejects expected anymore */
        tk->expect_more_rejects = 0;
 
-       /* and certainly not in election */
-       tk->in_election = 0;
-
        /* Needed? */
        newer_term(tk, sender, leader, msg, 0);
 
@@ -461,7 +463,12 @@
                        (tk->state == ST_FOLLOWER || tk->state == 
ST_CANDIDATE)) {
                tk_log_info("%s wants to give the ticket away",
                        site_string(tk->leader));
-               schedule_election(tk, OR_STEPDOWN);
+               reset_ticket(tk);
+               tk->state = ST_FOLLOWER;
+               if (local->type == SITE) {
+                       ticket_write(tk);
+                       schedule_election(tk, OR_STEPDOWN);
+               }
                return 0;
        }
 
@@ -534,7 +541,7 @@
                                                "we'll backup a bit",
                                                site_string(sender));
                        } else {
-                               tk_log_warn("%s unexpecetedly rejects 
elections",
+                               tk_log_warn("%s unexpectedly rejects elections",
                                                site_string(sender));
                        }
                } else {
@@ -688,11 +695,11 @@
        if (local->type != SITE)
                return 0;
 
-       time(&now);
+       get_secs(&now);
        tk_log_debug("start new election?, now=%" PRIi64 ", end %" PRIi64,
-                       (int64_t)now, (int64_t)(tk->election_end));
+                       (int64_t)wall_ts(now), 
(int64_t)(wall_ts(tk->election_end)));
        if (now < tk->election_end)
-               return 0;
+               return 1;
 
        /* §5.2 */
        /* If there was _no_ answer, don't keep incrementing the term number
@@ -711,6 +718,7 @@
 
        tk->term_expires = 0;
        tk->election_end = now + tk->timeout;
+       tk->in_election = 1;
 
        tk_log_info("starting new election (term=%d)",
                        tk->current_term);
@@ -889,7 +897,8 @@
                break;
        case OP_UPDATE:
                if (((tk->leader != local && tk->leader == leader) || 
!is_owned(tk)) &&
-                               tk->state == ST_FOLLOWER) {
+                               (tk->state == ST_INIT || tk->state == 
ST_FOLLOWER ||
+                               tk->state == ST_CANDIDATE)) {
                        rv = process_UPDATE(tk, sender, leader, msg);
                } else {
                        tk_log_warn("unexpected message %s, from %s",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/ticket.c new/booth/src/ticket.c
--- old/booth/src/ticket.c      2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/ticket.c      2014-07-03 17:11:10.000000000 +0200
@@ -165,7 +165,7 @@
        if (is_owned(tk))
                return RLT_OVERGRANT;
 
-       tk->delay_commit = time(NULL) +
+       tk->delay_commit = get_secs(NULL) +
                        tk->term_duration + tk->acquire_after;
 
        if (options & OPT_IMMEDIATE) {
@@ -214,6 +214,7 @@
        char pending_str[64];
        char *data, *cp;
        int i, alloc;
+       time_t ts;
 
        *pdata = NULL;
        *len = 0;
@@ -226,17 +227,19 @@
 
        cp = data;
        foreach_ticket(i, tk) {
-               if (tk->term_expires != 0)
+               if (tk->term_expires != 0) {
+                       ts = wall_ts(tk->term_expires);
                        strftime(timeout_str, sizeof(timeout_str), "%F %T",
-                                       localtime(&tk->term_expires));
-               else
+                                       localtime(&ts));
+               } else
                        strcpy(timeout_str, "N/A");
 
-               if (tk->leader == local && tk->delay_commit > time(NULL)) {
+               if (tk->leader == local && tk->delay_commit > get_secs(NULL)) {
+                       ts = wall_ts(tk->delay_commit);
                        strcpy(pending_str, " (commit pending until ");
                        strftime(pending_str + strlen(" (commit pending until 
"),
                                        sizeof(pending_str) - strlen(" (commit 
pending until ") - 1,
-                                       "%F %T", localtime(&tk->delay_commit));
+                                       "%F %T", localtime(&ts));
                        strcat(pending_str, ")");
                } else
                        *pending_str = '\0';
@@ -281,7 +284,7 @@
        const char *where_granted = "\0";
        char buff[64];
 
-       valid = (tk->term_expires >= time(NULL));
+       valid = (tk->term_expires >= get_secs(NULL));
 
        if (tk->leader == local) {
                where_granted = "granted here";
@@ -505,14 +508,14 @@
        if (!tk->delay_commit)
                return 0;
 
-       if (tk->delay_commit <= time(NULL) ||
+       if (tk->delay_commit <= get_secs(NULL) ||
                        all_sites_replied(tk)) {
                tk_log_debug("ticket delay commit expired");
                tk->delay_commit = 0;
                return 0;
        } else {
                tk_log_debug("delay ticket commit for %ds",
-                               (int)(tk->delay_commit - time(NULL)));
+                               (int)(tk->delay_commit - get_secs(NULL)));
        }
 
        return 1;
@@ -532,7 +535,7 @@
 
        if (tk->ticket_updated < 1) {
                tk->ticket_updated = 1;
-               tk->term_expires = time(NULL) + tk->term_duration;
+               tk->term_expires = get_secs(NULL) + tk->term_duration;
                rv = ticket_broadcast(tk, OP_UPDATE, OP_ACK, RLT_SUCCESS, 0);
        }
 
@@ -545,7 +548,7 @@
                        if (tk->retry_number == 1)
                                tk_log_info("delaying ticket commit to CIB for 
%ds "
                                        "(or all sites are reached)",
-                                       (int)(tk->delay_commit - time(NULL)));
+                                       (int)(tk->delay_commit - 
get_secs(NULL)));
                }
        }
 
@@ -650,68 +653,49 @@
        extern time_t start_time;
 
        return tk->start_postpone &&
-               ((time(NULL) - start_time) < tk->timeout);
+               ((get_secs(NULL) - start_time) < tk->timeout);
 }
 
-static void ticket_cron(struct ticket_config *tk)
+static void process_next_state(struct ticket_config *tk)
 {
-       time_t now;
-
-       now = time(NULL);
-
-       /* don't process the tickets too early */
-       if (postpone_ticket_processing(tk)) {
-               tk_log_debug("ticket processing postponed (start_postpone=%d)",
-                               tk->start_postpone);
-               /* but run again soon */
-               ticket_activate_timeout(tk);
-               return;
-       }
-
-       if (tk->acks_expected == OP_MY_INDEX) {
+       switch(tk->next_state) {
+       case ST_LEADER:
+               reacquire_ticket(tk);
+               break;
+       case ST_INIT:
                no_resends(tk);
+               start_revoke_ticket(tk);
+               break;
+       /* wanting to be follower is not much of an ambition; no
+        * processing, just return; don't reset start_postpone until
+        * we got some replies to status */
+       case ST_FOLLOWER:
+               return;
+       default:
+               break;
        }
+       tk->start_postpone = 0;
+}
 
-       /* wanting to be follower is not much of an ambition */
-       if (tk->next_state && tk->next_state != ST_FOLLOWER) {
-               switch(tk->next_state) {
-               case ST_LEADER:
-                       if (tk->state == ST_LEADER) {
-                               disown_ticket(tk);
-                               new_election(tk, NULL, 1, OR_SPLIT);
-                       } else {
-                               reacquire_ticket(tk);
-                       }
-                       break;
-               case ST_INIT:
-                       no_resends(tk);
-                       start_revoke_ticket(tk);
-                       break;
-               default:
-                       break;
-               }
-               tk->start_postpone = 0;
-               goto out;
+static void ticket_lost(struct ticket_config *tk)
+{
+       if (tk->leader != local) {
+               tk_log_warn("lost at %s", site_string(tk->leader));
+       } else {
+               tk_log_warn("lost majority (revoking locally)");
        }
 
-       /* Has an owner, has an expiry date, and expiry date in the past?
-        * Losing the ticket must happen in _every_ state. */
-       if (!tk->in_election &&
-                       tk->term_expires &&
-                       is_owned(tk) &&
-                       now >= tk->term_expires) {
-
-               if (tk->leader != local) {
-                       tk_log_warn("lost at %s", site_string(tk->leader));
-               } else {
-                       tk_log_warn("lost majority (revoking locally)");
-               }
-
-               tk->lost_leader = tk->leader;
+       tk->lost_leader = tk->leader;
+       reset_ticket(tk);
+       tk->state = ST_FOLLOWER;
+       if (local->type == SITE) {
+               ticket_write(tk);
                schedule_election(tk, OR_TKT_LOST);
-               goto out;
        }
+}
 
+static void next_action(struct ticket_config *tk)
+{
        switch(tk->state) {
        case ST_INIT:
                /* init state, handle resends for ticket revoke */
@@ -726,14 +710,23 @@
                tk_log_debug("leader: %s, voted_for: %s",
                                site_string(tk->leader),
                                site_string(tk->voted_for));
-               if (!tk->leader && !tk->voted_for) {
-                       disown_ticket(tk);
-                       new_election(tk, NULL, 1, OR_AGAIN);
+               if (!tk->leader) {
+                       if (!tk->voted_for) {
+                               disown_ticket(tk);
+                               if (!new_election(tk, NULL, 1, OR_AGAIN)) {
+                                       ticket_activate_timeout(tk);
+                               }
+                       } else {
+                               /* we should restart elections in case nothing
+                                * happens in the meantime */
+                               tk->in_election = 0;
+                               ticket_activate_timeout(tk);
+                       }
                }
                break;
 
        case ST_CANDIDATE:
-               /* §5.2 */
+               /* elections timed out? */
                elections_end(tk);
                break;
 
@@ -753,10 +746,52 @@
        default:
                break;
        }
+}
+
+static void ticket_cron(struct ticket_config *tk)
+{
+       time_t now;
+
+       /* don't process the tickets too early after start */
+       if (postpone_ticket_processing(tk)) {
+               tk_log_debug("ticket processing postponed (start_postpone=%d)",
+                               tk->start_postpone);
+               /* but run again soon */
+               ticket_activate_timeout(tk);
+               return;
+       }
+
+       /* no need for status resends, we hope we got at least one
+        * my_index back */
+       if (tk->acks_expected == OP_MY_INDEX) {
+               no_resends(tk);
+       }
+
+       /* after startup, we need to decide what to do based on the
+        * current ticket state; tk->next_state has a hint
+        * also used for revokes which had to be delayed
+        */
+       if (tk->next_state) {
+               process_next_state(tk);
+               goto out;
+       }
+
+       /* Has an owner, has an expiry date, and expiry date in the past?
+        * Losing the ticket must happen in _every_ state. */
+       now = get_secs(NULL);
+       if (!tk->in_election &&
+                       tk->term_expires &&
+                       is_owned(tk) &&
+                       now >= tk->term_expires) {
+               ticket_lost(tk);
+               goto out;
+       }
+
+       next_action(tk);
 
 out:
        tk->next_state = 0;
-       if (tk->update_cib)
+       if (!tk->in_election && tk->update_cib)
                ticket_write(tk);
 }
 
@@ -765,20 +800,12 @@
 {
        struct ticket_config *tk;
        int i;
-       struct timeval now, last_cron;
-       float sec_until;
+       timetype now, last_cron;
 
-       gettimeofday(&now, NULL);
+       get_time(&now);
 
        foreach_ticket(i, tk) {
-               sec_until = timeval_to_float(tk->next_cron) - 
timeval_to_float(now);
-               if (0)
-                       tk_log_debug("next cron %" PRIx64 ".%03d, "
-                                       "now %" PRIx64 "%03d, in %f",
-                                       (uint64_t)tk->next_cron.tv_sec, 
timeval_msec(tk->next_cron),
-                                       (uint64_t)now.tv_sec, timeval_msec(now),
-                                       sec_until);
-               if (sec_until > 0.0)
+               if (time_cmp(&tk->next_cron, &now, >))
                        continue;
 
                tk_log_debug("ticket cron");
@@ -786,7 +813,7 @@
 
                last_cron = tk->next_cron;
                ticket_cron(tk);
-               if (!timercmp(&last_cron, &tk->next_cron, !=)) {
+               if (!time_cmp(&last_cron, &tk->next_cron, !=)) {
                        tk_log_debug("nobody set ticket wakeup");
                        set_ticket_wakeup(tk);
                }
@@ -799,8 +826,10 @@
 {
        struct ticket_config *tk;
        int i;
+       time_t ts;
 
        foreach_ticket(i, tk) {
+               ts = wall_ts(tk->term_expires);
                tk_log_info("state '%s' "
                                "term %d "
                                "leader %s "
@@ -808,7 +837,7 @@
                                state_to_string(tk->state),
                                tk->current_term,
                                ticket_leader_string(tk),
-                               ctime(&tk->term_expires));
+                               ctime(&ts));
        }
 }
 
@@ -896,23 +925,22 @@
 
 static void log_next_wakeup(struct ticket_config *tk)
 {
-       struct timeval now, res;
+       timetype now, res;
 
-       gettimeofday(&now, NULL);
-       timersub(&tk->next_cron, &now, &res);
-       tk_log_debug("set ticket wakeup in %d.%06d",
-               (int)res.tv_sec, (int)res.tv_usec);
+       get_time(&now);
+       time_sub(&tk->next_cron, &now, &res);
+       tk_log_debug("set ticket wakeup in %d.%03d",
+               (int)res.tv_sec, (int)msecs(res));
 }
 
 /* New vote round; §5.2 */
 /* delay the next election start for up to 1s */
 void add_random_delay(struct ticket_config *tk)
 {
-       struct timeval delay, tv;
+       timetype delay, tv;
 
-       delay.tv_sec = 0;
-       delay.tv_usec = cl_rand_from_interval(0, 1000000);
-       timeradd(&tk->next_cron, &delay, &tv);
+       rand_time_ms(delay, 1000);
+       time_add(&tk->next_cron, &delay, &tv);
        ticket_next_cron_at(tk, tv);
        if (ANYDEBUG) {
                log_next_wakeup(tk);
@@ -921,11 +949,11 @@
 
 void set_ticket_wakeup(struct ticket_config *tk)
 {
-       struct timeval tv, now;
+       timetype tv, now, res;
 
        /* At least every hour, perhaps sooner. */
        ticket_next_cron_in(tk, 3600);
-       gettimeofday(&now, NULL);
+       get_time(&now);
 
        switch (tk->state) {
        case ST_LEADER:
@@ -934,12 +962,13 @@
                tv = now;
                tv.tv_sec = next_vote_starts_at(tk);
 
-               /* If timestamp is in the past, wakeup at the expiry
-                * time. */
-               if (timeval_compare(tv, now) <= 0) {
-                       tk_log_debug("next ts in the past (%f)",
-                               timeval_to_float(tv) - timeval_to_float(now));
-                       tv.tv_sec = tk->term_expires;
+               /* If timestamp is in the past, wakeup in
+                * one second. */
+               if (time_cmp(&tv, &now, <)) {
+                       time_sub(&tv, &now, &res);
+                       tk_log_debug("next ts in the past (%d.%03d)",
+                               (int)res.tv_sec, (int)msecs(res));
+                       tv.tv_sec = now.tv_sec + 1;
                }
 
                ticket_next_cron_at(tk, tv);
@@ -981,14 +1010,11 @@
 
 void schedule_election(struct ticket_config *tk, cmd_reason_t reason)
 {
-       reset_ticket(tk);
-       tk->state = ST_FOLLOWER;
        if (local->type != SITE)
                return;
 
        tk->election_reason = reason;
-       ticket_write(tk);
-       gettimeofday(&tk->next_cron, NULL);
+       get_time(&tk->next_cron);
        /* introduce a short delay before starting election */
        add_random_delay(tk);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/ticket.h new/booth/src/ticket.h
--- old/booth/src/ticket.h      2014-06-26 19:31:25.000000000 +0200
+++ new/booth/src/ticket.h      2014-07-03 17:11:10.000000000 +0200
@@ -24,6 +24,7 @@
 #include <sys/time.h>
 #include <math.h>
 
+#include "timer.h"
 #include "config.h"
 #include "log.h"
 
@@ -80,24 +81,23 @@
 void add_random_delay(struct ticket_config *tk);
 void schedule_election(struct ticket_config *tk, cmd_reason_t reason);
 
-static inline void ticket_next_cron_at(struct ticket_config *tk, struct 
timeval when)
+static inline void ticket_next_cron_at(struct ticket_config *tk, timetype when)
 {
        tk->next_cron = when;
 }
 
 static inline void ticket_next_cron_at_coarse(struct ticket_config *tk, time_t 
when)
 {
+       memset(&tk->next_cron, 0, sizeof(tk->next_cron));
        tk->next_cron.tv_sec  = when;
-       tk->next_cron.tv_usec = 0;
 }
 
-static inline void ticket_next_cron_in(struct ticket_config *tk, float seconds)
+static inline void ticket_next_cron_in(struct ticket_config *tk, time_t 
seconds)
 {
-       struct timeval tv;
+       timetype tv;
 
-       gettimeofday(&tv, NULL);
-       tv.tv_sec += trunc(seconds);
-       tv.tv_usec += (seconds - trunc(seconds)) * 1e6;
+       get_time(&tv);
+       tv.tv_sec += seconds;
 
        ticket_next_cron_at(tk, tv);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/timer.c new/booth/src/timer.c
--- old/booth/src/timer.c       1970-01-01 01:00:00.000000000 +0100
+++ new/booth/src/timer.c       2014-07-03 17:11:10.000000000 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 Dejan Muhamedagic <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "timer.h"
+
+void time_sub(struct timespec *a, struct timespec *b, struct timespec *res)
+{
+       if (a->tv_nsec < b->tv_nsec) {
+               res->tv_sec = a->tv_sec - b->tv_sec - 1;
+               res->tv_nsec = a->tv_nsec + (1000000000 - b->tv_nsec);
+       } else {
+               res->tv_sec = a->tv_sec - b->tv_sec;
+               res->tv_nsec = a->tv_nsec - b->tv_nsec;
+       }
+}
+
+
+void time_add(struct timespec *a, struct timespec *b, struct timespec *res)
+{
+       res->tv_nsec = (a->tv_nsec + b->tv_nsec) % 1000000000;
+       res->tv_sec = a->tv_sec + b->tv_sec + ((a->tv_nsec + b->tv_nsec) / 
1000000000);
+}
+
+time_t get_secs(time_t *p)
+{
+       struct timespec tv;
+       time_t secs;
+
+       get_time(&tv);
+       secs = tv.tv_sec;
+       if (p)
+               *p = secs;
+       return secs;
+}
+
+/* time booth_clk_t is a time since boot or similar, return
+ * something humans can understand */
+time_t wall_ts(time_t booth_clk_t)
+{
+       struct timespec booth_clk_now, now_tv, res;
+       struct timeval now;
+
+       get_time(&booth_clk_now);
+       gettimeofday(&now, NULL);
+       TIMEVAL_TO_TIMESPEC(&now, &now_tv);
+       time_sub(&now_tv, &booth_clk_now, &res);
+       return booth_clk_t + res.tv_sec;
+}
+
+/* time t is wall clock time, convert to time compatible
+ * with our clock_gettime clock */
+time_t unwall_ts(time_t t)
+{
+       struct timespec booth_clk_now, now_tv, res;
+       struct timeval now;
+
+       get_time(&booth_clk_now);
+       gettimeofday(&now, NULL);
+       TIMEVAL_TO_TIMESPEC(&now, &now_tv);
+       time_sub(&now_tv, &booth_clk_now, &res);
+       return t - res.tv_sec;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/src/timer.h new/booth/src/timer.h
--- old/booth/src/timer.h       1970-01-01 01:00:00.000000000 +0100
+++ new/booth/src/timer.h       2014-07-03 17:11:10.000000000 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 Dejan Muhamedagic <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _TIMER_H
+#define _TIMER_H
+
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#if _POSIX_TIMERS > 0
+
+#if defined(CLOCK_MONOTONIC)
+#      define BOOTH_CLOCK CLOCK_MONOTONIC
+#else
+#      define BOOTH_CLOCK CLOCK_REALTIME
+#endif
+
+typedef struct timespec timetype;
+
+#define get_time(p) clock_gettime(BOOTH_CLOCK, p)
+
+#define time_cmp(a, b, CMP)           \
+  (((a)->tv_sec == (b)->tv_sec) ?     \
+   ((a)->tv_nsec CMP (b)->tv_nsec) :  \
+   ((a)->tv_sec CMP (b)->tv_sec))
+
+void time_sub(struct timespec *a, struct timespec *b, struct timespec *res);
+void time_add(struct timespec *a, struct timespec *b, struct timespec *res);
+time_t get_secs(time_t *p);
+time_t wall_ts(time_t t);
+time_t unwall_ts(time_t t);
+
+#define msecs(tv) ((tv).tv_nsec/1000000)
+
+/* random time from 0 to t milliseconds */
+#define rand_time_ms(tv, t) do { \
+       tv.tv_sec = 0; \
+       tv.tv_nsec = t * cl_rand_from_interval(0, 1000000); \
+       } while(0)
+
+#else
+
+typedef struct timeval timetype;
+#define get_time(p) gettimeofday(p, NULL)
+#define time_sub timersub
+#define time_add timeradd
+#define time_cmp timercmp
+#define get_secs time
+
+#define msecs(tv) ((tv).tv_usec/1000)
+
+/* random time from 0 to t milliseconds */
+#define rand_time_ms(tv, t) do { \
+       tv.tv_sec = 0; \
+       tv.tv_usec = t * cl_rand_from_interval(0, 1000); \
+       } while(0)
+
+#define wall_ts(t) (t)
+#define unwall_ts(t) (t)
+
+#endif
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/booth/test/live_test.sh new/booth/test/live_test.sh
--- old/booth/test/live_test.sh 2014-06-26 19:31:25.000000000 +0200
+++ new/booth/test/live_test.sh 2014-07-03 17:11:10.000000000 +0200
@@ -46,8 +46,17 @@
 iprules=/usr/share/booth/tests/test/booth_path
 : ${HA_LOGFACILITY:="syslog"}
 
+get_site() {
+       local n=$1
+       echo $sites | awk '{print $'$n'}'
+}
+
 logmsg() {
-       logger -t "BOOTHTEST" -p $HA_LOGFACILITY.info -- $@
+       if [ "$WE_SERVER" ]; then
+               logger -t "BOOTHTEST" -p $HA_LOGFACILITY.info -- $@
+       else
+               ssh `get_site 1` logger -t "BOOTHTEST" -p $HA_LOGFACILITY.info 
-- $@
+       fi
 }
 
 ext_prog_log() {
@@ -105,7 +114,7 @@
 runcmd() {
        local h=$1 rc
        shift 1
-       logmsg "$h: running '$@'"
+       echo "$h: running '$@'" | logmsg
        if ip a l | fgrep -wq $h; then
                $@
        else
@@ -180,6 +189,13 @@
        wait $procs
        wait_timeout
 }
+is_we_server() {
+       local h
+       for h in $sites $arbitrators; do
+               ip a l | fgrep -wq $h && return
+       done
+       return 1
+}
 sync_conf() {
        local h rc=0
        for h in $sites $arbitrators; do
@@ -241,10 +257,6 @@
        h=`echo $arbitrators | awk '{print $'$n'}'`
        runcmd $h $@
 }
-get_site() {
-       local n=$1
-       echo $sites | awk '{print $'$n'}'
-}
 
 get_port() {
        grep "^port" | 
@@ -259,7 +271,10 @@
 }
 
 break_external_prog() {
-       echo "location __pref_booth_live_test `get_rsc` rule -inf: defined 
#uname" | run_site 1 crm configure
+       run_site $1 crm configure "location $PREFNAME `get_rsc` rule -inf: 
defined \#uname"
+}
+show_pref() {
+       run_site $1 crm configure show $PREFNAME > /dev/null
 }
 repair_external_prog() {
        run_site $1 crm configure delete __pref_booth_live_test
@@ -494,14 +509,14 @@
        start_ts=`date +%s`
        echo -n "Testing: $1... "
        can_run_test $1 || return 0
-       logmsg "starting booth test $1 ..."
+       echo "starting booth test $1 ..." | logmsg
        setup_netem
        test_$1 && check_$1
        rc=$?
        end_time=`date`
        end_ts=`date +%s`
        reset_netem_env
-       logmsg "finished booth test $1 (exit code $rc)"
+       echo "finished booth test $1 (exit code $rc)" | logmsg
        is_function recover_$1 && recover_$1
        sleep 3
        all_booth_status
@@ -547,6 +562,9 @@
 PS4='+ `date +"%T"`: '
 set -x
 
+WE_SERVER=""
+is_we_server && WE_SERVER=1
+
 #
 # the tests
 #
@@ -808,6 +826,7 @@
 test_external_prog_failed() {
        grant2site_one
        break_external_prog 1
+       show_pref 1 || return 1
        wait_half_exp
        wait_timeout
 }
@@ -843,11 +862,16 @@
        forall $0 $cnf __netem__ netem_delay ${1:-100}
 }
 
+PREFNAME=__pref_booth_live_test
+
 sync_conf || exit
 restart_booth
 all_booth_status || {
        start_booth
-       all_booth_status || exit
+       all_booth_status || {
+               echo "some booth servers couldn't be started"
+               exit 1
+       }
 }
 revoke_ticket
 

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to